diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2020-04-19 11:10:43 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2020-04-19 12:23:46 +0200 |
commit | 2ee60f02c456f39a80edb2dbfed48c3e0147a7f7 (patch) | |
tree | ca4b9c95c2c1f28dcfd4ecb3307015c7f82603b9 /drawinglayer/source | |
parent | 9df2821e61979dab32390d5c64dd49bee868adbb (diff) |
loplugin:flatten in drawinglayer
Change-Id: Ieb5f682ec627c8d8ddfc286ec0e4422104b4d847
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92494
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'drawinglayer/source')
42 files changed, 4408 insertions, 4416 deletions
diff --git a/drawinglayer/source/geometry/viewinformation2d.cxx b/drawinglayer/source/geometry/viewinformation2d.cxx index a88757416b1b..08a88b23d564 100644 --- a/drawinglayer/source/geometry/viewinformation2d.cxx +++ b/drawinglayer/source/geometry/viewinformation2d.cxx @@ -86,66 +86,65 @@ protected: void impInterpretPropertyValues(const uno::Sequence<beans::PropertyValue>& rViewParameters) { - if (rViewParameters.hasElements()) + if (!rViewParameters.hasElements()) + return; + + const sal_Int32 nCount(rViewParameters.getLength()); + sal_Int32 nExtendedInsert(0); + + // prepare extended information for filtering. Maximum size is nCount + mxExtendedInformation.realloc(nCount); + + for (sal_Int32 a(0); a < nCount; a++) { - const sal_Int32 nCount(rViewParameters.getLength()); - sal_Int32 nExtendedInsert(0); + const beans::PropertyValue& rProp = rViewParameters[a]; - // prepare extended information for filtering. Maximum size is nCount - mxExtendedInformation.realloc(nCount); + if (rProp.Name == g_PropertyName_ReducedDisplayQuality) + { + // extra information; add to filtered information + mxExtendedInformation[nExtendedInsert++] = rProp; - for (sal_Int32 a(0); a < nCount; a++) + // for performance reasons, also cache content locally + bool bSalBool(false); + rProp.Value >>= bSalBool; + mbReducedDisplayQuality = bSalBool; + } + else if (rProp.Name == g_PropertyName_ObjectTransformation) { - const beans::PropertyValue& rProp = rViewParameters[a]; - - if (rProp.Name == g_PropertyName_ReducedDisplayQuality) - { - // extra information; add to filtered information - mxExtendedInformation[nExtendedInsert++] = rProp; - - // for performance reasons, also cache content locally - bool bSalBool(false); - rProp.Value >>= bSalBool; - mbReducedDisplayQuality = bSalBool; - } - else if (rProp.Name == g_PropertyName_ObjectTransformation) - { - css::geometry::AffineMatrix2D aAffineMatrix2D; - rProp.Value >>= aAffineMatrix2D; - basegfx::unotools::homMatrixFromAffineMatrix(maObjectTransformation, - aAffineMatrix2D); - } - else if (rProp.Name == g_PropertyName_ViewTransformation) - { - css::geometry::AffineMatrix2D aAffineMatrix2D; - rProp.Value >>= aAffineMatrix2D; - basegfx::unotools::homMatrixFromAffineMatrix(maViewTransformation, - aAffineMatrix2D); - } - else if (rProp.Name == g_PropertyName_Viewport) - { - css::geometry::RealRectangle2D aViewport; - rProp.Value >>= aViewport; - maViewport = basegfx::unotools::b2DRectangleFromRealRectangle2D(aViewport); - } - else if (rProp.Name == g_PropertyName_Time) - { - rProp.Value >>= mfViewTime; - } - else if (rProp.Name == g_PropertyName_VisualizedPage) - { - rProp.Value >>= mxVisualizedPage; - } - else - { - // extra information; add to filtered information - mxExtendedInformation[nExtendedInsert++] = rProp; - } + css::geometry::AffineMatrix2D aAffineMatrix2D; + rProp.Value >>= aAffineMatrix2D; + basegfx::unotools::homMatrixFromAffineMatrix(maObjectTransformation, + aAffineMatrix2D); + } + else if (rProp.Name == g_PropertyName_ViewTransformation) + { + css::geometry::AffineMatrix2D aAffineMatrix2D; + rProp.Value >>= aAffineMatrix2D; + basegfx::unotools::homMatrixFromAffineMatrix(maViewTransformation, aAffineMatrix2D); + } + else if (rProp.Name == g_PropertyName_Viewport) + { + css::geometry::RealRectangle2D aViewport; + rProp.Value >>= aViewport; + maViewport = basegfx::unotools::b2DRectangleFromRealRectangle2D(aViewport); + } + else if (rProp.Name == g_PropertyName_Time) + { + rProp.Value >>= mfViewTime; + } + else if (rProp.Name == g_PropertyName_VisualizedPage) + { + rProp.Value >>= mxVisualizedPage; + } + else + { + // extra information; add to filtered information + mxExtendedInformation[nExtendedInsert++] = rProp; } - - // extra information size is now known; realloc to final size - mxExtendedInformation.realloc(nExtendedInsert); } + + // extra information size is now known; realloc to final size + mxExtendedInformation.realloc(nExtendedInsert); } void impFillViewInformationFromContent() diff --git a/drawinglayer/source/geometry/viewinformation3d.cxx b/drawinglayer/source/geometry/viewinformation3d.cxx index f59a88fa0071..b3e75bffa6dd 100644 --- a/drawinglayer/source/geometry/viewinformation3d.cxx +++ b/drawinglayer/source/geometry/viewinformation3d.cxx @@ -122,93 +122,93 @@ namespace drawinglayer::geometry // all ViewParameters using UNO API void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters) { - if(rViewParameters.hasElements()) - { - const sal_Int32 nCount(rViewParameters.getLength()); - sal_Int32 nExtendedInsert(0); + if(!rViewParameters.hasElements()) + return; + + const sal_Int32 nCount(rViewParameters.getLength()); + sal_Int32 nExtendedInsert(0); + + // prepare extended information for filtering. Maximum size is nCount + mxExtendedInformation.realloc(nCount); - // prepare extended information for filtering. Maximum size is nCount - mxExtendedInformation.realloc(nCount); + for(sal_Int32 a(0); a < nCount; a++) + { + const beans::PropertyValue& rProp = rViewParameters[a]; - for(sal_Int32 a(0); a < nCount; a++) + if(rProp.Name == getNamePropertyObjectTransformation()) { - const beans::PropertyValue& rProp = rViewParameters[a]; - - if(rProp.Name == getNamePropertyObjectTransformation()) - { - css::geometry::AffineMatrix3D aAffineMatrix3D; - rProp.Value >>= aAffineMatrix3D; - maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); - } - else if(rProp.Name == getNamePropertyOrientation()) - { - css::geometry::AffineMatrix3D aAffineMatrix3D; - rProp.Value >>= aAffineMatrix3D; - maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); - } - else if(rProp.Name == getNamePropertyProjection()) - { - // projection may be defined using a frustum in which case the last line of - // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that, - // these four values need to be treated extra - const double f_30(maProjection.get(3, 0)); - const double f_31(maProjection.get(3, 1)); - const double f_32(maProjection.get(3, 2)); - const double f_33(maProjection.get(3, 3)); - - css::geometry::AffineMatrix3D aAffineMatrix3D; - rProp.Value >>= aAffineMatrix3D; - maProjection = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); - - maProjection.set(3, 0, f_30); - maProjection.set(3, 1, f_31); - maProjection.set(3, 2, f_32); - maProjection.set(3, 3, f_33); - } - else if(rProp.Name == getNamePropertyProjection_30()) - { - double f_30(0.0); - rProp.Value >>= f_30; - maProjection.set(3, 0, f_30); - } - else if(rProp.Name == getNamePropertyProjection_31()) - { - double f_31(0.0); - rProp.Value >>= f_31; - maProjection.set(3, 1, f_31); - } - else if(rProp.Name == getNamePropertyProjection_32()) - { - double f_32(0.0); - rProp.Value >>= f_32; - maProjection.set(3, 2, f_32); - } - else if(rProp.Name == getNamePropertyProjection_33()) - { - double f_33(1.0); - rProp.Value >>= f_33; - maProjection.set(3, 3, f_33); - } - else if(rProp.Name == getNamePropertyDeviceToView()) - { - css::geometry::AffineMatrix3D aAffineMatrix3D; - rProp.Value >>= aAffineMatrix3D; - maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); - } - else if(rProp.Name == getNamePropertyTime()) - { - rProp.Value >>= mfViewTime; - } - else - { - // extra information; add to filtered information - mxExtendedInformation[nExtendedInsert++] = rProp; - } + css::geometry::AffineMatrix3D aAffineMatrix3D; + rProp.Value >>= aAffineMatrix3D; + maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); + } + else if(rProp.Name == getNamePropertyOrientation()) + { + css::geometry::AffineMatrix3D aAffineMatrix3D; + rProp.Value >>= aAffineMatrix3D; + maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); + } + else if(rProp.Name == getNamePropertyProjection()) + { + // projection may be defined using a frustum in which case the last line of + // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that, + // these four values need to be treated extra + const double f_30(maProjection.get(3, 0)); + const double f_31(maProjection.get(3, 1)); + const double f_32(maProjection.get(3, 2)); + const double f_33(maProjection.get(3, 3)); + + css::geometry::AffineMatrix3D aAffineMatrix3D; + rProp.Value >>= aAffineMatrix3D; + maProjection = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); + + maProjection.set(3, 0, f_30); + maProjection.set(3, 1, f_31); + maProjection.set(3, 2, f_32); + maProjection.set(3, 3, f_33); + } + else if(rProp.Name == getNamePropertyProjection_30()) + { + double f_30(0.0); + rProp.Value >>= f_30; + maProjection.set(3, 0, f_30); + } + else if(rProp.Name == getNamePropertyProjection_31()) + { + double f_31(0.0); + rProp.Value >>= f_31; + maProjection.set(3, 1, f_31); + } + else if(rProp.Name == getNamePropertyProjection_32()) + { + double f_32(0.0); + rProp.Value >>= f_32; + maProjection.set(3, 2, f_32); + } + else if(rProp.Name == getNamePropertyProjection_33()) + { + double f_33(1.0); + rProp.Value >>= f_33; + maProjection.set(3, 3, f_33); + } + else if(rProp.Name == getNamePropertyDeviceToView()) + { + css::geometry::AffineMatrix3D aAffineMatrix3D; + rProp.Value >>= aAffineMatrix3D; + maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); + } + else if(rProp.Name == getNamePropertyTime()) + { + rProp.Value >>= mfViewTime; + } + else + { + // extra information; add to filtered information + mxExtendedInformation[nExtendedInsert++] = rProp; } - - // extra information size is now known; realloc to final size - mxExtendedInformation.realloc(nExtendedInsert); } + + // extra information size is now known; realloc to final size + mxExtendedInformation.realloc(nExtendedInsert); } // central method to create a Sequence of PropertyValues containing he complete diff --git a/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx index 00bea0ab10ea..2a1aefafa275 100644 --- a/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx +++ b/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx @@ -33,70 +33,66 @@ namespace drawinglayer::primitive2d void PolyPolygonGraphicPrimitive2D::create2DDecomposition( Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if (!getFillGraphic().isDefault()) + if (getFillGraphic().isDefault()) + return; + + const Graphic& rGraphic = getFillGraphic().getGraphic(); + const GraphicType aType(rGraphic.GetType()); + + // is there a bitmap or a metafile (do we have content)? + if (!(GraphicType::Bitmap == aType || GraphicType::GdiMetafile == aType)) + return; + + const Size aPrefSize(rGraphic.GetPrefSize()); + + // does content have a size? + if (!(aPrefSize.Width() && aPrefSize.Height())) + return; + + // create SubSequence with FillGraphicPrimitive2D based on polygon range + const basegfx::B2DRange aOutRange(getB2DPolyPolygon().getB2DRange()); + const basegfx::B2DHomMatrix aNewObjectTransform( + basegfx::utils::createScaleTranslateB2DHomMatrix(aOutRange.getRange(), + aOutRange.getMinimum())); + Primitive2DReference xSubRef; + + if (aOutRange != getDefinitionRange()) { - const Graphic& rGraphic = getFillGraphic().getGraphic(); - const GraphicType aType(rGraphic.GetType()); - - // is there a bitmap or a metafile (do we have content)? - if (GraphicType::Bitmap == aType || GraphicType::GdiMetafile == aType) - { - const Size aPrefSize(rGraphic.GetPrefSize()); - - // does content have a size? - if (aPrefSize.Width() && aPrefSize.Height()) - { - // create SubSequence with FillGraphicPrimitive2D based on polygon range - const basegfx::B2DRange aOutRange(getB2DPolyPolygon().getB2DRange()); - const basegfx::B2DHomMatrix aNewObjectTransform( - basegfx::utils::createScaleTranslateB2DHomMatrix(aOutRange.getRange(), - aOutRange.getMinimum())); - Primitive2DReference xSubRef; - - if (aOutRange != getDefinitionRange()) - { - // we want to paint (tiled) content which is defined relative to DefinitionRange - // with the same tiling and offset(s) in the target range of the geometry (the - // polygon). The range given in the local FillGraphicAttribute defines the position - // of the graphic in unit coordinates relative to the DefinitionRange. Transform - // this using DefinitionRange to get to the global definition and then with the - // inverse transformation from the target range to go to unit coordinates relative - // to that target coordinate system. - basegfx::B2DRange aAdaptedRange(getFillGraphic().getGraphicRange()); - - const basegfx::B2DHomMatrix aFromDefinitionRangeToGlobal( - basegfx::utils::createScaleTranslateB2DHomMatrix( - getDefinitionRange().getRange(), getDefinitionRange().getMinimum())); - - aAdaptedRange.transform(aFromDefinitionRangeToGlobal); - - basegfx::B2DHomMatrix aFromGlobalToOutRange( - basegfx::utils::createScaleTranslateB2DHomMatrix(aOutRange.getRange(), - aOutRange.getMinimum())); - aFromGlobalToOutRange.invert(); - - aAdaptedRange.transform(aFromGlobalToOutRange); - - const drawinglayer::attribute::FillGraphicAttribute - aAdaptedFillGraphicAttribute(getFillGraphic().getGraphic(), aAdaptedRange, - getFillGraphic().getTiling(), - getFillGraphic().getOffsetX(), - getFillGraphic().getOffsetY()); - - xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, - aAdaptedFillGraphicAttribute); - } - else - { - xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, getFillGraphic()); - } - - // embed to mask primitive - rContainer.push_back( - new MaskPrimitive2D(getB2DPolyPolygon(), Primitive2DContainer{ xSubRef })); - } - } + // we want to paint (tiled) content which is defined relative to DefinitionRange + // with the same tiling and offset(s) in the target range of the geometry (the + // polygon). The range given in the local FillGraphicAttribute defines the position + // of the graphic in unit coordinates relative to the DefinitionRange. Transform + // this using DefinitionRange to get to the global definition and then with the + // inverse transformation from the target range to go to unit coordinates relative + // to that target coordinate system. + basegfx::B2DRange aAdaptedRange(getFillGraphic().getGraphicRange()); + + const basegfx::B2DHomMatrix aFromDefinitionRangeToGlobal( + basegfx::utils::createScaleTranslateB2DHomMatrix(getDefinitionRange().getRange(), + getDefinitionRange().getMinimum())); + + aAdaptedRange.transform(aFromDefinitionRangeToGlobal); + + basegfx::B2DHomMatrix aFromGlobalToOutRange( + basegfx::utils::createScaleTranslateB2DHomMatrix(aOutRange.getRange(), + aOutRange.getMinimum())); + aFromGlobalToOutRange.invert(); + + aAdaptedRange.transform(aFromGlobalToOutRange); + + const drawinglayer::attribute::FillGraphicAttribute aAdaptedFillGraphicAttribute( + getFillGraphic().getGraphic(), aAdaptedRange, getFillGraphic().getTiling(), + getFillGraphic().getOffsetX(), getFillGraphic().getOffsetY()); + + xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, aAdaptedFillGraphicAttribute); } + else + { + xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, getFillGraphic()); + } + + // embed to mask primitive + rContainer.push_back(new MaskPrimitive2D(getB2DPolyPolygon(), Primitive2DContainer{ xSubRef })); } PolyPolygonGraphicPrimitive2D::PolyPolygonGraphicPrimitive2D( diff --git a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx index 19e586359395..d2c8d4a6571a 100644 --- a/drawinglayer/source/primitive2d/animatedprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/animatedprimitive2d.cxx @@ -64,20 +64,20 @@ namespace drawinglayer::primitive2d void AnimatedSwitchPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const { - if(!getChildren().empty()) - { - const double fState(getAnimationEntry().getStateAtTime(rViewInformation.getViewTime())); - const sal_uInt32 nLen(getChildren().size()); - sal_uInt32 nIndex(basegfx::fround(fState * static_cast<double>(nLen))); + if(getChildren().empty()) + return; - if(nIndex >= nLen) - { - nIndex = nLen - 1; - } + const double fState(getAnimationEntry().getStateAtTime(rViewInformation.getViewTime())); + const sal_uInt32 nLen(getChildren().size()); + sal_uInt32 nIndex(basegfx::fround(fState * static_cast<double>(nLen))); - const Primitive2DReference xRef(getChildren()[nIndex], uno::UNO_SET_THROW); - rVisitor.append(xRef); + if(nIndex >= nLen) + { + nIndex = nLen - 1; } + + const Primitive2DReference xRef(getChildren()[nIndex], uno::UNO_SET_THROW); + rVisitor.append(xRef); } // provide unique ID diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx index 71dfe1629085..32c95fb02a66 100644 --- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx @@ -113,138 +113,138 @@ namespace drawinglayer::primitive2d void BorderLinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if (!getStart().equal(getEnd()) && !getBorderLines().empty()) + if (getStart().equal(getEnd()) || getBorderLines().empty()) + return; + + // get data and vectors + basegfx::B2DVector aVector(getEnd() - getStart()); + aVector.normalize(); + const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector)); + const double fFullWidth(getFullWidth()); + double fOffset(fFullWidth * -0.5); + + for(const auto& candidate : maBorderLines) { - // get data and vectors - basegfx::B2DVector aVector(getEnd() - getStart()); - aVector.normalize(); - const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector)); - const double fFullWidth(getFullWidth()); - double fOffset(fFullWidth * -0.5); - - for(const auto& candidate : maBorderLines) + const double fWidth(candidate.getLineAttribute().getWidth()); + + if(!candidate.isGap()) { - const double fWidth(candidate.getLineAttribute().getWidth()); + const basegfx::B2DVector aDeltaY(aPerpendicular * (fOffset + (fWidth * 0.5))); + const basegfx::B2DPoint aStart(getStart() + aDeltaY); + const basegfx::B2DPoint aEnd(getEnd() + aDeltaY); + const bool bStartPerpendicular(rtl::math::approxEqual(candidate.getStartLeft(), candidate.getStartRight())); + const bool bEndPerpendicular(rtl::math::approxEqual(candidate.getEndLeft(), candidate.getEndRight())); - if(!candidate.isGap()) + if(bStartPerpendicular && bEndPerpendicular) { - const basegfx::B2DVector aDeltaY(aPerpendicular * (fOffset + (fWidth * 0.5))); - const basegfx::B2DPoint aStart(getStart() + aDeltaY); - const basegfx::B2DPoint aEnd(getEnd() + aDeltaY); - const bool bStartPerpendicular(rtl::math::approxEqual(candidate.getStartLeft(), candidate.getStartRight())); - const bool bEndPerpendicular(rtl::math::approxEqual(candidate.getEndLeft(), candidate.getEndRight())); - - if(bStartPerpendicular && bEndPerpendicular) + // start and end extends lead to an edge perpendicular to the line, so we can just use + // a PolygonStrokePrimitive2D for representation + addPolygonStrokePrimitive2D( + rContainer, + aStart - (aVector * candidate.getStartLeft()), + aEnd + (aVector * candidate.getEndLeft()), + candidate.getLineAttribute(), + getStrokeAttribute()); + } + else + { + // start and/or end extensions lead to a lineStart/End that is *not* + // perpendicular to the line itself + if(getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen()) { - // start and end extends lead to an edge perpendicular to the line, so we can just use - // a PolygonStrokePrimitive2D for representation - addPolygonStrokePrimitive2D( - rContainer, - aStart - (aVector * candidate.getStartLeft()), - aEnd + (aVector * candidate.getEndLeft()), - candidate.getLineAttribute(), - getStrokeAttribute()); + // without stroke, we can simply represent that using a filled polygon + const basegfx::B2DVector aHalfLineOffset(aPerpendicular * (candidate.getLineAttribute().getWidth() * 0.5)); + basegfx::B2DPolygon aPolygon; + + aPolygon.append(aStart - aHalfLineOffset - (aVector * candidate.getStartLeft())); + aPolygon.append(aEnd - aHalfLineOffset + (aVector * candidate.getEndLeft())); + aPolygon.append(aEnd + aHalfLineOffset + (aVector * candidate.getEndRight())); + aPolygon.append(aStart + aHalfLineOffset - (aVector * candidate.getStartRight())); + + rContainer.push_back( + new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + candidate.getLineAttribute().getColor())); } else { - // start and/or end extensions lead to a lineStart/End that is *not* - // perpendicular to the line itself - if(getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen()) + // with stroke, we have a problem - a filled polygon would lose the + // stroke. Let's represent the start and/or end as triangles, the main + // line still as PolygonStrokePrimitive2D. + // Fill default line Start/End for stroke, so we need no adaptations in else paths + basegfx::B2DPoint aStrokeStart(aStart - (aVector * candidate.getStartLeft())); + basegfx::B2DPoint aStrokeEnd(aEnd + (aVector * candidate.getEndLeft())); + const basegfx::B2DVector aHalfLineOffset(aPerpendicular * (candidate.getLineAttribute().getWidth() * 0.5)); + + if(!bStartPerpendicular) { - // without stroke, we can simply represent that using a filled polygon - const basegfx::B2DVector aHalfLineOffset(aPerpendicular * (candidate.getLineAttribute().getWidth() * 0.5)); + const double fMin(std::min(candidate.getStartLeft(), candidate.getStartRight())); + const double fMax(std::max(candidate.getStartLeft(), candidate.getStartRight())); basegfx::B2DPolygon aPolygon; - aPolygon.append(aStart - aHalfLineOffset - (aVector * candidate.getStartLeft())); - aPolygon.append(aEnd - aHalfLineOffset + (aVector * candidate.getEndLeft())); - aPolygon.append(aEnd + aHalfLineOffset + (aVector * candidate.getEndRight())); - aPolygon.append(aStart + aHalfLineOffset - (aVector * candidate.getStartRight())); + // create a triangle with min/max values for LineStart and add + if(rtl::math::approxEqual(candidate.getStartLeft(), fMax)) + { + aPolygon.append(aStart - aHalfLineOffset - (aVector * candidate.getStartLeft())); + } + + aPolygon.append(aStart - aHalfLineOffset - (aVector * fMin)); + aPolygon.append(aStart + aHalfLineOffset - (aVector * fMin)); + + if(rtl::math::approxEqual(candidate.getStartRight(), fMax)) + { + aPolygon.append(aStart + aHalfLineOffset - (aVector * candidate.getStartRight())); + } rContainer.push_back( new PolyPolygonColorPrimitive2D( basegfx::B2DPolyPolygon(aPolygon), candidate.getLineAttribute().getColor())); + + // Adapt StrokeStart accordingly + aStrokeStart = aStart - (aVector * fMin); } - else + + if(!bEndPerpendicular) { - // with stroke, we have a problem - a filled polygon would lose the - // stroke. Let's represent the start and/or end as triangles, the main - // line still as PolygonStrokePrimitive2D. - // Fill default line Start/End for stroke, so we need no adaptations in else paths - basegfx::B2DPoint aStrokeStart(aStart - (aVector * candidate.getStartLeft())); - basegfx::B2DPoint aStrokeEnd(aEnd + (aVector * candidate.getEndLeft())); - const basegfx::B2DVector aHalfLineOffset(aPerpendicular * (candidate.getLineAttribute().getWidth() * 0.5)); - - if(!bStartPerpendicular) + const double fMin(std::min(candidate.getEndLeft(), candidate.getEndRight())); + const double fMax(std::max(candidate.getEndLeft(), candidate.getEndRight())); + basegfx::B2DPolygon aPolygon; + + // create a triangle with min/max values for LineEnd and add + if(rtl::math::approxEqual(candidate.getEndLeft(), fMax)) { - const double fMin(std::min(candidate.getStartLeft(), candidate.getStartRight())); - const double fMax(std::max(candidate.getStartLeft(), candidate.getStartRight())); - basegfx::B2DPolygon aPolygon; - - // create a triangle with min/max values for LineStart and add - if(rtl::math::approxEqual(candidate.getStartLeft(), fMax)) - { - aPolygon.append(aStart - aHalfLineOffset - (aVector * candidate.getStartLeft())); - } - - aPolygon.append(aStart - aHalfLineOffset - (aVector * fMin)); - aPolygon.append(aStart + aHalfLineOffset - (aVector * fMin)); - - if(rtl::math::approxEqual(candidate.getStartRight(), fMax)) - { - aPolygon.append(aStart + aHalfLineOffset - (aVector * candidate.getStartRight())); - } - - rContainer.push_back( - new PolyPolygonColorPrimitive2D( - basegfx::B2DPolyPolygon(aPolygon), - candidate.getLineAttribute().getColor())); - - // Adapt StrokeStart accordingly - aStrokeStart = aStart - (aVector * fMin); + aPolygon.append(aEnd - aHalfLineOffset + (aVector * candidate.getEndLeft())); } - if(!bEndPerpendicular) + if(rtl::math::approxEqual(candidate.getEndRight(), fMax)) { - const double fMin(std::min(candidate.getEndLeft(), candidate.getEndRight())); - const double fMax(std::max(candidate.getEndLeft(), candidate.getEndRight())); - basegfx::B2DPolygon aPolygon; - - // create a triangle with min/max values for LineEnd and add - if(rtl::math::approxEqual(candidate.getEndLeft(), fMax)) - { - aPolygon.append(aEnd - aHalfLineOffset + (aVector * candidate.getEndLeft())); - } - - if(rtl::math::approxEqual(candidate.getEndRight(), fMax)) - { - aPolygon.append(aEnd + aHalfLineOffset + (aVector * candidate.getEndRight())); - } - - aPolygon.append(aEnd + aHalfLineOffset + (aVector * fMin)); - aPolygon.append(aEnd - aHalfLineOffset + (aVector * fMin)); - - rContainer.push_back( - new PolyPolygonColorPrimitive2D( - basegfx::B2DPolyPolygon(aPolygon), - candidate.getLineAttribute().getColor())); - - // Adapt StrokeEnd accordingly - aStrokeEnd = aEnd + (aVector * fMin); + aPolygon.append(aEnd + aHalfLineOffset + (aVector * candidate.getEndRight())); } - addPolygonStrokePrimitive2D( - rContainer, - aStrokeStart, - aStrokeEnd, - candidate.getLineAttribute(), - getStrokeAttribute()); + aPolygon.append(aEnd + aHalfLineOffset + (aVector * fMin)); + aPolygon.append(aEnd - aHalfLineOffset + (aVector * fMin)); + + rContainer.push_back( + new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + candidate.getLineAttribute().getColor())); + + // Adapt StrokeEnd accordingly + aStrokeEnd = aEnd + (aVector * fMin); } + + addPolygonStrokePrimitive2D( + rContainer, + aStrokeStart, + aStrokeEnd, + candidate.getLineAttribute(), + getStrokeAttribute()); } } - - fOffset += fWidth; } + + fOffset += fWidth; } } diff --git a/drawinglayer/source/primitive2d/controlprimitive2d.cxx b/drawinglayer/source/primitive2d/controlprimitive2d.cxx index 600bb4be8a3f..c3b030dcf1ac 100644 --- a/drawinglayer/source/primitive2d/controlprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/controlprimitive2d.cxx @@ -45,33 +45,33 @@ namespace drawinglayer::primitive2d { void ControlPrimitive2D::createXControl() { - if(!mxXControl.is() && getControlModel().is()) - { - uno::Reference< beans::XPropertySet > xSet(getControlModel(), uno::UNO_QUERY); + if(!(!mxXControl.is() && getControlModel().is())) + return; - if(xSet.is()) - { - uno::Any aValue(xSet->getPropertyValue("DefaultControl")); - OUString aUnoControlTypeName; + uno::Reference< beans::XPropertySet > xSet(getControlModel(), uno::UNO_QUERY); - if(aValue >>= aUnoControlTypeName) - { - if(!aUnoControlTypeName.isEmpty()) - { - uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); - uno::Reference< awt::XControl > xXControl( - xContext->getServiceManager()->createInstanceWithContext(aUnoControlTypeName, xContext), uno::UNO_QUERY); + if(!xSet.is()) + return; - if(xXControl.is()) - { - xXControl->setModel(getControlModel()); + uno::Any aValue(xSet->getPropertyValue("DefaultControl")); + OUString aUnoControlTypeName; - // remember XControl - mxXControl = xXControl; - } - } - } - } + if(!(aValue >>= aUnoControlTypeName)) + return; + + if(aUnoControlTypeName.isEmpty()) + return; + + uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference< awt::XControl > xXControl( + xContext->getServiceManager()->createInstanceWithContext(aUnoControlTypeName, xContext), uno::UNO_QUERY); + + if(xXControl.is()) + { + xXControl->setModel(getControlModel()); + + // remember XControl + mxXControl = xXControl; } } diff --git a/drawinglayer/source/primitive2d/cropprimitive2d.cxx b/drawinglayer/source/primitive2d/cropprimitive2d.cxx index 5dbc13ff4119..2d780ac2645c 100644 --- a/drawinglayer/source/primitive2d/cropprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/cropprimitive2d.cxx @@ -65,82 +65,82 @@ namespace drawinglayer::primitive2d void CropPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if(!getChildren().empty()) + if(getChildren().empty()) + return; + + // get original object scale in unit coordinates (no mirroring) + const basegfx::B2DVector aObjectScale(basegfx::absolute(getTransformation() * basegfx::B2DVector(1.0, 1.0))); + + // we handle cropping, so when no width or no height, content will be empty, + // so only do something when we have a width and a height + if(aObjectScale.equalZero()) + return; + + // calculate crop distances in unit coordinates. They are already combined with CropScaleFactor, thus + // are relative only to object scale + const double fBackScaleX(basegfx::fTools::equalZero(aObjectScale.getX()) ? 1.0 : 1.0 / fabs(aObjectScale.getX())); + const double fBackScaleY(basegfx::fTools::equalZero(aObjectScale.getY()) ? 1.0 : 1.0 / fabs(aObjectScale.getY())); + const double fLeft(getCropLeft() * fBackScaleX); + const double fTop(getCropTop() * fBackScaleY); + const double fRight(getCropRight() * fBackScaleX); + const double fBottom(getCropBottom() * fBackScaleY); + + // calc new unit range for comparisons; the original range is the unit range + const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); + const basegfx::B2DRange aNewRange( + -fLeft, + -fTop, + 1.0 + fRight, + 1.0 + fBottom); + + // if we have no overlap the crop has removed everything, so we do only + // have to create content if this is not the case + if(!aNewRange.overlaps(aUnitRange)) + return; + + // create new transform; first take out old transform to get + // to unit coordinates by inverting. Inverting should be flawless + // since we already checked that object size is not zero in X or Y + basegfx::B2DHomMatrix aNewTransform(getTransformation()); + + aNewTransform.invert(); + + // apply crop enlargement in unit coordinates + aNewTransform = basegfx::utils::createScaleTranslateB2DHomMatrix( + aNewRange.getRange(), + aNewRange.getMinimum()) * aNewTransform; + + // apply original transformation. Since we have manipulated the crop + // in unit coordinates we do not need to care about mirroring or + // a corrected point for a possible shear or rotation, this all comes for + // free + aNewTransform = getTransformation() * aNewTransform; + + // prepare TransformPrimitive2D with xPrimitive + const Primitive2DReference xTransformPrimitive( + new TransformPrimitive2D( + aNewTransform, + getChildren())); + + if(aUnitRange.isInside(aNewRange)) { - // get original object scale in unit coordinates (no mirroring) - const basegfx::B2DVector aObjectScale(basegfx::absolute(getTransformation() * basegfx::B2DVector(1.0, 1.0))); - - // we handle cropping, so when no width or no height, content will be empty, - // so only do something when we have a width and a height - if(!aObjectScale.equalZero()) - { - // calculate crop distances in unit coordinates. They are already combined with CropScaleFactor, thus - // are relative only to object scale - const double fBackScaleX(basegfx::fTools::equalZero(aObjectScale.getX()) ? 1.0 : 1.0 / fabs(aObjectScale.getX())); - const double fBackScaleY(basegfx::fTools::equalZero(aObjectScale.getY()) ? 1.0 : 1.0 / fabs(aObjectScale.getY())); - const double fLeft(getCropLeft() * fBackScaleX); - const double fTop(getCropTop() * fBackScaleY); - const double fRight(getCropRight() * fBackScaleX); - const double fBottom(getCropBottom() * fBackScaleY); - - // calc new unit range for comparisons; the original range is the unit range - const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); - const basegfx::B2DRange aNewRange( - -fLeft, - -fTop, - 1.0 + fRight, - 1.0 + fBottom); - - // if we have no overlap the crop has removed everything, so we do only - // have to create content if this is not the case - if(aNewRange.overlaps(aUnitRange)) - { - // create new transform; first take out old transform to get - // to unit coordinates by inverting. Inverting should be flawless - // since we already checked that object size is not zero in X or Y - basegfx::B2DHomMatrix aNewTransform(getTransformation()); - - aNewTransform.invert(); - - // apply crop enlargement in unit coordinates - aNewTransform = basegfx::utils::createScaleTranslateB2DHomMatrix( - aNewRange.getRange(), - aNewRange.getMinimum()) * aNewTransform; - - // apply original transformation. Since we have manipulated the crop - // in unit coordinates we do not need to care about mirroring or - // a corrected point for a possible shear or rotation, this all comes for - // free - aNewTransform = getTransformation() * aNewTransform; - - // prepare TransformPrimitive2D with xPrimitive - const Primitive2DReference xTransformPrimitive( - new TransformPrimitive2D( - aNewTransform, - getChildren())); - - if(aUnitRange.isInside(aNewRange)) - { - // the new range is completely inside the old range (unit range), - // so no masking is needed - rVisitor.append(xTransformPrimitive); - } - else - { - // mask with original object's bounds - basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::utils::createUnitPolygon()); - aMaskPolyPolygon.transform(getTransformation()); - - // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector - const Primitive2DReference xMask( - new MaskPrimitive2D( - aMaskPolyPolygon, - Primitive2DContainer { xTransformPrimitive })); - - rVisitor.append(xMask); - } - } - } + // the new range is completely inside the old range (unit range), + // so no masking is needed + rVisitor.append(xTransformPrimitive); + } + else + { + // mask with original object's bounds + basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::utils::createUnitPolygon()); + aMaskPolyPolygon.transform(getTransformation()); + + // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector + const Primitive2DReference xMask( + new MaskPrimitive2D( + aMaskPolyPolygon, + Primitive2DContainer { xTransformPrimitive })); + + rVisitor.append(xMask); } } diff --git a/drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx b/drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx index bb73067a7d36..17d6f2301a43 100644 --- a/drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/discretebitmapprimitive2d.cxx @@ -31,43 +31,43 @@ namespace drawinglayer::primitive2d // ObjectAndViewTransformationDependentPrimitive2D to create a BitmapPrimitive2D // with the correct mapping - if(!getBitmapEx().IsEmpty()) - { - // get discrete size - const Size& rSizePixel = getBitmapEx().GetSizePixel(); - const basegfx::B2DVector aDiscreteSize(rSizePixel.Width(), rSizePixel.Height()); - - // get inverse ViewTransformation - basegfx::B2DHomMatrix aInverseViewTransformation(getViewTransformation()); - aInverseViewTransformation.invert(); - - // get size and position in world coordinates - const basegfx::B2DVector aWorldSize(aInverseViewTransformation * aDiscreteSize); - const basegfx::B2DPoint aWorldTopLeft(getObjectTransformation() * getTopLeft()); - - // build object matrix in world coordinates so that the top-left - // position remains, but possible transformations (e.g. rotations) - // in the ObjectToView stack remain and get correctly applied - basegfx::B2DHomMatrix aObjectTransform; - - aObjectTransform.set(0, 0, aWorldSize.getX()); - aObjectTransform.set(1, 1, aWorldSize.getY()); - aObjectTransform.set(0, 2, aWorldTopLeft.getX()); - aObjectTransform.set(1, 2, aWorldTopLeft.getY()); - - // get inverse ObjectTransformation - basegfx::B2DHomMatrix aInverseObjectTransformation(getObjectTransformation()); - aInverseObjectTransformation.invert(); - - // transform to object coordinate system - aObjectTransform = aInverseObjectTransformation * aObjectTransform; - - // create BitmapPrimitive2D with now object-local coordinate data - rContainer.push_back( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getBitmapEx()), - aObjectTransform)); - } + if(getBitmapEx().IsEmpty()) + return; + + // get discrete size + const Size& rSizePixel = getBitmapEx().GetSizePixel(); + const basegfx::B2DVector aDiscreteSize(rSizePixel.Width(), rSizePixel.Height()); + + // get inverse ViewTransformation + basegfx::B2DHomMatrix aInverseViewTransformation(getViewTransformation()); + aInverseViewTransformation.invert(); + + // get size and position in world coordinates + const basegfx::B2DVector aWorldSize(aInverseViewTransformation * aDiscreteSize); + const basegfx::B2DPoint aWorldTopLeft(getObjectTransformation() * getTopLeft()); + + // build object matrix in world coordinates so that the top-left + // position remains, but possible transformations (e.g. rotations) + // in the ObjectToView stack remain and get correctly applied + basegfx::B2DHomMatrix aObjectTransform; + + aObjectTransform.set(0, 0, aWorldSize.getX()); + aObjectTransform.set(1, 1, aWorldSize.getY()); + aObjectTransform.set(0, 2, aWorldTopLeft.getX()); + aObjectTransform.set(1, 2, aWorldTopLeft.getY()); + + // get inverse ObjectTransformation + basegfx::B2DHomMatrix aInverseObjectTransformation(getObjectTransformation()); + aInverseObjectTransformation.invert(); + + // transform to object coordinate system + aObjectTransform = aInverseObjectTransformation * aObjectTransform; + + // create BitmapPrimitive2D with now object-local coordinate data + rContainer.push_back( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getBitmapEx()), + aObjectTransform)); } DiscreteBitmapPrimitive2D::DiscreteBitmapPrimitive2D( diff --git a/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx b/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx index 116389383b4c..3100db147345 100644 --- a/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/discreteshadowprimitive2d.cxx @@ -161,105 +161,105 @@ namespace drawinglayer::primitive2d { Primitive2DContainer xRetval; - if(!getDiscreteShadow().getBitmapEx().IsEmpty()) - { - const sal_Int32 nQuarter((getDiscreteShadow().getBitmapEx().GetSizePixel().Width() - 3) >> 2); - const basegfx::B2DVector aScale(getTransform() * basegfx::B2DVector(1.0, 1.0)); - const double fSingleX(getDiscreteUnit() / aScale.getX()); - const double fSingleY(getDiscreteUnit() / aScale.getY()); - const double fBorderX(fSingleX * nQuarter); - const double fBorderY(fSingleY * nQuarter); - const double fBigLenX((fBorderX * 2.0) + fSingleX); - const double fBigLenY((fBorderY * 2.0) + fSingleY); - - xRetval.resize(8); - - // TopLeft - xRetval[0] = Primitive2DReference( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTopLeft()), - basegfx::utils::createScaleTranslateB2DHomMatrix( - fBigLenX, - fBigLenY, - -fBorderX, - -fBorderY))); - - // Top - xRetval[1] = Primitive2DReference( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTop()), - basegfx::utils::createScaleTranslateB2DHomMatrix( - 1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX, - fBorderY, - fBorderX + fSingleX, - -fBorderY))); - - // TopRight - xRetval[2] = Primitive2DReference( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTopRight()), - basegfx::utils::createScaleTranslateB2DHomMatrix( - fBigLenX, - fBigLenY, - 1.0 - fBorderX, - -fBorderY))); - - // Right - xRetval[3] = Primitive2DReference( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getRight()), - basegfx::utils::createScaleTranslateB2DHomMatrix( - fBorderX, - 1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY, - 1.0 + fSingleX, - fBorderY + fSingleY))); - - // BottomRight - xRetval[4] = Primitive2DReference( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottomRight()), - basegfx::utils::createScaleTranslateB2DHomMatrix( - fBigLenX, - fBigLenY, - 1.0 - (fBorderX + fSingleX) + fSingleX, - 1.0 - (fBorderY + fSingleY) + fSingleY))); - - // Bottom - xRetval[5] = Primitive2DReference( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottom()), - basegfx::utils::createScaleTranslateB2DHomMatrix( - 1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX, - fBorderY, - fBorderX + fSingleX, - 1.0 + fSingleY))); - - // BottomLeft - xRetval[6] = Primitive2DReference( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottomLeft()), - basegfx::utils::createScaleTranslateB2DHomMatrix( - fBigLenX, - fBigLenY, - -fBorderX, - 1.0 - fBorderY))); - - // Left - xRetval[7] = Primitive2DReference( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getLeft()), - basegfx::utils::createScaleTranslateB2DHomMatrix( - fBorderX, - 1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY, - -fBorderX, - fBorderY + fSingleY))); - - // put all in object transformation to get to target positions - rContainer.push_back( - new TransformPrimitive2D( - getTransform(), - xRetval)); - } + if(getDiscreteShadow().getBitmapEx().IsEmpty()) + return; + + const sal_Int32 nQuarter((getDiscreteShadow().getBitmapEx().GetSizePixel().Width() - 3) >> 2); + const basegfx::B2DVector aScale(getTransform() * basegfx::B2DVector(1.0, 1.0)); + const double fSingleX(getDiscreteUnit() / aScale.getX()); + const double fSingleY(getDiscreteUnit() / aScale.getY()); + const double fBorderX(fSingleX * nQuarter); + const double fBorderY(fSingleY * nQuarter); + const double fBigLenX((fBorderX * 2.0) + fSingleX); + const double fBigLenY((fBorderY * 2.0) + fSingleY); + + xRetval.resize(8); + + // TopLeft + xRetval[0] = Primitive2DReference( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTopLeft()), + basegfx::utils::createScaleTranslateB2DHomMatrix( + fBigLenX, + fBigLenY, + -fBorderX, + -fBorderY))); + + // Top + xRetval[1] = Primitive2DReference( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTop()), + basegfx::utils::createScaleTranslateB2DHomMatrix( + 1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX, + fBorderY, + fBorderX + fSingleX, + -fBorderY))); + + // TopRight + xRetval[2] = Primitive2DReference( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getTopRight()), + basegfx::utils::createScaleTranslateB2DHomMatrix( + fBigLenX, + fBigLenY, + 1.0 - fBorderX, + -fBorderY))); + + // Right + xRetval[3] = Primitive2DReference( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getRight()), + basegfx::utils::createScaleTranslateB2DHomMatrix( + fBorderX, + 1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY, + 1.0 + fSingleX, + fBorderY + fSingleY))); + + // BottomRight + xRetval[4] = Primitive2DReference( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottomRight()), + basegfx::utils::createScaleTranslateB2DHomMatrix( + fBigLenX, + fBigLenY, + 1.0 - (fBorderX + fSingleX) + fSingleX, + 1.0 - (fBorderY + fSingleY) + fSingleY))); + + // Bottom + xRetval[5] = Primitive2DReference( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottom()), + basegfx::utils::createScaleTranslateB2DHomMatrix( + 1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX, + fBorderY, + fBorderX + fSingleX, + 1.0 + fSingleY))); + + // BottomLeft + xRetval[6] = Primitive2DReference( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getBottomLeft()), + basegfx::utils::createScaleTranslateB2DHomMatrix( + fBigLenX, + fBigLenY, + -fBorderX, + 1.0 - fBorderY))); + + // Left + xRetval[7] = Primitive2DReference( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getDiscreteShadow().getLeft()), + basegfx::utils::createScaleTranslateB2DHomMatrix( + fBorderX, + 1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY, + -fBorderX, + fBorderY + fSingleY))); + + // put all in object transformation to get to target positions + rContainer.push_back( + new TransformPrimitive2D( + getTransform(), + xRetval)); } DiscreteShadowPrimitive2D::DiscreteShadowPrimitive2D( diff --git a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx index 5368016069a9..fba740e833c5 100644 --- a/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/fillgradientprimitive2d.cxx @@ -201,35 +201,35 @@ namespace drawinglayer::primitive2d aCombinedPolyPoly, rOuterColor)); - if(!rEntries.empty()) - { - // reuse first polygon, it's the second one - aCombinedPolyPoly.remove(0); + if(rEntries.empty()) + return; - for(size_t a(0); a < rEntries.size() - 1; a++) - { - // create next inner polygon, combined with last one - basegfx::B2DPolygon aNextPoly(rUnitPolygon); + // reuse first polygon, it's the second one + aCombinedPolyPoly.remove(0); - aNextPoly.transform(rEntries[a + 1].maB2DHomMatrix); - aCombinedPolyPoly.append(aNextPoly); - - // create primitive with correct color - rContainer.push_back( - new PolyPolygonColorPrimitive2D( - aCombinedPolyPoly, - rEntries[a].maBColor)); + for(size_t a(0); a < rEntries.size() - 1; a++) + { + // create next inner polygon, combined with last one + basegfx::B2DPolygon aNextPoly(rUnitPolygon); - // reuse inner polygon, it's the 2nd one - aCombinedPolyPoly.remove(0); - } + aNextPoly.transform(rEntries[a + 1].maB2DHomMatrix); + aCombinedPolyPoly.append(aNextPoly); - // add last inner polygon with last color + // create primitive with correct color rContainer.push_back( new PolyPolygonColorPrimitive2D( aCombinedPolyPoly, - rEntries[rEntries.size() - 1].maBColor)); + rEntries[a].maBColor)); + + // reuse inner polygon, it's the 2nd one + aCombinedPolyPoly.remove(0); } + + // add last inner polygon with last color + rContainer.push_back( + new PolyPolygonColorPrimitive2D( + aCombinedPolyPoly, + rEntries[rEntries.size() - 1].maBColor)); } void FillGradientPrimitive2D::createFill(Primitive2DContainer& rContainer, bool bOverlapping) const diff --git a/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx index af2c75a42720..1bfc47940a87 100644 --- a/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx @@ -36,57 +36,57 @@ namespace drawinglayer::primitive2d { const attribute::FillGraphicAttribute& rAttribute = getFillGraphic(); - if(!rAttribute.isDefault()) - { - const Graphic& rGraphic = rAttribute.getGraphic(); + if(rAttribute.isDefault()) + return; + + const Graphic& rGraphic = rAttribute.getGraphic(); + + if(!(GraphicType::Bitmap == rGraphic.GetType() || GraphicType::GdiMetafile == rGraphic.GetType())) + return; + + const Size aSize(rGraphic.GetPrefSize()); - if(GraphicType::Bitmap == rGraphic.GetType() || GraphicType::GdiMetafile == rGraphic.GetType()) + if(!(aSize.Width() && aSize.Height())) + return; + + // we have a graphic (bitmap or metafile) with some size + if(rAttribute.getTiling()) + { + // get object range and create tiling matrices + std::vector< basegfx::B2DHomMatrix > aMatrices; + texture::GeoTexSvxTiled aTiling( + rAttribute.getGraphicRange(), + rAttribute.getOffsetX(), + rAttribute.getOffsetY()); + + // get matrices and realloc retval + aTiling.appendTransformations(aMatrices); + + // prepare content primitive + Primitive2DContainer xSeq; + create2DDecompositionOfGraphic(xSeq, + rGraphic, + basegfx::B2DHomMatrix()); + + for(size_t a(0); a < aMatrices.size(); a++) { - const Size aSize(rGraphic.GetPrefSize()); - - if(aSize.Width() && aSize.Height()) - { - // we have a graphic (bitmap or metafile) with some size - if(rAttribute.getTiling()) - { - // get object range and create tiling matrices - std::vector< basegfx::B2DHomMatrix > aMatrices; - texture::GeoTexSvxTiled aTiling( - rAttribute.getGraphicRange(), - rAttribute.getOffsetX(), - rAttribute.getOffsetY()); - - // get matrices and realloc retval - aTiling.appendTransformations(aMatrices); - - // prepare content primitive - Primitive2DContainer xSeq; - create2DDecompositionOfGraphic(xSeq, - rGraphic, - basegfx::B2DHomMatrix()); - - for(size_t a(0); a < aMatrices.size(); a++) - { - rContainer.push_back(new TransformPrimitive2D( - getTransformation() * aMatrices[a], - xSeq)); - } - } - else - { - // add graphic without tiling - const basegfx::B2DHomMatrix aObjectTransform( - getTransformation() * basegfx::utils::createScaleTranslateB2DHomMatrix( - rAttribute.getGraphicRange().getRange(), - rAttribute.getGraphicRange().getMinimum())); - - create2DDecompositionOfGraphic(rContainer, - rGraphic, - aObjectTransform); - } - } + rContainer.push_back(new TransformPrimitive2D( + getTransformation() * aMatrices[a], + xSeq)); } } + else + { + // add graphic without tiling + const basegfx::B2DHomMatrix aObjectTransform( + getTransformation() * basegfx::utils::createScaleTranslateB2DHomMatrix( + rAttribute.getGraphicRange().getRange(), + rAttribute.getGraphicRange().getMinimum())); + + create2DDecompositionOfGraphic(rContainer, + rGraphic, + aObjectTransform); + } } FillGraphicPrimitive2D::FillGraphicPrimitive2D( diff --git a/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx b/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx index c408c04701b5..5919847ab33c 100644 --- a/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/fillhatchprimitive2d.cxx @@ -34,96 +34,96 @@ namespace drawinglayer::primitive2d { void FillHatchPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if(!getFillHatch().isDefault()) + if(getFillHatch().isDefault()) + return; + + // create hatch + const basegfx::BColor aHatchColor(getFillHatch().getColor()); + const double fAngle(getFillHatch().getAngle()); + std::vector< basegfx::B2DHomMatrix > aMatrices; + double fDistance(getFillHatch().getDistance()); + const bool bAdaptDistance(0 != getFillHatch().getMinimalDiscreteDistance()); + + // #i120230# evtl. adapt distance + if(bAdaptDistance) { - // create hatch - const basegfx::BColor aHatchColor(getFillHatch().getColor()); - const double fAngle(getFillHatch().getAngle()); - std::vector< basegfx::B2DHomMatrix > aMatrices; - double fDistance(getFillHatch().getDistance()); - const bool bAdaptDistance(0 != getFillHatch().getMinimalDiscreteDistance()); - - // #i120230# evtl. adapt distance - if(bAdaptDistance) - { - const double fDiscreteDistance(getFillHatch().getDistance() / getDiscreteUnit()); + const double fDiscreteDistance(getFillHatch().getDistance() / getDiscreteUnit()); - if(fDiscreteDistance < static_cast<double>(getFillHatch().getMinimalDiscreteDistance())) - { - fDistance = static_cast<double>(getFillHatch().getMinimalDiscreteDistance()) * getDiscreteUnit(); - } + if(fDiscreteDistance < static_cast<double>(getFillHatch().getMinimalDiscreteDistance())) + { + fDistance = static_cast<double>(getFillHatch().getMinimalDiscreteDistance()) * getDiscreteUnit(); } + } - // get hatch transformations - switch(getFillHatch().getStyle()) + // get hatch transformations + switch(getFillHatch().getStyle()) + { + case attribute::HatchStyle::Triple: { - case attribute::HatchStyle::Triple: - { - // rotated 45 degrees - texture::GeoTexSvxHatch aHatch( - getDefinitionRange(), - getOutputRange(), - fDistance, - fAngle - F_PI4); - - aHatch.appendTransformations(aMatrices); - - [[fallthrough]]; - } - case attribute::HatchStyle::Double: - { - // rotated 90 degrees - texture::GeoTexSvxHatch aHatch( - getDefinitionRange(), - getOutputRange(), - fDistance, - fAngle - F_PI2); - - aHatch.appendTransformations(aMatrices); - - [[fallthrough]]; - } - case attribute::HatchStyle::Single: - { - // angle as given - texture::GeoTexSvxHatch aHatch( - getDefinitionRange(), - getOutputRange(), - fDistance, - fAngle); - - aHatch.appendTransformations(aMatrices); - } + // rotated 45 degrees + texture::GeoTexSvxHatch aHatch( + getDefinitionRange(), + getOutputRange(), + fDistance, + fAngle - F_PI4); + + aHatch.appendTransformations(aMatrices); + + [[fallthrough]]; } + case attribute::HatchStyle::Double: + { + // rotated 90 degrees + texture::GeoTexSvxHatch aHatch( + getDefinitionRange(), + getOutputRange(), + fDistance, + fAngle - F_PI2); - // prepare return value - const bool bFillBackground(getFillHatch().isFillBackground()); + aHatch.appendTransformations(aMatrices); - // evtl. create filled background - if(bFillBackground) + [[fallthrough]]; + } + case attribute::HatchStyle::Single: { - // create primitive for background - rContainer.push_back( - new PolyPolygonColorPrimitive2D( - basegfx::B2DPolyPolygon( - basegfx::utils::createPolygonFromRect(getOutputRange())), getBColor())); + // angle as given + texture::GeoTexSvxHatch aHatch( + getDefinitionRange(), + getOutputRange(), + fDistance, + fAngle); + + aHatch.appendTransformations(aMatrices); } + } - // create primitives - const basegfx::B2DPoint aStart(0.0, 0.0); - const basegfx::B2DPoint aEnd(1.0, 0.0); + // prepare return value + const bool bFillBackground(getFillHatch().isFillBackground()); - for(size_t a(0); a < aMatrices.size(); a++) - { - const basegfx::B2DHomMatrix& rMatrix = aMatrices[a]; - basegfx::B2DPolygon aNewLine; + // evtl. create filled background + if(bFillBackground) + { + // create primitive for background + rContainer.push_back( + new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon( + basegfx::utils::createPolygonFromRect(getOutputRange())), getBColor())); + } - aNewLine.append(rMatrix * aStart); - aNewLine.append(rMatrix * aEnd); + // create primitives + const basegfx::B2DPoint aStart(0.0, 0.0); + const basegfx::B2DPoint aEnd(1.0, 0.0); - // create hairline - rContainer.push_back(new PolygonHairlinePrimitive2D(aNewLine, aHatchColor)); - } + for(size_t a(0); a < aMatrices.size(); a++) + { + const basegfx::B2DHomMatrix& rMatrix = aMatrices[a]; + basegfx::B2DPolygon aNewLine; + + aNewLine.append(rMatrix * aStart); + aNewLine.append(rMatrix * aEnd); + + // create hairline + rContainer.push_back(new PolygonHairlinePrimitive2D(aNewLine, aHatchColor)); } } diff --git a/drawinglayer/source/primitive2d/glowprimitive2d.cxx b/drawinglayer/source/primitive2d/glowprimitive2d.cxx index 1fc035bf5279..7d6c23a322ad 100644 --- a/drawinglayer/source/primitive2d/glowprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/glowprimitive2d.cxx @@ -64,19 +64,18 @@ void GlowPrimitive2D::get2DDecomposition( Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if (!getChildren().empty()) - { - // create a modifiedColorPrimitive containing the Glow color and the content - basegfx::BColorModifierSharedPtr aBColorModifier - = std::make_shared<basegfx::BColorModifier_replace>(getGlowColor()); + if (getChildren().empty()) + return; - const Primitive2DReference xRefA( - new ModifiedColorPrimitive2D(getChildren(), aBColorModifier)); - const Primitive2DContainer aSequenceB{ xRefA }; + // create a modifiedColorPrimitive containing the Glow color and the content + basegfx::BColorModifierSharedPtr aBColorModifier + = std::make_shared<basegfx::BColorModifier_replace>(getGlowColor()); - // build transformed primitiveVector with Glow offset and add to target - rVisitor.append(new TransformPrimitive2D(getGlowTransform(), aSequenceB)); - } + const Primitive2DReference xRefA(new ModifiedColorPrimitive2D(getChildren(), aBColorModifier)); + const Primitive2DContainer aSequenceB{ xRefA }; + + // build transformed primitiveVector with Glow offset and add to target + rVisitor.append(new TransformPrimitive2D(getGlowTransform(), aSequenceB)); } // provide unique ID diff --git a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx index d301adc16a9c..69caa9956e96 100644 --- a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx +++ b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx @@ -90,26 +90,26 @@ namespace drawinglayer::primitive2d void ensureVirtualDeviceSizeAndState() { - if (isValidData()) - { - const Size aCurrent(maVirtualDevice->GetOutputSizePixel()); - const Size aTarget(maAnimation.GetDisplaySizePixel()); + if (!isValidData()) + return; - if (aCurrent != aTarget) - { - maVirtualDevice->EnableMapMode(false); - maVirtualDeviceMask->EnableMapMode(false); - maVirtualDevice->SetOutputSizePixel(aTarget); - maVirtualDeviceMask->SetOutputSizePixel(aTarget); - } + const Size aCurrent(maVirtualDevice->GetOutputSizePixel()); + const Size aTarget(maAnimation.GetDisplaySizePixel()); - maVirtualDevice->Erase(); - maVirtualDeviceMask->Erase(); - const ::tools::Rectangle aRect(Point(0, 0), aTarget); - maVirtualDeviceMask->SetFillColor(COL_BLACK); - maVirtualDeviceMask->SetLineColor(); - maVirtualDeviceMask->DrawRect(aRect); + if (aCurrent != aTarget) + { + maVirtualDevice->EnableMapMode(false); + maVirtualDeviceMask->EnableMapMode(false); + maVirtualDevice->SetOutputSizePixel(aTarget); + maVirtualDeviceMask->SetOutputSizePixel(aTarget); } + + maVirtualDevice->Erase(); + maVirtualDeviceMask->Erase(); + const ::tools::Rectangle aRect(Point(0, 0), aTarget); + maVirtualDeviceMask->SetFillColor(COL_BLACK); + maVirtualDeviceMask->SetLineColor(); + maVirtualDeviceMask->DrawRect(aRect); } sal_uInt32 generateStepTime(sal_uInt32 nIndex) const @@ -139,24 +139,24 @@ namespace drawinglayer::primitive2d void createAndSetAnimationTiming() { - if (isValidData()) - { - animation::AnimationEntryLoop aAnimationLoop(maAnimation.GetLoopCount() ? maAnimation.GetLoopCount() : 0xffff); - const sal_uInt32 nCount(maAnimation.Count()); - - for (sal_uInt32 a(0); a < nCount; a++) - { - const sal_uInt32 aStepTime(generateStepTime(a)); - const animation::AnimationEntryFixed aTime(static_cast<double>(aStepTime), static_cast<double>(a) / static_cast<double>(nCount)); + if (!isValidData()) + return; - aAnimationLoop.append(aTime); - } + animation::AnimationEntryLoop aAnimationLoop(maAnimation.GetLoopCount() ? maAnimation.GetLoopCount() : 0xffff); + const sal_uInt32 nCount(maAnimation.Count()); - animation::AnimationEntryList aAnimationEntryList; - aAnimationEntryList.append(aAnimationLoop); + for (sal_uInt32 a(0); a < nCount; a++) + { + const sal_uInt32 aStepTime(generateStepTime(a)); + const animation::AnimationEntryFixed aTime(static_cast<double>(aStepTime), static_cast<double>(a) / static_cast<double>(nCount)); - setAnimationEntry(aAnimationEntryList); + aAnimationLoop.append(aTime); } + + animation::AnimationEntryList aAnimationEntryList; + aAnimationEntryList.append(aAnimationLoop); + + setAnimationEntry(aAnimationEntryList); } Primitive2DReference createFromBuffer() const @@ -221,80 +221,80 @@ namespace drawinglayer::primitive2d // mnNextFrameToPrepare is the target frame to create next (which implies that // mnNextFrameToPrepare-1 *is* currently in the VirtualDevice when // 0 != mnNextFrameToPrepare. nTarget is the target frame. - if (isValidData()) + if (!isValidData()) + return; + + if (mnNextFrameToPrepare > nTarget) { - if (mnNextFrameToPrepare > nTarget) - { - // we are ahead request, reset mechanism to start at frame zero - ensureVirtualDeviceSizeAndState(); - mnNextFrameToPrepare = 0; - } + // we are ahead request, reset mechanism to start at frame zero + ensureVirtualDeviceSizeAndState(); + mnNextFrameToPrepare = 0; + } - while (mnNextFrameToPrepare <= nTarget) - { - // prepare step - const AnimationBitmap& rAnimationBitmap = maAnimation.Get(sal_uInt16(mnNextFrameToPrepare)); + while (mnNextFrameToPrepare <= nTarget) + { + // prepare step + const AnimationBitmap& rAnimationBitmap = maAnimation.Get(sal_uInt16(mnNextFrameToPrepare)); - switch (rAnimationBitmap.meDisposal) + switch (rAnimationBitmap.meDisposal) + { + case Disposal::Not: { - case Disposal::Not: - { - maVirtualDevice->DrawBitmapEx(rAnimationBitmap.maPositionPixel, rAnimationBitmap.maBitmapEx); - Bitmap aMask = rAnimationBitmap.maBitmapEx.GetMask(); - - if (aMask.IsEmpty()) - { - const Point aEmpty; - const ::tools::Rectangle aRect(aEmpty, maVirtualDeviceMask->GetOutputSizePixel()); - const Wallpaper aWallpaper(COL_BLACK); - maVirtualDeviceMask->DrawWallpaper(aRect, aWallpaper); - } - else - { - BitmapEx aExpandVisibilityMask(aMask, aMask); - maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask); - } + maVirtualDevice->DrawBitmapEx(rAnimationBitmap.maPositionPixel, rAnimationBitmap.maBitmapEx); + Bitmap aMask = rAnimationBitmap.maBitmapEx.GetMask(); - break; + if (aMask.IsEmpty()) + { + const Point aEmpty; + const ::tools::Rectangle aRect(aEmpty, maVirtualDeviceMask->GetOutputSizePixel()); + const Wallpaper aWallpaper(COL_BLACK); + maVirtualDeviceMask->DrawWallpaper(aRect, aWallpaper); } - case Disposal::Back: + else { - // #i70772# react on no mask, for primitives, too. - const Bitmap & rMask(rAnimationBitmap.maBitmapEx.GetMask()); - const Bitmap & rContent(rAnimationBitmap.maBitmapEx.GetBitmap()); + BitmapEx aExpandVisibilityMask(aMask, aMask); + maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask); + } - maVirtualDeviceMask->Erase(); - maVirtualDevice->DrawBitmap(rAnimationBitmap.maPositionPixel, rContent); + break; + } + case Disposal::Back: + { + // #i70772# react on no mask, for primitives, too. + const Bitmap & rMask(rAnimationBitmap.maBitmapEx.GetMask()); + const Bitmap & rContent(rAnimationBitmap.maBitmapEx.GetBitmap()); - if (rMask.IsEmpty()) - { - const ::tools::Rectangle aRect(rAnimationBitmap.maPositionPixel, rContent.GetSizePixel()); - maVirtualDeviceMask->SetFillColor(COL_BLACK); - maVirtualDeviceMask->SetLineColor(); - maVirtualDeviceMask->DrawRect(aRect); - } - else - { - BitmapEx aExpandVisibilityMask(rMask, rMask); - maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask); - } + maVirtualDeviceMask->Erase(); + maVirtualDevice->DrawBitmap(rAnimationBitmap.maPositionPixel, rContent); - break; + if (rMask.IsEmpty()) + { + const ::tools::Rectangle aRect(rAnimationBitmap.maPositionPixel, rContent.GetSizePixel()); + maVirtualDeviceMask->SetFillColor(COL_BLACK); + maVirtualDeviceMask->SetLineColor(); + maVirtualDeviceMask->DrawRect(aRect); } - case Disposal::Previous: + else { - maVirtualDevice->DrawBitmapEx(rAnimationBitmap.maPositionPixel, rAnimationBitmap.maBitmapEx); - BitmapEx aExpandVisibilityMask(rAnimationBitmap.maBitmapEx.GetMask(), rAnimationBitmap.maBitmapEx.GetMask()); + BitmapEx aExpandVisibilityMask(rMask, rMask); maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask); - break; } + + break; + } + case Disposal::Previous: + { + maVirtualDevice->DrawBitmapEx(rAnimationBitmap.maPositionPixel, rAnimationBitmap.maBitmapEx); + BitmapEx aExpandVisibilityMask(rAnimationBitmap.maBitmapEx.GetMask(), rAnimationBitmap.maBitmapEx.GetMask()); + maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask); + break; } + } - // to not waste created data, check adding to buffers - checkSafeToBuffer(mnNextFrameToPrepare); + // to not waste created data, check adding to buffers + checkSafeToBuffer(mnNextFrameToPrepare); - mnNextFrameToPrepare++; - } + mnNextFrameToPrepare++; } } @@ -409,53 +409,53 @@ namespace drawinglayer::primitive2d void AnimatedGraphicPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const { - if (isValidData()) - { - Primitive2DReference aRetval; - const double fState(getAnimationEntry().getStateAtTime(rViewInformation.getViewTime())); - const sal_uInt32 nLen(maAnimation.Count()); - sal_uInt32 nIndex(basegfx::fround(fState * static_cast<double>(nLen))); - - // nIndex is the requested frame - it is in range [0..nLen[ - // create frame representation in VirtualDevices - if (nIndex >= nLen) - { - nIndex = nLen - 1; - } + if (!isValidData()) + return; - // check buffering shortcuts, may already be created - aRetval = tryTogetFromBuffer(nIndex); + Primitive2DReference aRetval; + const double fState(getAnimationEntry().getStateAtTime(rViewInformation.getViewTime())); + const sal_uInt32 nLen(maAnimation.Count()); + sal_uInt32 nIndex(basegfx::fround(fState * static_cast<double>(nLen))); - if (aRetval.is()) - { - rVisitor.append(aRetval); - return; - } + // nIndex is the requested frame - it is in range [0..nLen[ + // create frame representation in VirtualDevices + if (nIndex >= nLen) + { + nIndex = nLen - 1; + } - // if huge size (and not the buffered 1st frame) simply - // create next frame - if (mbHugeSize && 0 != nIndex && mnNextFrameToPrepare <= nIndex) - { - nIndex = mnNextFrameToPrepare % nLen; - } + // check buffering shortcuts, may already be created + aRetval = tryTogetFromBuffer(nIndex); - // frame not (yet) buffered or no buffering allowed, create it - const_cast<AnimatedGraphicPrimitive2D*>(this)->createFrame(nIndex); + if (aRetval.is()) + { + rVisitor.append(aRetval); + return; + } - // try to get from buffer again, may have been added from createFrame - aRetval = tryTogetFromBuffer(nIndex); + // if huge size (and not the buffered 1st frame) simply + // create next frame + if (mbHugeSize && 0 != nIndex && mnNextFrameToPrepare <= nIndex) + { + nIndex = mnNextFrameToPrepare % nLen; + } - if (aRetval.is()) - { - rVisitor.append(aRetval); - return; - } + // frame not (yet) buffered or no buffering allowed, create it + const_cast<AnimatedGraphicPrimitive2D*>(this)->createFrame(nIndex); - // did not work (not buffered and not 1st frame), create from buffer - aRetval = createFromBuffer(); + // try to get from buffer again, may have been added from createFrame + aRetval = tryTogetFromBuffer(nIndex); + if (aRetval.is()) + { rVisitor.append(aRetval); + return; } + + // did not work (not buffered and not 1st frame), create from buffer + aRetval = createFromBuffer(); + + rVisitor.append(aRetval); } } // end of namespace diff --git a/drawinglayer/source/primitive2d/gridprimitive2d.cxx b/drawinglayer/source/primitive2d/gridprimitive2d.cxx index 232c35fa66c2..66a747452103 100644 --- a/drawinglayer/source/primitive2d/gridprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/gridprimitive2d.cxx @@ -32,221 +32,221 @@ namespace drawinglayer::primitive2d { void GridPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const { - if(!rViewInformation.getViewport().isEmpty() && getWidth() > 0.0 && getHeight() > 0.0) + if(!(!rViewInformation.getViewport().isEmpty() && getWidth() > 0.0 && getHeight() > 0.0)) + return; + + // decompose grid matrix to get logic size + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + // create grid matrix which transforms from scaled logic to view + basegfx::B2DHomMatrix aRST(basegfx::utils::createShearXRotateTranslateB2DHomMatrix( + fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); + aRST *= rViewInformation.getObjectToViewTransformation(); + + // get step widths + double fStepX(getWidth()); + double fStepY(getHeight()); + const double fMinimalStep(10.0); + + // guarantee a step width of 10.0 + if(basegfx::fTools::less(fStepX, fMinimalStep)) { - // decompose grid matrix to get logic size - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - getTransform().decompose(aScale, aTranslate, fRotate, fShearX); - - // create grid matrix which transforms from scaled logic to view - basegfx::B2DHomMatrix aRST(basegfx::utils::createShearXRotateTranslateB2DHomMatrix( - fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); - aRST *= rViewInformation.getObjectToViewTransformation(); - - // get step widths - double fStepX(getWidth()); - double fStepY(getHeight()); - const double fMinimalStep(10.0); - - // guarantee a step width of 10.0 - if(basegfx::fTools::less(fStepX, fMinimalStep)) - { - fStepX = fMinimalStep; - } + fStepX = fMinimalStep; + } - if(basegfx::fTools::less(fStepY, fMinimalStep)) - { - fStepY = fMinimalStep; - } + if(basegfx::fTools::less(fStepY, fMinimalStep)) + { + fStepY = fMinimalStep; + } - // get relative distances in view coordinates - double fViewStepX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fStepX, 0.0)).getLength()); - double fViewStepY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fStepY)).getLength()); - double fSmallStepX(1.0), fViewSmallStepX(1.0), fSmallStepY(1.0), fViewSmallStepY(1.0); - sal_uInt32 nSmallStepsX(0), nSmallStepsY(0); + // get relative distances in view coordinates + double fViewStepX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fStepX, 0.0)).getLength()); + double fViewStepY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fStepY)).getLength()); + double fSmallStepX(1.0), fViewSmallStepX(1.0), fSmallStepY(1.0), fViewSmallStepY(1.0); + sal_uInt32 nSmallStepsX(0), nSmallStepsY(0); - // setup subdivisions - if(getSubdivisionsX()) - { - fSmallStepX = fStepX / getSubdivisionsX(); - fViewSmallStepX = fViewStepX / getSubdivisionsX(); - } + // setup subdivisions + if(getSubdivisionsX()) + { + fSmallStepX = fStepX / getSubdivisionsX(); + fViewSmallStepX = fViewStepX / getSubdivisionsX(); + } - if(getSubdivisionsY()) - { - fSmallStepY = fStepY / getSubdivisionsY(); - fViewSmallStepY = fViewStepY / getSubdivisionsY(); - } + if(getSubdivisionsY()) + { + fSmallStepY = fStepY / getSubdivisionsY(); + fViewSmallStepY = fViewStepY / getSubdivisionsY(); + } - // correct step width - while(fViewStepX < getSmallestViewDistance()) - { - fViewStepX *= 2.0; - fStepX *= 2.0; - } + // correct step width + while(fViewStepX < getSmallestViewDistance()) + { + fViewStepX *= 2.0; + fStepX *= 2.0; + } - while(fViewStepY < getSmallestViewDistance()) + while(fViewStepY < getSmallestViewDistance()) + { + fViewStepY *= 2.0; + fStepY *= 2.0; + } + + // correct small step width + if(getSubdivisionsX()) + { + while(fViewSmallStepX < getSmallestSubdivisionViewDistance()) { - fViewStepY *= 2.0; - fStepY *= 2.0; + fViewSmallStepX *= 2.0; + fSmallStepX *= 2.0; } - // correct small step width - if(getSubdivisionsX()) - { - while(fViewSmallStepX < getSmallestSubdivisionViewDistance()) - { - fViewSmallStepX *= 2.0; - fSmallStepX *= 2.0; - } + nSmallStepsX = static_cast<sal_uInt32>(fStepX / fSmallStepX); + } - nSmallStepsX = static_cast<sal_uInt32>(fStepX / fSmallStepX); + if(getSubdivisionsY()) + { + while(fViewSmallStepY < getSmallestSubdivisionViewDistance()) + { + fViewSmallStepY *= 2.0; + fSmallStepY *= 2.0; } - if(getSubdivisionsY()) - { - while(fViewSmallStepY < getSmallestSubdivisionViewDistance()) - { - fViewSmallStepY *= 2.0; - fSmallStepY *= 2.0; - } + nSmallStepsY = static_cast<sal_uInt32>(fStepY / fSmallStepY); + } - nSmallStepsY = static_cast<sal_uInt32>(fStepY / fSmallStepY); - } + // calculate extended viewport in which grid points may lie at all + basegfx::B2DRange aExtendedViewport; - // calculate extended viewport in which grid points may lie at all - basegfx::B2DRange aExtendedViewport; + if(rViewInformation.getDiscreteViewport().isEmpty()) + { + // not set, use logic size to travel over all potential grid points + aExtendedViewport = basegfx::B2DRange(0.0, 0.0, aScale.getX(), aScale.getY()); + } + else + { + // transform unit range to discrete view + aExtendedViewport = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0); + basegfx::B2DHomMatrix aTrans(rViewInformation.getObjectToViewTransformation() * getTransform()); + aExtendedViewport.transform(aTrans); - if(rViewInformation.getDiscreteViewport().isEmpty()) - { - // not set, use logic size to travel over all potential grid points - aExtendedViewport = basegfx::B2DRange(0.0, 0.0, aScale.getX(), aScale.getY()); - } - else + // intersect with visible part + aExtendedViewport.intersect(rViewInformation.getDiscreteViewport()); + + if(!aExtendedViewport.isEmpty()) { - // transform unit range to discrete view - aExtendedViewport = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0); - basegfx::B2DHomMatrix aTrans(rViewInformation.getObjectToViewTransformation() * getTransform()); + // convert back and apply scale + aTrans.invert(); + aTrans.scale(aScale.getX(), aScale.getY()); aExtendedViewport.transform(aTrans); - // intersect with visible part - aExtendedViewport.intersect(rViewInformation.getDiscreteViewport()); - - if(!aExtendedViewport.isEmpty()) - { - // convert back and apply scale - aTrans.invert(); - aTrans.scale(aScale.getX(), aScale.getY()); - aExtendedViewport.transform(aTrans); - - // crop start/end in X/Y to multiples of logical step width - const double fHalfCrossSize((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(3.0, 0.0)).getLength()); - const double fMinX(floor((aExtendedViewport.getMinX() - fHalfCrossSize) / fStepX) * fStepX); - const double fMaxX(ceil((aExtendedViewport.getMaxX() + fHalfCrossSize) / fStepX) * fStepX); - const double fMinY(floor((aExtendedViewport.getMinY() - fHalfCrossSize) / fStepY) * fStepY); - const double fMaxY(ceil((aExtendedViewport.getMaxY() + fHalfCrossSize) / fStepY) * fStepY); - - // put to aExtendedViewport and crop on object logic size - aExtendedViewport = basegfx::B2DRange( - std::max(fMinX, 0.0), - std::max(fMinY, 0.0), - std::min(fMaxX, aScale.getX()), - std::min(fMaxY, aScale.getY())); - } + // crop start/end in X/Y to multiples of logical step width + const double fHalfCrossSize((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(3.0, 0.0)).getLength()); + const double fMinX(floor((aExtendedViewport.getMinX() - fHalfCrossSize) / fStepX) * fStepX); + const double fMaxX(ceil((aExtendedViewport.getMaxX() + fHalfCrossSize) / fStepX) * fStepX); + const double fMinY(floor((aExtendedViewport.getMinY() - fHalfCrossSize) / fStepY) * fStepY); + const double fMaxY(ceil((aExtendedViewport.getMaxY() + fHalfCrossSize) / fStepY) * fStepY); + + // put to aExtendedViewport and crop on object logic size + aExtendedViewport = basegfx::B2DRange( + std::max(fMinX, 0.0), + std::max(fMinY, 0.0), + std::min(fMaxX, aScale.getX()), + std::min(fMaxY, aScale.getY())); } + } - if(!aExtendedViewport.isEmpty()) + if(aExtendedViewport.isEmpty()) + return; + + // prepare point vectors for point and cross markers + std::vector< basegfx::B2DPoint > aPositionsPoint; + std::vector< basegfx::B2DPoint > aPositionsCross; + + for(double fX(aExtendedViewport.getMinX()); fX < aExtendedViewport.getMaxX(); fX += fStepX) + { + const bool bXZero(basegfx::fTools::equalZero(fX)); + + for(double fY(aExtendedViewport.getMinY()); fY < aExtendedViewport.getMaxY(); fY += fStepY) { - // prepare point vectors for point and cross markers - std::vector< basegfx::B2DPoint > aPositionsPoint; - std::vector< basegfx::B2DPoint > aPositionsCross; + const bool bYZero(basegfx::fTools::equalZero(fY)); - for(double fX(aExtendedViewport.getMinX()); fX < aExtendedViewport.getMaxX(); fX += fStepX) + if(!bXZero && !bYZero) { - const bool bXZero(basegfx::fTools::equalZero(fX)); - - for(double fY(aExtendedViewport.getMinY()); fY < aExtendedViewport.getMaxY(); fY += fStepY) + // get discrete position and test against 3x3 area surrounding it + // since it's a cross + const double fHalfCrossSize(3.0 * 0.5); + const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fY)); + const basegfx::B2DRange aDiscreteRangeCross( + aViewPos.getX() - fHalfCrossSize, aViewPos.getY() - fHalfCrossSize, + aViewPos.getX() + fHalfCrossSize, aViewPos.getY() + fHalfCrossSize); + + if(rViewInformation.getDiscreteViewport().overlaps(aDiscreteRangeCross)) { - const bool bYZero(basegfx::fTools::equalZero(fY)); + const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); + aPositionsCross.push_back(aLogicPos); + } + } - if(!bXZero && !bYZero) - { - // get discrete position and test against 3x3 area surrounding it - // since it's a cross - const double fHalfCrossSize(3.0 * 0.5); - const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fY)); - const basegfx::B2DRange aDiscreteRangeCross( - aViewPos.getX() - fHalfCrossSize, aViewPos.getY() - fHalfCrossSize, - aViewPos.getX() + fHalfCrossSize, aViewPos.getY() + fHalfCrossSize); - - if(rViewInformation.getDiscreteViewport().overlaps(aDiscreteRangeCross)) - { - const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); - aPositionsCross.push_back(aLogicPos); - } - } + if(getSubdivisionsX() && !bYZero) + { + double fF(fX + fSmallStepX); - if(getSubdivisionsX() && !bYZero) - { - double fF(fX + fSmallStepX); - - for(sal_uInt32 a(1); a < nSmallStepsX && fF < aExtendedViewport.getMaxX(); a++, fF += fSmallStepX) - { - const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fF, fY)); - - if(rViewInformation.getDiscreteViewport().isInside(aViewPos)) - { - const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); - aPositionsPoint.push_back(aLogicPos); - } - } - } + for(sal_uInt32 a(1); a < nSmallStepsX && fF < aExtendedViewport.getMaxX(); a++, fF += fSmallStepX) + { + const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fF, fY)); - if(getSubdivisionsY() && !bXZero) + if(rViewInformation.getDiscreteViewport().isInside(aViewPos)) { - double fF(fY + fSmallStepY); - - for(sal_uInt32 a(1); a < nSmallStepsY && fF < aExtendedViewport.getMaxY(); a++, fF += fSmallStepY) - { - const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fF)); - - if(rViewInformation.getDiscreteViewport().isInside(aViewPos)) - { - const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); - aPositionsPoint.push_back(aLogicPos); - } - } + const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); + aPositionsPoint.push_back(aLogicPos); } } } - // prepare return value - const sal_uInt32 nCountPoint(aPositionsPoint.size()); - const sal_uInt32 nCountCross(aPositionsCross.size()); - - // add PointArrayPrimitive2D if point markers were added - if(nCountPoint) + if(getSubdivisionsY() && !bXZero) { - rContainer.push_back(new PointArrayPrimitive2D(aPositionsPoint, getBColor())); - } + double fF(fY + fSmallStepY); - // add MarkerArrayPrimitive2D if cross markers were added - if(nCountCross) - { - if(!getSubdivisionsX() && !getSubdivisionsY()) - { - // no subdivisions, so fall back to points at grid positions, no need to - // visualize a difference between divisions and sub-divisions - rContainer.push_back(new PointArrayPrimitive2D(aPositionsCross, getBColor())); - } - else + for(sal_uInt32 a(1); a < nSmallStepsY && fF < aExtendedViewport.getMaxY(); a++, fF += fSmallStepY) { - rContainer.push_back(new MarkerArrayPrimitive2D(aPositionsCross, getCrossMarker())); + const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fF)); + + if(rViewInformation.getDiscreteViewport().isInside(aViewPos)) + { + const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); + aPositionsPoint.push_back(aLogicPos); + } } } } } + + // prepare return value + const sal_uInt32 nCountPoint(aPositionsPoint.size()); + const sal_uInt32 nCountCross(aPositionsCross.size()); + + // add PointArrayPrimitive2D if point markers were added + if(nCountPoint) + { + rContainer.push_back(new PointArrayPrimitive2D(aPositionsPoint, getBColor())); + } + + // add MarkerArrayPrimitive2D if cross markers were added + if(!nCountCross) + return; + + if(!getSubdivisionsX() && !getSubdivisionsY()) + { + // no subdivisions, so fall back to points at grid positions, no need to + // visualize a difference between divisions and sub-divisions + rContainer.push_back(new PointArrayPrimitive2D(aPositionsCross, getBColor())); + } + else + { + rContainer.push_back(new MarkerArrayPrimitive2D(aPositionsCross, getCrossMarker())); + } } GridPrimitive2D::GridPrimitive2D( diff --git a/drawinglayer/source/primitive2d/helplineprimitive2d.cxx b/drawinglayer/source/primitive2d/helplineprimitive2d.cxx index 735b1e2785e2..86c3b88ca6d5 100644 --- a/drawinglayer/source/primitive2d/helplineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/helplineprimitive2d.cxx @@ -32,93 +32,93 @@ namespace drawinglayer::primitive2d { void HelplinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const { - if(!rViewInformation.getViewport().isEmpty() && !getDirection().equalZero()) - { - // position to view coordinates, DashLen and DashLen in logic - const basegfx::B2DPoint aViewPosition(rViewInformation.getObjectToViewTransformation() * getPosition()); + if(rViewInformation.getViewport().isEmpty() || getDirection().equalZero()) + return; + + // position to view coordinates, DashLen and DashLen in logic + const basegfx::B2DPoint aViewPosition(rViewInformation.getObjectToViewTransformation() * getPosition()); - switch(getStyle()) + switch(getStyle()) + { + default : // HelplineStyle2D::Point { - default : // HelplineStyle2D::Point - { - const double fViewFixValue(15.0); - basegfx::B2DVector aNormalizedDirection(getDirection()); - aNormalizedDirection.normalize(); - aNormalizedDirection *= fViewFixValue; - const basegfx::B2DPoint aStartA(aViewPosition - aNormalizedDirection); - const basegfx::B2DPoint aEndA(aViewPosition + aNormalizedDirection); - basegfx::B2DPolygon aLineA; - aLineA.append(aStartA); - aLineA.append(aEndA); - aLineA.transform(rViewInformation.getInverseObjectToViewTransformation()); - PolygonMarkerPrimitive2D* pNewA = new PolygonMarkerPrimitive2D(aLineA, getRGBColA(), getRGBColB(), getDiscreteDashLength()); - rContainer.push_back(pNewA); - - const basegfx::B2DVector aPerpendicularNormalizedDirection(basegfx::getPerpendicular(aNormalizedDirection)); - const basegfx::B2DPoint aStartB(aViewPosition - aPerpendicularNormalizedDirection); - const basegfx::B2DPoint aEndB(aViewPosition + aPerpendicularNormalizedDirection); - basegfx::B2DPolygon aLineB; - aLineB.append(aStartB); - aLineB.append(aEndB); - aLineB.transform(rViewInformation.getInverseObjectToViewTransformation()); - PolygonMarkerPrimitive2D* pNewB = new PolygonMarkerPrimitive2D(aLineB, getRGBColA(), getRGBColB(), getDiscreteDashLength()); - rContainer.push_back(pNewB); - - break; - } - case HelplineStyle2D::Line : - { - basegfx::B2DPolygon aLine; + const double fViewFixValue(15.0); + basegfx::B2DVector aNormalizedDirection(getDirection()); + aNormalizedDirection.normalize(); + aNormalizedDirection *= fViewFixValue; + const basegfx::B2DPoint aStartA(aViewPosition - aNormalizedDirection); + const basegfx::B2DPoint aEndA(aViewPosition + aNormalizedDirection); + basegfx::B2DPolygon aLineA; + aLineA.append(aStartA); + aLineA.append(aEndA); + aLineA.transform(rViewInformation.getInverseObjectToViewTransformation()); + PolygonMarkerPrimitive2D* pNewA = new PolygonMarkerPrimitive2D(aLineA, getRGBColA(), getRGBColB(), getDiscreteDashLength()); + rContainer.push_back(pNewA); + + const basegfx::B2DVector aPerpendicularNormalizedDirection(basegfx::getPerpendicular(aNormalizedDirection)); + const basegfx::B2DPoint aStartB(aViewPosition - aPerpendicularNormalizedDirection); + const basegfx::B2DPoint aEndB(aViewPosition + aPerpendicularNormalizedDirection); + basegfx::B2DPolygon aLineB; + aLineB.append(aStartB); + aLineB.append(aEndB); + aLineB.transform(rViewInformation.getInverseObjectToViewTransformation()); + PolygonMarkerPrimitive2D* pNewB = new PolygonMarkerPrimitive2D(aLineB, getRGBColA(), getRGBColB(), getDiscreteDashLength()); + rContainer.push_back(pNewB); + + break; + } + case HelplineStyle2D::Line : + { + basegfx::B2DPolygon aLine; - if(basegfx::areParallel(getDirection(), basegfx::B2DVector(1.0, 0.0))) + if(basegfx::areParallel(getDirection(), basegfx::B2DVector(1.0, 0.0))) + { + // parallel to X-Axis, get cuts with Y-Axes + const double fCutA((rViewInformation.getDiscreteViewport().getMinX() - aViewPosition.getX()) / getDirection().getX()); + const double fCutB((rViewInformation.getDiscreteViewport().getMaxX() - aViewPosition.getX()) / getDirection().getX()); + const basegfx::B2DPoint aPosA(aViewPosition + (fCutA * getDirection())); + const basegfx::B2DPoint aPosB(aViewPosition + (fCutB * getDirection())); + const bool bBothLeft(aPosA.getX() < rViewInformation.getDiscreteViewport().getMinX() && aPosB.getX() < rViewInformation.getDiscreteViewport().getMinX()); + const bool bBothRight(aPosA.getX() > rViewInformation.getDiscreteViewport().getMaxX() && aPosB.getX() < rViewInformation.getDiscreteViewport().getMaxX()); + + if(!bBothLeft && !bBothRight) { - // parallel to X-Axis, get cuts with Y-Axes - const double fCutA((rViewInformation.getDiscreteViewport().getMinX() - aViewPosition.getX()) / getDirection().getX()); - const double fCutB((rViewInformation.getDiscreteViewport().getMaxX() - aViewPosition.getX()) / getDirection().getX()); - const basegfx::B2DPoint aPosA(aViewPosition + (fCutA * getDirection())); - const basegfx::B2DPoint aPosB(aViewPosition + (fCutB * getDirection())); - const bool bBothLeft(aPosA.getX() < rViewInformation.getDiscreteViewport().getMinX() && aPosB.getX() < rViewInformation.getDiscreteViewport().getMinX()); - const bool bBothRight(aPosA.getX() > rViewInformation.getDiscreteViewport().getMaxX() && aPosB.getX() < rViewInformation.getDiscreteViewport().getMaxX()); - - if(!bBothLeft && !bBothRight) - { - aLine.append(aPosA); - aLine.append(aPosB); - } + aLine.append(aPosA); + aLine.append(aPosB); } - else + } + else + { + // get cuts with X-Axes + const double fCutA((rViewInformation.getDiscreteViewport().getMinY() - aViewPosition.getY()) / getDirection().getY()); + const double fCutB((rViewInformation.getDiscreteViewport().getMaxY() - aViewPosition.getY()) / getDirection().getY()); + const basegfx::B2DPoint aPosA(aViewPosition + (fCutA * getDirection())); + const basegfx::B2DPoint aPosB(aViewPosition + (fCutB * getDirection())); + const bool bBothAbove(aPosA.getY() < rViewInformation.getDiscreteViewport().getMinY() && aPosB.getY() < rViewInformation.getDiscreteViewport().getMinY()); + const bool bBothBelow(aPosA.getY() > rViewInformation.getDiscreteViewport().getMaxY() && aPosB.getY() < rViewInformation.getDiscreteViewport().getMaxY()); + + if(!bBothAbove && !bBothBelow) { - // get cuts with X-Axes - const double fCutA((rViewInformation.getDiscreteViewport().getMinY() - aViewPosition.getY()) / getDirection().getY()); - const double fCutB((rViewInformation.getDiscreteViewport().getMaxY() - aViewPosition.getY()) / getDirection().getY()); - const basegfx::B2DPoint aPosA(aViewPosition + (fCutA * getDirection())); - const basegfx::B2DPoint aPosB(aViewPosition + (fCutB * getDirection())); - const bool bBothAbove(aPosA.getY() < rViewInformation.getDiscreteViewport().getMinY() && aPosB.getY() < rViewInformation.getDiscreteViewport().getMinY()); - const bool bBothBelow(aPosA.getY() > rViewInformation.getDiscreteViewport().getMaxY() && aPosB.getY() < rViewInformation.getDiscreteViewport().getMaxY()); - - if(!bBothAbove && !bBothBelow) - { - aLine.append(aPosA); - aLine.append(aPosB); - } + aLine.append(aPosA); + aLine.append(aPosB); } + } - if(aLine.count()) + if(aLine.count()) + { + // clip against visible area + const basegfx::B2DPolyPolygon aResult(basegfx::utils::clipPolygonOnRange(aLine, rViewInformation.getDiscreteViewport(), true, true)); + + for(sal_uInt32 a(0); a < aResult.count(); a++) { - // clip against visible area - const basegfx::B2DPolyPolygon aResult(basegfx::utils::clipPolygonOnRange(aLine, rViewInformation.getDiscreteViewport(), true, true)); - - for(sal_uInt32 a(0); a < aResult.count(); a++) - { - basegfx::B2DPolygon aPart(aResult.getB2DPolygon(a)); - aPart.transform(rViewInformation.getInverseObjectToViewTransformation()); - PolygonMarkerPrimitive2D* pNew = new PolygonMarkerPrimitive2D(aPart, getRGBColA(), getRGBColB(), getDiscreteDashLength()); - rContainer.push_back(pNew); - } + basegfx::B2DPolygon aPart(aResult.getB2DPolygon(a)); + aPart.transform(rViewInformation.getInverseObjectToViewTransformation()); + PolygonMarkerPrimitive2D* pNew = new PolygonMarkerPrimitive2D(aPart, getRGBColA(), getRGBColB(), getDiscreteDashLength()); + rContainer.push_back(pNew); } - - break; } + + break; } } } diff --git a/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx b/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx index d038353db9be..d4b604e79c9f 100644 --- a/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/markerarrayprimitive2d.cxx @@ -35,37 +35,37 @@ namespace drawinglayer::primitive2d const std::vector< basegfx::B2DPoint >& rPositions = getPositions(); const sal_uInt32 nMarkerCount(rPositions.size()); - if(nMarkerCount && !getMarker().IsEmpty()) - { - // get pixel size - Size aBitmapSize(getMarker().GetSizePixel()); + if(!(nMarkerCount && !getMarker().IsEmpty())) + return; - if(aBitmapSize.Width() && aBitmapSize.Height()) - { - // get logic half pixel size - basegfx::B2DVector aLogicHalfSize(rViewInformation.getInverseObjectToViewTransformation() * - basegfx::B2DVector(aBitmapSize.getWidth() - 1.0, aBitmapSize.getHeight() - 1.0)); + // get pixel size + Size aBitmapSize(getMarker().GetSizePixel()); - // use half size for expand - aLogicHalfSize *= 0.5; + if(!(aBitmapSize.Width() && aBitmapSize.Height())) + return; - for(sal_uInt32 a(0); a < nMarkerCount; a++) - { - const basegfx::B2DPoint& rPosition(rPositions[a]); - const basegfx::B2DRange aRange(rPosition - aLogicHalfSize, rPosition + aLogicHalfSize); - basegfx::B2DHomMatrix aTransform; - - aTransform.set(0, 0, aRange.getWidth()); - aTransform.set(1, 1, aRange.getHeight()); - aTransform.set(0, 2, aRange.getMinX()); - aTransform.set(1, 2, aRange.getMinY()); - - rContainer.push_back( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(getMarker()), - aTransform)); - } - } + // get logic half pixel size + basegfx::B2DVector aLogicHalfSize(rViewInformation.getInverseObjectToViewTransformation() * + basegfx::B2DVector(aBitmapSize.getWidth() - 1.0, aBitmapSize.getHeight() - 1.0)); + + // use half size for expand + aLogicHalfSize *= 0.5; + + for(sal_uInt32 a(0); a < nMarkerCount; a++) + { + const basegfx::B2DPoint& rPosition(rPositions[a]); + const basegfx::B2DRange aRange(rPosition - aLogicHalfSize, rPosition + aLogicHalfSize); + basegfx::B2DHomMatrix aTransform; + + aTransform.set(0, 0, aRange.getWidth()); + aTransform.set(1, 1, aRange.getHeight()); + aTransform.set(0, 2, aRange.getMinX()); + aTransform.set(1, 2, aRange.getMinY()); + + rContainer.push_back( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(getMarker()), + aTransform)); } } diff --git a/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx b/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx index ae82e9389598..b7c67bf8fd0c 100644 --- a/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/pagepreviewprimitive2d.cxx @@ -35,69 +35,69 @@ namespace drawinglayer::primitive2d { Primitive2DContainer aContent(getPageContent()); - if(!aContent.empty() + if(!(!aContent.empty() && basegfx::fTools::more(getContentWidth(), 0.0) - && basegfx::fTools::more(getContentHeight(), 0.0)) + && basegfx::fTools::more(getContentHeight(), 0.0))) + return; + + // the decomposed matrix will be needed + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getTransform().decompose(aScale, aTranslate, fRotate, fShearX); + + if(!(basegfx::fTools::more(aScale.getX(), 0.0) && basegfx::fTools::more(aScale.getY(), 0.0))) + return; + + // check if content overlaps with target size and needs to be embedded with a + // clipping primitive + const basegfx::B2DRange aRealContentRange(aContent.getB2DRange(rViewInformation)); + const basegfx::B2DRange aAllowedContentRange(0.0, 0.0, getContentWidth(), getContentHeight()); + + if(!aAllowedContentRange.isInside(aRealContentRange)) { - // the decomposed matrix will be needed - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - getTransform().decompose(aScale, aTranslate, fRotate, fShearX); - - if(basegfx::fTools::more(aScale.getX(), 0.0) && basegfx::fTools::more(aScale.getY(), 0.0)) - { - // check if content overlaps with target size and needs to be embedded with a - // clipping primitive - const basegfx::B2DRange aRealContentRange(aContent.getB2DRange(rViewInformation)); - const basegfx::B2DRange aAllowedContentRange(0.0, 0.0, getContentWidth(), getContentHeight()); - - if(!aAllowedContentRange.isInside(aRealContentRange)) - { - const Primitive2DReference xReferenceA( - new MaskPrimitive2D( - basegfx::B2DPolyPolygon( - basegfx::utils::createPolygonFromRect(aAllowedContentRange)), aContent)); - aContent = Primitive2DContainer { xReferenceA }; - } - - // create a mapping from content to object. - basegfx::B2DHomMatrix aPageTrans; - - // #i101075# when keeping the aspect ratio is wanted, it is necessary to calculate - // an equidistant scaling in X and Y and a corresponding translation to - // center the output. Calculate needed scale factors - const double fScaleX(aScale.getX() / getContentWidth()); - const double fScaleY(aScale.getY() / getContentHeight()); - - // to keep the aspect, use the smaller scale and adapt missing size by translation - if(fScaleX < fScaleY) - { - // height needs to be adapted - const double fNeededHeight(aScale.getY() / fScaleX); - const double fSpaceToAdd(fNeededHeight - getContentHeight()); - - aPageTrans.translate(0.0, fSpaceToAdd * 0.5); - aPageTrans.scale(fScaleX, aScale.getY() / fNeededHeight); - } - else - { - // width needs to be adapted - const double fNeededWidth(aScale.getX() / fScaleY); - const double fSpaceToAdd(fNeededWidth - getContentWidth()); - - aPageTrans.translate(fSpaceToAdd * 0.5, 0.0); - aPageTrans.scale(aScale.getX() / fNeededWidth, fScaleY); - } - - // add the missing object transformation aspects - const basegfx::B2DHomMatrix aCombined(basegfx::utils::createShearXRotateTranslateB2DHomMatrix( - fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); - aPageTrans = aCombined * aPageTrans; - - // embed in necessary transformation to map from SdrPage to SdrPageObject - rContainer.push_back(new TransformPrimitive2D(aPageTrans, aContent)); - } + const Primitive2DReference xReferenceA( + new MaskPrimitive2D( + basegfx::B2DPolyPolygon( + basegfx::utils::createPolygonFromRect(aAllowedContentRange)), aContent)); + aContent = Primitive2DContainer { xReferenceA }; } + + // create a mapping from content to object. + basegfx::B2DHomMatrix aPageTrans; + + // #i101075# when keeping the aspect ratio is wanted, it is necessary to calculate + // an equidistant scaling in X and Y and a corresponding translation to + // center the output. Calculate needed scale factors + const double fScaleX(aScale.getX() / getContentWidth()); + const double fScaleY(aScale.getY() / getContentHeight()); + + // to keep the aspect, use the smaller scale and adapt missing size by translation + if(fScaleX < fScaleY) + { + // height needs to be adapted + const double fNeededHeight(aScale.getY() / fScaleX); + const double fSpaceToAdd(fNeededHeight - getContentHeight()); + + aPageTrans.translate(0.0, fSpaceToAdd * 0.5); + aPageTrans.scale(fScaleX, aScale.getY() / fNeededHeight); + } + else + { + // width needs to be adapted + const double fNeededWidth(aScale.getX() / fScaleY); + const double fSpaceToAdd(fNeededWidth - getContentWidth()); + + aPageTrans.translate(fSpaceToAdd * 0.5, 0.0); + aPageTrans.scale(aScale.getX() / fNeededWidth, fScaleY); + } + + // add the missing object transformation aspects + const basegfx::B2DHomMatrix aCombined(basegfx::utils::createShearXRotateTranslateB2DHomMatrix( + fShearX, fRotate, aTranslate.getX(), aTranslate.getY())); + aPageTrans = aCombined * aPageTrans; + + // embed in necessary transformation to map from SdrPage to SdrPageObject + rContainer.push_back(new TransformPrimitive2D(aPageTrans, aContent)); } PagePreviewPrimitive2D::PagePreviewPrimitive2D( diff --git a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx index 5ed50cf95ebd..ec1f9621452a 100644 --- a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx @@ -64,32 +64,32 @@ namespace drawinglayer::primitive2d const double fH(basegfx::B2DVector(aY - aTopLeft).getLength()); const double fSquare(fW * fH); - if(fSquare > 0.0) - { - // check if less than a maximum square pixels is used - static const sal_uInt32 fMaximumSquare(MAXIMUM_SQUARE_LENGTH * MAXIMUM_SQUARE_LENGTH); + if(fSquare <= 0.0) + return; - if(fSquare < fMaximumSquare) - { - // calculate needed number of tiles and check if used more than a minimum count - const texture::GeoTexSvxTiled aTiling(getReferenceRange()); - const sal_uInt32 nTiles(aTiling.getNumberOfTiles()); - static const sal_uInt32 nMinimumTiles(MINIMUM_TILES_LENGTH * MINIMUM_TILES_LENGTH); + // check if less than a maximum square pixels is used + static const sal_uInt32 fMaximumSquare(MAXIMUM_SQUARE_LENGTH * MAXIMUM_SQUARE_LENGTH); - if(nTiles >= nMinimumTiles) - { - rWidth = basegfx::fround(ceil(fW)); - rHeight = basegfx::fround(ceil(fH)); - static const sal_uInt32 fMinimumSquare(MINIMUM_SQUARE_LENGTH * MINIMUM_SQUARE_LENGTH); - - if(fSquare < fMinimumSquare) - { - const double fRel(fW/fH); - rWidth = basegfx::fround(sqrt(fMinimumSquare * fRel)); - rHeight = basegfx::fround(sqrt(fMinimumSquare / fRel)); - } - } - } + if(fSquare >= fMaximumSquare) + return; + + // calculate needed number of tiles and check if used more than a minimum count + const texture::GeoTexSvxTiled aTiling(getReferenceRange()); + const sal_uInt32 nTiles(aTiling.getNumberOfTiles()); + static const sal_uInt32 nMinimumTiles(MINIMUM_TILES_LENGTH * MINIMUM_TILES_LENGTH); + + if(nTiles < nMinimumTiles) + return; + + rWidth = basegfx::fround(ceil(fW)); + rHeight = basegfx::fround(ceil(fH)); + static const sal_uInt32 fMinimumSquare(MINIMUM_SQUARE_LENGTH * MINIMUM_SQUARE_LENGTH); + + if(fSquare < fMinimumSquare) + { + const double fRel(fW/fH); + rWidth = basegfx::fround(sqrt(fMinimumSquare * fRel)); + rHeight = basegfx::fround(sqrt(fMinimumSquare / fRel)); } } @@ -162,59 +162,58 @@ namespace drawinglayer::primitive2d { Primitive2DContainer aRetval; - if(!getChildren().empty()) + if(getChildren().empty()) + return; + + if(!(!getReferenceRange().isEmpty() && getReferenceRange().getWidth() > 0.0 && getReferenceRange().getHeight() > 0.0)) + return; + + const basegfx::B2DRange aMaskRange(getMask().getB2DRange()); + + if(!(!aMaskRange.isEmpty() && aMaskRange.getWidth() > 0.0 && aMaskRange.getHeight() > 0.0)) + return; + + // create tiling matrices + std::vector< basegfx::B2DHomMatrix > aMatrices; + texture::GeoTexSvxTiled aTiling(getReferenceRange()); + + aTiling.appendTransformations(aMatrices); + + // create content + const Primitive2DContainer aContent(createContent(rViewInformation)); + + // resize result + aRetval.resize(aMatrices.size()); + + // create one primitive for each matrix + for(size_t a(0); a < aMatrices.size(); a++) { - if(!getReferenceRange().isEmpty() && getReferenceRange().getWidth() > 0.0 && getReferenceRange().getHeight() > 0.0) - { - const basegfx::B2DRange aMaskRange(getMask().getB2DRange()); + aRetval[a] = new TransformPrimitive2D( + aMatrices[a], + aContent); + } - if(!aMaskRange.isEmpty() && aMaskRange.getWidth() > 0.0 && aMaskRange.getHeight() > 0.0) - { - // create tiling matrices - std::vector< basegfx::B2DHomMatrix > aMatrices; - texture::GeoTexSvxTiled aTiling(getReferenceRange()); - - aTiling.appendTransformations(aMatrices); - - // create content - const Primitive2DContainer aContent(createContent(rViewInformation)); - - // resize result - aRetval.resize(aMatrices.size()); - - // create one primitive for each matrix - for(size_t a(0); a < aMatrices.size(); a++) - { - aRetval[a] = new TransformPrimitive2D( - aMatrices[a], - aContent); - } - - // transform result which is in unit coordinates to mask's object coordinates - { - const basegfx::B2DHomMatrix aMaskTransform( - basegfx::utils::createScaleTranslateB2DHomMatrix( - aMaskRange.getRange(), - aMaskRange.getMinimum())); - - const Primitive2DReference xRef( - new TransformPrimitive2D( - aMaskTransform, - aRetval)); - - aRetval = Primitive2DContainer { xRef }; - } - - // embed result in mask - { - rContainer.push_back( - new MaskPrimitive2D( - getMask(), - aRetval)); - } + // transform result which is in unit coordinates to mask's object coordinates + { + const basegfx::B2DHomMatrix aMaskTransform( + basegfx::utils::createScaleTranslateB2DHomMatrix( + aMaskRange.getRange(), + aMaskRange.getMinimum())); - } - } + const Primitive2DReference xRef( + new TransformPrimitive2D( + aMaskTransform, + aRetval)); + + aRetval = Primitive2DContainer { xRef }; + } + + // embed result in mask + { + rContainer.push_back( + new MaskPrimitive2D( + getMask(), + aRetval)); } } diff --git a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx index 3331bbf53c5c..0251910e8252 100644 --- a/drawinglayer/source/primitive2d/polygonprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/polygonprimitive2d.cxx @@ -200,68 +200,68 @@ namespace drawinglayer { void PolygonStrokePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if(getB2DPolygon().count()) - { - // #i102241# try to simplify before usage - const basegfx::B2DPolygon aB2DPolygon(basegfx::utils::simplifyCurveSegments(getB2DPolygon())); - basegfx::B2DPolyPolygon aHairLinePolyPolygon; + if(!getB2DPolygon().count()) + return; - if(getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen()) - { - // no line dashing, just copy - aHairLinePolyPolygon.append(aB2DPolygon); - } - else - { - // apply LineStyle - basegfx::utils::applyLineDashing( - aB2DPolygon, getStrokeAttribute().getDotDashArray(), - &aHairLinePolyPolygon, nullptr, getStrokeAttribute().getFullDotDashLen()); - } + // #i102241# try to simplify before usage + const basegfx::B2DPolygon aB2DPolygon(basegfx::utils::simplifyCurveSegments(getB2DPolygon())); + basegfx::B2DPolyPolygon aHairLinePolyPolygon; + + if(getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen()) + { + // no line dashing, just copy + aHairLinePolyPolygon.append(aB2DPolygon); + } + else + { + // apply LineStyle + basegfx::utils::applyLineDashing( + aB2DPolygon, getStrokeAttribute().getDotDashArray(), + &aHairLinePolyPolygon, nullptr, getStrokeAttribute().getFullDotDashLen()); + } - const sal_uInt32 nCount(aHairLinePolyPolygon.count()); + const sal_uInt32 nCount(aHairLinePolyPolygon.count()); - if(!getLineAttribute().isDefault() && getLineAttribute().getWidth()) + if(!getLineAttribute().isDefault() && getLineAttribute().getWidth()) + { + // create fat line data + const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0); + const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin()); + const css::drawing::LineCap aLineCap(getLineAttribute().getLineCap()); + basegfx::B2DPolyPolygon aAreaPolyPolygon; + const double fMiterMinimumAngle(getLineAttribute().getMiterMinimumAngle()); + + for(sal_uInt32 a(0); a < nCount; a++) { - // create fat line data - const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0); - const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin()); - const css::drawing::LineCap aLineCap(getLineAttribute().getLineCap()); - basegfx::B2DPolyPolygon aAreaPolyPolygon; - const double fMiterMinimumAngle(getLineAttribute().getMiterMinimumAngle()); - - for(sal_uInt32 a(0); a < nCount; a++) - { - // New version of createAreaGeometry; now creates bezier polygons - aAreaPolyPolygon.append(basegfx::utils::createAreaGeometry( - aHairLinePolyPolygon.getB2DPolygon(a), - fHalfLineWidth, - aLineJoin, - aLineCap, - basegfx::deg2rad(12.5) /* default fMaxAllowedAngle*/ , - 0.4 /* default fMaxPartOfEdge*/ , - fMiterMinimumAngle)); - } - - // create primitive - for(sal_uInt32 b(0); b < aAreaPolyPolygon.count(); b++) - { - // put into single polyPolygon primitives to make clear that this is NOT meant - // to be painted as a single tools::PolyPolygon (XORed as fill rule). Alternatively, a - // melting process may be used here one day. - const basegfx::B2DPolyPolygon aNewPolyPolygon(aAreaPolyPolygon.getB2DPolygon(b)); - const basegfx::BColor aColor(getLineAttribute().getColor()); - rContainer.push_back(new PolyPolygonColorPrimitive2D(aNewPolyPolygon, aColor)); - } + // New version of createAreaGeometry; now creates bezier polygons + aAreaPolyPolygon.append(basegfx::utils::createAreaGeometry( + aHairLinePolyPolygon.getB2DPolygon(a), + fHalfLineWidth, + aLineJoin, + aLineCap, + basegfx::deg2rad(12.5) /* default fMaxAllowedAngle*/ , + 0.4 /* default fMaxPartOfEdge*/ , + fMiterMinimumAngle)); } - else + + // create primitive + for(sal_uInt32 b(0); b < aAreaPolyPolygon.count(); b++) { - rContainer.push_back( - new PolyPolygonHairlinePrimitive2D( - aHairLinePolyPolygon, - getLineAttribute().getColor())); + // put into single polyPolygon primitives to make clear that this is NOT meant + // to be painted as a single tools::PolyPolygon (XORed as fill rule). Alternatively, a + // melting process may be used here one day. + const basegfx::B2DPolyPolygon aNewPolyPolygon(aAreaPolyPolygon.getB2DPolygon(b)); + const basegfx::BColor aColor(getLineAttribute().getColor()); + rContainer.push_back(new PolyPolygonColorPrimitive2D(aNewPolyPolygon, aColor)); } } + else + { + rContainer.push_back( + new PolyPolygonHairlinePrimitive2D( + aHairLinePolyPolygon, + getLineAttribute().getColor())); + } } PolygonStrokePrimitive2D::PolygonStrokePrimitive2D( @@ -380,22 +380,22 @@ namespace drawinglayer void PolygonWavePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if(getB2DPolygon().count()) - { - const bool bHasWidth(!basegfx::fTools::equalZero(getWaveWidth())); - const bool bHasHeight(!basegfx::fTools::equalZero(getWaveHeight())); + if(!getB2DPolygon().count()) + return; - if(bHasWidth && bHasHeight) - { - // create waveline curve - const basegfx::B2DPolygon aWaveline(basegfx::utils::createWaveline(getB2DPolygon(), getWaveWidth(), getWaveHeight())); - rContainer.push_back(new PolygonStrokePrimitive2D(aWaveline, getLineAttribute(), getStrokeAttribute())); - } - else - { - // flat waveline, decompose to simple line primitive - rContainer.push_back(new PolygonStrokePrimitive2D(getB2DPolygon(), getLineAttribute(), getStrokeAttribute())); - } + const bool bHasWidth(!basegfx::fTools::equalZero(getWaveWidth())); + const bool bHasHeight(!basegfx::fTools::equalZero(getWaveHeight())); + + if(bHasWidth && bHasHeight) + { + // create waveline curve + const basegfx::B2DPolygon aWaveline(basegfx::utils::createWaveline(getB2DPolygon(), getWaveWidth(), getWaveHeight())); + rContainer.push_back(new PolygonStrokePrimitive2D(aWaveline, getLineAttribute(), getStrokeAttribute())); + } + else + { + // flat waveline, decompose to simple line primitive + rContainer.push_back(new PolygonStrokePrimitive2D(getB2DPolygon(), getLineAttribute(), getStrokeAttribute())); } } diff --git a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx index c0c0fec7d41a..e58c05e406af 100644 --- a/drawinglayer/source/primitive2d/sceneprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/sceneprimitive2d.cxx @@ -236,255 +236,255 @@ namespace drawinglayer::primitive2d calculateDiscreteSizes(rViewInformation, aDiscreteRange, aVisibleDiscreteRange, aUnitVisibleRange); - if(!aVisibleDiscreteRange.isEmpty()) + if(aVisibleDiscreteRange.isEmpty()) + return; + + // test if discrete view size (pixel) maybe too big and limit it + double fViewSizeX(aVisibleDiscreteRange.getWidth()); + double fViewSizeY(aVisibleDiscreteRange.getHeight()); + const double fViewVisibleArea(fViewSizeX * fViewSizeY); + const SvtOptionsDrawinglayer aDrawinglayerOpt; + const double fMaximumVisibleArea(aDrawinglayerOpt.GetQuadratic3DRenderLimit()); + double fReduceFactor(1.0); + + if(fViewVisibleArea > fMaximumVisibleArea) { - // test if discrete view size (pixel) maybe too big and limit it - double fViewSizeX(aVisibleDiscreteRange.getWidth()); - double fViewSizeY(aVisibleDiscreteRange.getHeight()); - const double fViewVisibleArea(fViewSizeX * fViewSizeY); - const SvtOptionsDrawinglayer aDrawinglayerOpt; - const double fMaximumVisibleArea(aDrawinglayerOpt.GetQuadratic3DRenderLimit()); - double fReduceFactor(1.0); - - if(fViewVisibleArea > fMaximumVisibleArea) - { - fReduceFactor = sqrt(fMaximumVisibleArea / fViewVisibleArea); - fViewSizeX *= fReduceFactor; - fViewSizeY *= fReduceFactor; - } + fReduceFactor = sqrt(fMaximumVisibleArea / fViewVisibleArea); + fViewSizeX *= fReduceFactor; + fViewSizeY *= fReduceFactor; + } - if(rViewInformation.getReducedDisplayQuality()) + if(rViewInformation.getReducedDisplayQuality()) + { + // when reducing the visualisation is allowed (e.g. an OverlayObject + // only needed for dragging), reduce resolution extra + // to speed up dragging interactions + const double fArea(fViewSizeX * fViewSizeY); + if (fArea != 0.0) { - // when reducing the visualisation is allowed (e.g. an OverlayObject - // only needed for dragging), reduce resolution extra - // to speed up dragging interactions - const double fArea(fViewSizeX * fViewSizeY); - if (fArea != 0.0) - { - double fReducedVisualisationFactor(1.0 / (sqrt(fArea) * (1.0 / 170.0))); - - if(fReducedVisualisationFactor > 1.0) - { - fReducedVisualisationFactor = 1.0; - } - else if(fReducedVisualisationFactor < 0.20) - { - fReducedVisualisationFactor = 0.20; - } + double fReducedVisualisationFactor(1.0 / (sqrt(fArea) * (1.0 / 170.0))); - if(fReducedVisualisationFactor != 1.0) - { - fReduceFactor *= fReducedVisualisationFactor; - } + if(fReducedVisualisationFactor > 1.0) + { + fReducedVisualisationFactor = 1.0; } - } - - // determine the oversample value - static const sal_uInt16 nDefaultOversampleValue(3); - const sal_uInt16 nOversampleValue(aDrawinglayerOpt.IsAntiAliasing() ? nDefaultOversampleValue : 0); - - geometry::ViewInformation3D aViewInformation3D(getViewInformation3D()); - { - // calculate a transformation from DiscreteRange to evtl. rotated/sheared content. - // Start with full transformation from object to discrete units - basegfx::B2DHomMatrix aObjToUnit(rViewInformation.getObjectToViewTransformation() * getObjectTransformation()); - - // bring to unit coordinates by applying inverse DiscreteRange - aObjToUnit.translate(-aDiscreteRange.getMinX(), -aDiscreteRange.getMinY()); - if (aDiscreteRange.getWidth() != 0.0 && aDiscreteRange.getHeight() != 0.0) + else if(fReducedVisualisationFactor < 0.20) { - aObjToUnit.scale(1.0 / aDiscreteRange.getWidth(), 1.0 / aDiscreteRange.getHeight()); + fReducedVisualisationFactor = 0.20; } - // calculate transformed user coordinate system - const basegfx::B2DPoint aStandardNull(0.0, 0.0); - const basegfx::B2DPoint aUnitRangeTopLeft(aObjToUnit * aStandardNull); - const basegfx::B2DVector aStandardXAxis(1.0, 0.0); - const basegfx::B2DVector aUnitRangeXAxis(aObjToUnit * aStandardXAxis); - const basegfx::B2DVector aStandardYAxis(0.0, 1.0); - const basegfx::B2DVector aUnitRangeYAxis(aObjToUnit * aStandardYAxis); - - if(!aUnitRangeTopLeft.equal(aStandardNull) || !aUnitRangeXAxis.equal(aStandardXAxis) || !aUnitRangeYAxis.equal(aStandardYAxis)) + if(fReducedVisualisationFactor != 1.0) { - // build transformation from unit range to user coordinate system; the unit range - // X and Y axes are the column vectors, the null point is the offset - basegfx::B2DHomMatrix aUnitRangeToUser; - - aUnitRangeToUser.set3x2( - aUnitRangeXAxis.getX(), aUnitRangeYAxis.getX(), aUnitRangeTopLeft.getX(), - aUnitRangeXAxis.getY(), aUnitRangeYAxis.getY(), aUnitRangeTopLeft.getY()); - - // decompose to allow to apply this to the 3D transformation - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - aUnitRangeToUser.decompose(aScale, aTranslate, fRotate, fShearX); - - // apply before DeviceToView and after Projection, 3D is in range [-1.0 .. 1.0] in X,Y and Z - // and not yet flipped in Y - basegfx::B3DHomMatrix aExtendedProjection(aViewInformation3D.getProjection()); - - // bring to unit coordinates, flip Y, leave Z unchanged - aExtendedProjection.scale(0.5, -0.5, 1.0); - aExtendedProjection.translate(0.5, 0.5, 0.0); - - // apply extra; Y is flipped now, go with positive shear and rotate values - aExtendedProjection.scale(aScale.getX(), aScale.getY(), 1.0); - aExtendedProjection.shearXZ(fShearX, 0.0); - aExtendedProjection.rotate(0.0, 0.0, fRotate); - aExtendedProjection.translate(aTranslate.getX(), aTranslate.getY(), 0.0); - - // back to state after projection - aExtendedProjection.translate(-0.5, -0.5, 0.0); - aExtendedProjection.scale(2.0, -2.0, 1.0); - - aViewInformation3D = geometry::ViewInformation3D( - aViewInformation3D.getObjectTransformation(), - aViewInformation3D.getOrientation(), - aExtendedProjection, - aViewInformation3D.getDeviceToView(), - aViewInformation3D.getViewTime(), - aViewInformation3D.getExtendedInformationSequence()); + fReduceFactor *= fReducedVisualisationFactor; } } + } - // calculate logic render size in world coordinates for usage in renderer - const basegfx::B2DHomMatrix& aInverseOToV(rViewInformation.getInverseObjectToViewTransformation()); - const double fLogicX((aInverseOToV * basegfx::B2DVector(aDiscreteRange.getWidth() * fReduceFactor, 0.0)).getLength()); - const double fLogicY((aInverseOToV * basegfx::B2DVector(0.0, aDiscreteRange.getHeight() * fReduceFactor)).getLength()); + // determine the oversample value + static const sal_uInt16 nDefaultOversampleValue(3); + const sal_uInt16 nOversampleValue(aDrawinglayerOpt.IsAntiAliasing() ? nDefaultOversampleValue : 0); - // generate ViewSizes - const double fFullViewSizeX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fLogicX, 0.0)).getLength()); - const double fFullViewSizeY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fLogicY)).getLength()); + geometry::ViewInformation3D aViewInformation3D(getViewInformation3D()); + { + // calculate a transformation from DiscreteRange to evtl. rotated/sheared content. + // Start with full transformation from object to discrete units + basegfx::B2DHomMatrix aObjToUnit(rViewInformation.getObjectToViewTransformation() * getObjectTransformation()); + + // bring to unit coordinates by applying inverse DiscreteRange + aObjToUnit.translate(-aDiscreteRange.getMinX(), -aDiscreteRange.getMinY()); + if (aDiscreteRange.getWidth() != 0.0 && aDiscreteRange.getHeight() != 0.0) + { + aObjToUnit.scale(1.0 / aDiscreteRange.getWidth(), 1.0 / aDiscreteRange.getHeight()); + } - // generate RasterWidth and RasterHeight for visible part - const sal_Int32 nRasterWidth(basegfx::fround(fFullViewSizeX * aUnitVisibleRange.getWidth()) + 1); - const sal_Int32 nRasterHeight(basegfx::fround(fFullViewSizeY * aUnitVisibleRange.getHeight()) + 1); + // calculate transformed user coordinate system + const basegfx::B2DPoint aStandardNull(0.0, 0.0); + const basegfx::B2DPoint aUnitRangeTopLeft(aObjToUnit * aStandardNull); + const basegfx::B2DVector aStandardXAxis(1.0, 0.0); + const basegfx::B2DVector aUnitRangeXAxis(aObjToUnit * aStandardXAxis); + const basegfx::B2DVector aStandardYAxis(0.0, 1.0); + const basegfx::B2DVector aUnitRangeYAxis(aObjToUnit * aStandardYAxis); - if(nRasterWidth && nRasterHeight) + if(!aUnitRangeTopLeft.equal(aStandardNull) || !aUnitRangeXAxis.equal(aStandardXAxis) || !aUnitRangeYAxis.equal(aStandardYAxis)) { - // create view unit buffer - basegfx::BZPixelRaster aBZPixelRaster( - nOversampleValue ? nRasterWidth * nOversampleValue : nRasterWidth, - nOversampleValue ? nRasterHeight * nOversampleValue : nRasterHeight); + // build transformation from unit range to user coordinate system; the unit range + // X and Y axes are the column vectors, the null point is the offset + basegfx::B2DHomMatrix aUnitRangeToUser; + + aUnitRangeToUser.set3x2( + aUnitRangeXAxis.getX(), aUnitRangeYAxis.getX(), aUnitRangeTopLeft.getX(), + aUnitRangeXAxis.getY(), aUnitRangeYAxis.getY(), aUnitRangeTopLeft.getY()); + + // decompose to allow to apply this to the 3D transformation + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + aUnitRangeToUser.decompose(aScale, aTranslate, fRotate, fShearX); + + // apply before DeviceToView and after Projection, 3D is in range [-1.0 .. 1.0] in X,Y and Z + // and not yet flipped in Y + basegfx::B3DHomMatrix aExtendedProjection(aViewInformation3D.getProjection()); + + // bring to unit coordinates, flip Y, leave Z unchanged + aExtendedProjection.scale(0.5, -0.5, 1.0); + aExtendedProjection.translate(0.5, 0.5, 0.0); + + // apply extra; Y is flipped now, go with positive shear and rotate values + aExtendedProjection.scale(aScale.getX(), aScale.getY(), 1.0); + aExtendedProjection.shearXZ(fShearX, 0.0); + aExtendedProjection.rotate(0.0, 0.0, fRotate); + aExtendedProjection.translate(aTranslate.getX(), aTranslate.getY(), 0.0); + + // back to state after projection + aExtendedProjection.translate(-0.5, -0.5, 0.0); + aExtendedProjection.scale(2.0, -2.0, 1.0); + + aViewInformation3D = geometry::ViewInformation3D( + aViewInformation3D.getObjectTransformation(), + aViewInformation3D.getOrientation(), + aExtendedProjection, + aViewInformation3D.getDeviceToView(), + aViewInformation3D.getViewTime(), + aViewInformation3D.getExtendedInformationSequence()); + } + } - // check for parallel execution possibilities - static bool bMultithreadAllowed = false; // loplugin:constvars:ignore - sal_Int32 nThreadCount(0); - comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool()); + // calculate logic render size in world coordinates for usage in renderer + const basegfx::B2DHomMatrix& aInverseOToV(rViewInformation.getInverseObjectToViewTransformation()); + const double fLogicX((aInverseOToV * basegfx::B2DVector(aDiscreteRange.getWidth() * fReduceFactor, 0.0)).getLength()); + const double fLogicY((aInverseOToV * basegfx::B2DVector(0.0, aDiscreteRange.getHeight() * fReduceFactor)).getLength()); - if(bMultithreadAllowed) - { - nThreadCount = rThreadPool.getWorkerCount(); + // generate ViewSizes + const double fFullViewSizeX((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(fLogicX, 0.0)).getLength()); + const double fFullViewSizeY((rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(0.0, fLogicY)).getLength()); - if(nThreadCount > 1) - { - // at least use 10px per processor, so limit number of processors to - // target pixel size divided by 10 (which might be zero what is okay) - nThreadCount = std::min(nThreadCount, nRasterHeight / 10); - } - } + // generate RasterWidth and RasterHeight for visible part + const sal_Int32 nRasterWidth(basegfx::fround(fFullViewSizeX * aUnitVisibleRange.getWidth()) + 1); + const sal_Int32 nRasterHeight(basegfx::fround(fFullViewSizeY * aUnitVisibleRange.getHeight()) + 1); - if(nThreadCount > 1) - { - class Executor : public comphelper::ThreadTask - { - private: - std::unique_ptr<processor3d::ZBufferProcessor3D> mpZBufferProcessor3D; - const primitive3d::Primitive3DContainer& mrChildren3D; - - public: - explicit Executor( - std::shared_ptr<comphelper::ThreadTaskTag> const & rTag, - std::unique_ptr<processor3d::ZBufferProcessor3D> pZBufferProcessor3D, - const primitive3d::Primitive3DContainer& rChildren3D) - : comphelper::ThreadTask(rTag), - mpZBufferProcessor3D(std::move(pZBufferProcessor3D)), - mrChildren3D(rChildren3D) - { - } + if(!(nRasterWidth && nRasterHeight)) + return; - virtual void doWork() override - { - mpZBufferProcessor3D->process(mrChildren3D); - mpZBufferProcessor3D->finish(); - mpZBufferProcessor3D.reset(); - } - }; + // create view unit buffer + basegfx::BZPixelRaster aBZPixelRaster( + nOversampleValue ? nRasterWidth * nOversampleValue : nRasterWidth, + nOversampleValue ? nRasterHeight * nOversampleValue : nRasterHeight); - const sal_uInt32 nLinesPerThread(aBZPixelRaster.getHeight() / nThreadCount); - std::shared_ptr<comphelper::ThreadTaskTag> aTag = comphelper::ThreadPool::createThreadTaskTag(); + // check for parallel execution possibilities + static bool bMultithreadAllowed = false; // loplugin:constvars:ignore + sal_Int32 nThreadCount(0); + comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool()); - for(sal_Int32 a(0); a < nThreadCount; a++) - { - std::unique_ptr<processor3d::ZBufferProcessor3D> pNewZBufferProcessor3D(new processor3d::ZBufferProcessor3D( - aViewInformation3D, - getSdrSceneAttribute(), - getSdrLightingAttribute(), - aUnitVisibleRange, - nOversampleValue, - fFullViewSizeX, - fFullViewSizeY, - aBZPixelRaster, - nLinesPerThread * a, - a + 1 == nThreadCount ? aBZPixelRaster.getHeight() : nLinesPerThread * (a + 1))); - std::unique_ptr<Executor> pExecutor(new Executor(aTag, std::move(pNewZBufferProcessor3D), getChildren3D())); - rThreadPool.pushTask(std::move(pExecutor)); - } + if(bMultithreadAllowed) + { + nThreadCount = rThreadPool.getWorkerCount(); + + if(nThreadCount > 1) + { + // at least use 10px per processor, so limit number of processors to + // target pixel size divided by 10 (which might be zero what is okay) + nThreadCount = std::min(nThreadCount, nRasterHeight / 10); + } + } - rThreadPool.waitUntilDone(aTag); + if(nThreadCount > 1) + { + class Executor : public comphelper::ThreadTask + { + private: + std::unique_ptr<processor3d::ZBufferProcessor3D> mpZBufferProcessor3D; + const primitive3d::Primitive3DContainer& mrChildren3D; + + public: + explicit Executor( + std::shared_ptr<comphelper::ThreadTaskTag> const & rTag, + std::unique_ptr<processor3d::ZBufferProcessor3D> pZBufferProcessor3D, + const primitive3d::Primitive3DContainer& rChildren3D) + : comphelper::ThreadTask(rTag), + mpZBufferProcessor3D(std::move(pZBufferProcessor3D)), + mrChildren3D(rChildren3D) + { } - else + + virtual void doWork() override { - // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process - processor3d::ZBufferProcessor3D aZBufferProcessor3D( - aViewInformation3D, - getSdrSceneAttribute(), - getSdrLightingAttribute(), - aUnitVisibleRange, - nOversampleValue, - fFullViewSizeX, - fFullViewSizeY, - aBZPixelRaster, - 0, - aBZPixelRaster.getHeight()); - - aZBufferProcessor3D.process(getChildren3D()); - aZBufferProcessor3D.finish(); + mpZBufferProcessor3D->process(mrChildren3D); + mpZBufferProcessor3D->finish(); + mpZBufferProcessor3D.reset(); } + }; - const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = BPixelRasterToBitmapEx(aBZPixelRaster, nOversampleValue); - const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); + const sal_uInt32 nLinesPerThread(aBZPixelRaster.getHeight() / nThreadCount); + std::shared_ptr<comphelper::ThreadTaskTag> aTag = comphelper::ThreadPool::createThreadTaskTag(); - if(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight()) - { - // create transform for the created bitmap in discrete coordinates first. - basegfx::B2DHomMatrix aNew2DTransform; + for(sal_Int32 a(0); a < nThreadCount; a++) + { + std::unique_ptr<processor3d::ZBufferProcessor3D> pNewZBufferProcessor3D(new processor3d::ZBufferProcessor3D( + aViewInformation3D, + getSdrSceneAttribute(), + getSdrLightingAttribute(), + aUnitVisibleRange, + nOversampleValue, + fFullViewSizeX, + fFullViewSizeY, + aBZPixelRaster, + nLinesPerThread * a, + a + 1 == nThreadCount ? aBZPixelRaster.getHeight() : nLinesPerThread * (a + 1))); + std::unique_ptr<Executor> pExecutor(new Executor(aTag, std::move(pNewZBufferProcessor3D), getChildren3D())); + rThreadPool.pushTask(std::move(pExecutor)); + } - aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth()); - aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight()); - aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX()); - aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY()); + rThreadPool.waitUntilDone(aTag); + } + else + { + // use default 3D primitive processor to create BitmapEx for aUnitVisiblePart and process + processor3d::ZBufferProcessor3D aZBufferProcessor3D( + aViewInformation3D, + getSdrSceneAttribute(), + getSdrLightingAttribute(), + aUnitVisibleRange, + nOversampleValue, + fFullViewSizeX, + fFullViewSizeY, + aBZPixelRaster, + 0, + aBZPixelRaster.getHeight()); + + aZBufferProcessor3D.process(getChildren3D()); + aZBufferProcessor3D.finish(); + } - // transform back to world coordinates for usage in primitive creation - aNew2DTransform *= aInverseOToV; + const_cast< ScenePrimitive2D* >(this)->maOldRenderedBitmap = BPixelRasterToBitmapEx(aBZPixelRaster, nOversampleValue); + const Size aBitmapSizePixel(maOldRenderedBitmap.GetSizePixel()); - // create bitmap primitive and add - rContainer.push_back( - new BitmapPrimitive2D( - VCLUnoHelper::CreateVCLXBitmap(maOldRenderedBitmap), - aNew2DTransform)); + if(!(aBitmapSizePixel.getWidth() && aBitmapSizePixel.getHeight())) + return; - // test: Allow to add an outline in the debugger when tests are needed - static bool bAddOutlineToCreated3DSceneRepresentation(false); // loplugin:constvars:ignore + // create transform for the created bitmap in discrete coordinates first. + basegfx::B2DHomMatrix aNew2DTransform; - if(bAddOutlineToCreated3DSceneRepresentation) - { - basegfx::B2DPolygon aOutline(basegfx::utils::createUnitPolygon()); - aOutline.transform(aNew2DTransform); - rContainer.push_back(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0))); - } - } - } + aNew2DTransform.set(0, 0, aVisibleDiscreteRange.getWidth()); + aNew2DTransform.set(1, 1, aVisibleDiscreteRange.getHeight()); + aNew2DTransform.set(0, 2, aVisibleDiscreteRange.getMinX()); + aNew2DTransform.set(1, 2, aVisibleDiscreteRange.getMinY()); + + // transform back to world coordinates for usage in primitive creation + aNew2DTransform *= aInverseOToV; + + // create bitmap primitive and add + rContainer.push_back( + new BitmapPrimitive2D( + VCLUnoHelper::CreateVCLXBitmap(maOldRenderedBitmap), + aNew2DTransform)); + + // test: Allow to add an outline in the debugger when tests are needed + static bool bAddOutlineToCreated3DSceneRepresentation(false); // loplugin:constvars:ignore + + if(bAddOutlineToCreated3DSceneRepresentation) + { + basegfx::B2DPolygon aOutline(basegfx::utils::createUnitPolygon()); + aOutline.transform(aNew2DTransform); + rContainer.push_back(new PolygonHairlinePrimitive2D(aOutline, basegfx::BColor(1.0, 0.0, 0.0))); } } diff --git a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx index ba239ee02123..8cb8311494a5 100644 --- a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx @@ -61,21 +61,21 @@ namespace drawinglayer::primitive2d void ShadowPrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if(!getChildren().empty()) - { - // create a modifiedColorPrimitive containing the shadow color and the content - const basegfx::BColorModifierSharedPtr aBColorModifier = - std::make_shared<basegfx::BColorModifier_replace>( - getShadowColor()); - const Primitive2DReference xRefA( - new ModifiedColorPrimitive2D( - getChildren(), - aBColorModifier)); - const Primitive2DContainer aSequenceB { xRefA }; + if(getChildren().empty()) + return; - // build transformed primitiveVector with shadow offset and add to target - rVisitor.append(new TransformPrimitive2D(getShadowTransform(), aSequenceB)); - } + // create a modifiedColorPrimitive containing the shadow color and the content + const basegfx::BColorModifierSharedPtr aBColorModifier = + std::make_shared<basegfx::BColorModifier_replace>( + getShadowColor()); + const Primitive2DReference xRefA( + new ModifiedColorPrimitive2D( + getChildren(), + aBColorModifier)); + const Primitive2DContainer aSequenceB { xRefA }; + + // build transformed primitiveVector with shadow offset and add to target + rVisitor.append(new TransformPrimitive2D(getShadowTransform(), aSequenceB)); } // provide unique ID diff --git a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx index 94346d9e5b90..d3e32e22ea46 100644 --- a/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/svggradientprimitive2d.cxx @@ -313,31 +313,31 @@ namespace drawinglayer::primitive2d const Primitive2DContainer aTargetColorEntries(rTargetColor.maybeInvert(bInvert)); const Primitive2DContainer aTargetOpacityEntries(rTargetOpacity.maybeInvert(bInvert)); - if(!aTargetColorEntries.empty()) - { - Primitive2DReference xRefContent; + if(aTargetColorEntries.empty()) + return; - if(!aTargetOpacityEntries.empty()) - { - const Primitive2DReference xRefOpacity = new TransparencePrimitive2D( - aTargetColorEntries, - aTargetOpacityEntries); + Primitive2DReference xRefContent; - xRefContent = new TransformPrimitive2D( - rUnitGradientToObject, - Primitive2DContainer { xRefOpacity }); - } - else - { - xRefContent = new TransformPrimitive2D( - rUnitGradientToObject, - aTargetColorEntries); - } + if(!aTargetOpacityEntries.empty()) + { + const Primitive2DReference xRefOpacity = new TransparencePrimitive2D( + aTargetColorEntries, + aTargetOpacityEntries); - rContainer.push_back(new MaskPrimitive2D( - getPolyPolygon(), - Primitive2DContainer { xRefContent })); + xRefContent = new TransformPrimitive2D( + rUnitGradientToObject, + Primitive2DContainer { xRefOpacity }); + } + else + { + xRefContent = new TransformPrimitive2D( + rUnitGradientToObject, + aTargetColorEntries); } + + rContainer.push_back(new MaskPrimitive2D( + getPolyPolygon(), + Primitive2DContainer { xRefContent })); } SvgGradientHelper::SvgGradientHelper( @@ -377,21 +377,21 @@ namespace drawinglayer::primitive2d void SvgGradientHelper::createMirroredGradientEntries() { - if(maMirroredGradientEntries.empty() && !getGradientEntries().empty()) - { - const sal_uInt32 nCount(getGradientEntries().size()); - maMirroredGradientEntries.clear(); - maMirroredGradientEntries.reserve(nCount); + if(!(maMirroredGradientEntries.empty() && !getGradientEntries().empty())) + return; - for(sal_uInt32 a(0); a < nCount; a++) - { - const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a]; + const sal_uInt32 nCount(getGradientEntries().size()); + maMirroredGradientEntries.clear(); + maMirroredGradientEntries.reserve(nCount); - maMirroredGradientEntries.emplace_back( - 1.0 - rCandidate.getOffset(), - rCandidate.getColor(), - rCandidate.getOpacity()); - } + for(sal_uInt32 a(0); a < nCount; a++) + { + const SvgGradientEntry& rCandidate = getGradientEntries()[nCount - 1 - a]; + + maMirroredGradientEntries.emplace_back( + 1.0 - rCandidate.getOffset(), + rCandidate.getColor(), + rCandidate.getOpacity()); } } @@ -859,43 +859,43 @@ namespace drawinglayer::primitive2d { const double fDelta(getOffsetB() - getOffsetA()); - if(!basegfx::fTools::equalZero(fDelta)) + if(basegfx::fTools::equalZero(fDelta)) + return; + + // use one discrete unit for overlap (one pixel) + const double fDiscreteUnit(getDiscreteUnit()); + + // use color distance and discrete lengths to calculate step count + const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDelta, fDiscreteUnit)); + + // tdf#117949 Use a small amount of discrete overlap at the edges. Usually this + // should be exactly 0.0 and 1.0, but there were cases when this gets clipped + // against the mask polygon which got numerically problematic. + // This change is unnecessary in that respect, but avoids that numerical havoc + // by at the same time doing no real harm AFAIK + // TTTT: Remove again when clipping is fixed (!) + + // prepare polygon in needed width at start position (with discrete overlap) + const basegfx::B2DPolygon aPolygon( + basegfx::utils::createPolygonFromRect( + basegfx::B2DRange( + getOffsetA() - fDiscreteUnit, + -0.0001, // TTTT -> should be 0.0, see comment above + getOffsetA() + (fDelta / nSteps) + fDiscreteUnit, + 1.0001))); // TTTT -> should be 1.0, see comment above + + // prepare loop (inside to outside, [0.0 .. 1.0[) + double fUnitScale(0.0); + const double fUnitStep(1.0 / nSteps); + + for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep) { - // use one discrete unit for overlap (one pixel) - const double fDiscreteUnit(getDiscreteUnit()); - - // use color distance and discrete lengths to calculate step count - const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDelta, fDiscreteUnit)); - - // tdf#117949 Use a small amount of discrete overlap at the edges. Usually this - // should be exactly 0.0 and 1.0, but there were cases when this gets clipped - // against the mask polygon which got numerically problematic. - // This change is unnecessary in that respect, but avoids that numerical havoc - // by at the same time doing no real harm AFAIK - // TTTT: Remove again when clipping is fixed (!) - - // prepare polygon in needed width at start position (with discrete overlap) - const basegfx::B2DPolygon aPolygon( - basegfx::utils::createPolygonFromRect( - basegfx::B2DRange( - getOffsetA() - fDiscreteUnit, - -0.0001, // TTTT -> should be 0.0, see comment above - getOffsetA() + (fDelta / nSteps) + fDiscreteUnit, - 1.0001))); // TTTT -> should be 1.0, see comment above - - // prepare loop (inside to outside, [0.0 .. 1.0[) - double fUnitScale(0.0); - const double fUnitStep(1.0 / nSteps); - - for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep) - { - basegfx::B2DPolygon aNew(aPolygon); + basegfx::B2DPolygon aNew(aPolygon); - aNew.transform(basegfx::utils::createTranslateB2DHomMatrix(fDelta * fUnitScale, 0.0)); - rContainer.push_back(new PolyPolygonColorPrimitive2D( - basegfx::B2DPolyPolygon(aNew), - basegfx::interpolate(getColorA(), getColorB(), fUnitScale))); - } + aNew.transform(basegfx::utils::createTranslateB2DHomMatrix(fDelta * fUnitScale, 0.0)); + rContainer.push_back(new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aNew), + basegfx::interpolate(getColorA(), getColorB(), fUnitScale))); } } @@ -944,51 +944,51 @@ namespace drawinglayer::primitive2d { const double fDeltaScale(getScaleB() - getScaleA()); - if(!basegfx::fTools::equalZero(fDeltaScale)) - { - // use one discrete unit for overlap (one pixel) - const double fDiscreteUnit(getDiscreteUnit()); + if(basegfx::fTools::equalZero(fDeltaScale)) + return; - // use color distance and discrete lengths to calculate step count - const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDeltaScale, fDiscreteUnit)); + // use one discrete unit for overlap (one pixel) + const double fDiscreteUnit(getDiscreteUnit()); - // prepare loop ([0.0 .. 1.0[, full polygons, no polypolygons with holes) - double fUnitScale(0.0); - const double fUnitStep(1.0 / nSteps); + // use color distance and discrete lengths to calculate step count + const sal_uInt32 nSteps(calculateStepsForSvgGradient(getColorA(), getColorB(), fDeltaScale, fDiscreteUnit)); - for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep) - { - basegfx::B2DHomMatrix aTransform; - const double fEndScale(getScaleB() - (fDeltaScale * fUnitScale)); + // prepare loop ([0.0 .. 1.0[, full polygons, no polypolygons with holes) + double fUnitScale(0.0); + const double fUnitStep(1.0 / nSteps); - if(isTranslateSet()) - { - const basegfx::B2DVector aTranslate( - basegfx::interpolate( - getTranslateB(), - getTranslateA(), - fUnitScale)); - - aTransform = basegfx::utils::createScaleTranslateB2DHomMatrix( - fEndScale, - fEndScale, - aTranslate.getX(), - aTranslate.getY()); - } - else - { - aTransform = basegfx::utils::createScaleB2DHomMatrix( - fEndScale, - fEndScale); - } - - basegfx::B2DPolygon aNew(basegfx::utils::createPolygonFromUnitCircle()); + for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep) + { + basegfx::B2DHomMatrix aTransform; + const double fEndScale(getScaleB() - (fDeltaScale * fUnitScale)); - aNew.transform(aTransform); - rContainer.push_back(new PolyPolygonColorPrimitive2D( - basegfx::B2DPolyPolygon(aNew), - basegfx::interpolate(getColorB(), getColorA(), fUnitScale))); + if(isTranslateSet()) + { + const basegfx::B2DVector aTranslate( + basegfx::interpolate( + getTranslateB(), + getTranslateA(), + fUnitScale)); + + aTransform = basegfx::utils::createScaleTranslateB2DHomMatrix( + fEndScale, + fEndScale, + aTranslate.getX(), + aTranslate.getY()); } + else + { + aTransform = basegfx::utils::createScaleB2DHomMatrix( + fEndScale, + fEndScale); + } + + basegfx::B2DPolygon aNew(basegfx::utils::createPolygonFromUnitCircle()); + + aNew.transform(aTransform); + rContainer.push_back(new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aNew), + basegfx::interpolate(getColorB(), getColorA(), fUnitScale))); } } diff --git a/drawinglayer/source/primitive2d/textbreakuphelper.cxx b/drawinglayer/source/primitive2d/textbreakuphelper.cxx index 22946711079b..1139f19e8d06 100644 --- a/drawinglayer/source/primitive2d/textbreakuphelper.cxx +++ b/drawinglayer/source/primitive2d/textbreakuphelper.cxx @@ -55,125 +55,125 @@ namespace drawinglayer::primitive2d void TextBreakupHelper::breakupPortion(Primitive2DContainer& rTempResult, sal_Int32 nIndex, sal_Int32 nLength, bool bWordLineMode) { - if(nLength && !(nIndex == mrSource.getTextPosition() && nLength == mrSource.getTextLength())) + if(!(nLength && !(nIndex == mrSource.getTextPosition() && nLength == mrSource.getTextLength()))) + return; + + // prepare values for new portion + basegfx::B2DHomMatrix aNewTransform; + std::vector< double > aNewDXArray; + const bool bNewStartIsNotOldStart(nIndex > mrSource.getTextPosition()); + + if(!mbNoDXArray) { - // prepare values for new portion - basegfx::B2DHomMatrix aNewTransform; - std::vector< double > aNewDXArray; - const bool bNewStartIsNotOldStart(nIndex > mrSource.getTextPosition()); + // prepare new DXArray for the single word + aNewDXArray = std::vector< double >( + mrSource.getDXArray().begin() + (nIndex - mrSource.getTextPosition()), + mrSource.getDXArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition())); + } - if(!mbNoDXArray) + if(bNewStartIsNotOldStart) + { + // needs to be moved to a new start position + double fOffset(0.0); + + if(mbNoDXArray) { - // prepare new DXArray for the single word - aNewDXArray = std::vector< double >( - mrSource.getDXArray().begin() + (nIndex - mrSource.getTextPosition()), - mrSource.getDXArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition())); + // evaluate using TextLayouter + fOffset = maTextLayouter.getTextWidth(mrSource.getText(), mrSource.getTextPosition(), nIndex); } - - if(bNewStartIsNotOldStart) + else { - // needs to be moved to a new start position - double fOffset(0.0); + // get from DXArray + const sal_Int32 nIndex2(nIndex - mrSource.getTextPosition()); + fOffset = mrSource.getDXArray()[nIndex2 - 1]; + } - if(mbNoDXArray) - { - // evaluate using TextLayouter - fOffset = maTextLayouter.getTextWidth(mrSource.getText(), mrSource.getTextPosition(), nIndex); - } - else - { - // get from DXArray - const sal_Int32 nIndex2(nIndex - mrSource.getTextPosition()); - fOffset = mrSource.getDXArray()[nIndex2 - 1]; - } + // need offset without FontScale for building the new transformation. The + // new transformation will be multiplied with the current text transformation + // so FontScale would be double + double fOffsetNoScale(fOffset); + const double fFontScaleX(maDecTrans.getScale().getX()); - // need offset without FontScale for building the new transformation. The - // new transformation will be multiplied with the current text transformation - // so FontScale would be double - double fOffsetNoScale(fOffset); - const double fFontScaleX(maDecTrans.getScale().getX()); + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) + { + fOffsetNoScale /= fFontScaleX; + } - if(!basegfx::fTools::equal(fFontScaleX, 1.0) - && !basegfx::fTools::equalZero(fFontScaleX)) - { - fOffsetNoScale /= fFontScaleX; - } + // apply needed offset to transformation + aNewTransform.translate(fOffsetNoScale, 0.0); - // apply needed offset to transformation - aNewTransform.translate(fOffsetNoScale, 0.0); + if(!mbNoDXArray) + { + // DXArray values need to be corrected with the offset, too. Here, + // take the scaled offset since the DXArray is scaled + const sal_uInt32 nArraySize(aNewDXArray.size()); - if(!mbNoDXArray) + for(sal_uInt32 a(0); a < nArraySize; a++) { - // DXArray values need to be corrected with the offset, too. Here, - // take the scaled offset since the DXArray is scaled - const sal_uInt32 nArraySize(aNewDXArray.size()); - - for(sal_uInt32 a(0); a < nArraySize; a++) - { - aNewDXArray[a] -= fOffset; - } + aNewDXArray[a] -= fOffset; } } + } - // add text transformation to new transformation - // coverity[swapped_arguments : FALSE] - this is in the correct order - aNewTransform *= maDecTrans.getB2DHomMatrix(); + // add text transformation to new transformation + // coverity[swapped_arguments : FALSE] - this is in the correct order + aNewTransform *= maDecTrans.getB2DHomMatrix(); - // callback to allow evtl. changes - const bool bCreate(allowChange(rTempResult.size(), aNewTransform, nIndex, nLength)); + // callback to allow evtl. changes + const bool bCreate(allowChange(rTempResult.size(), aNewTransform, nIndex, nLength)); - if(bCreate) - { - // check if we have a decorated primitive as source - const TextDecoratedPortionPrimitive2D* pTextDecoratedPortionPrimitive2D = - dynamic_cast< const TextDecoratedPortionPrimitive2D* >(&mrSource); + if(!bCreate) + return; - if(pTextDecoratedPortionPrimitive2D) - { - // create a TextDecoratedPortionPrimitive2D - rTempResult.push_back( - new TextDecoratedPortionPrimitive2D( - aNewTransform, - mrSource.getText(), - nIndex, - nLength, - aNewDXArray, - mrSource.getFontAttribute(), - mrSource.getLocale(), - mrSource.getFontColor(), - mrSource.getTextFillColor(), - - pTextDecoratedPortionPrimitive2D->getOverlineColor(), - pTextDecoratedPortionPrimitive2D->getTextlineColor(), - pTextDecoratedPortionPrimitive2D->getFontOverline(), - pTextDecoratedPortionPrimitive2D->getFontUnderline(), - pTextDecoratedPortionPrimitive2D->getUnderlineAbove(), - pTextDecoratedPortionPrimitive2D->getTextStrikeout(), - - // reset WordLineMode when BreakupUnit::Word is executed; else copy original - !bWordLineMode && pTextDecoratedPortionPrimitive2D->getWordLineMode(), - - pTextDecoratedPortionPrimitive2D->getTextEmphasisMark(), - pTextDecoratedPortionPrimitive2D->getEmphasisMarkAbove(), - pTextDecoratedPortionPrimitive2D->getEmphasisMarkBelow(), - pTextDecoratedPortionPrimitive2D->getTextRelief(), - pTextDecoratedPortionPrimitive2D->getShadow())); - } - else - { - // create a SimpleTextPrimitive - rTempResult.push_back( - new TextSimplePortionPrimitive2D( - aNewTransform, - mrSource.getText(), - nIndex, - nLength, - aNewDXArray, - mrSource.getFontAttribute(), - mrSource.getLocale(), - mrSource.getFontColor())); - } - } + // check if we have a decorated primitive as source + const TextDecoratedPortionPrimitive2D* pTextDecoratedPortionPrimitive2D = + dynamic_cast< const TextDecoratedPortionPrimitive2D* >(&mrSource); + + if(pTextDecoratedPortionPrimitive2D) + { + // create a TextDecoratedPortionPrimitive2D + rTempResult.push_back( + new TextDecoratedPortionPrimitive2D( + aNewTransform, + mrSource.getText(), + nIndex, + nLength, + aNewDXArray, + mrSource.getFontAttribute(), + mrSource.getLocale(), + mrSource.getFontColor(), + mrSource.getTextFillColor(), + + pTextDecoratedPortionPrimitive2D->getOverlineColor(), + pTextDecoratedPortionPrimitive2D->getTextlineColor(), + pTextDecoratedPortionPrimitive2D->getFontOverline(), + pTextDecoratedPortionPrimitive2D->getFontUnderline(), + pTextDecoratedPortionPrimitive2D->getUnderlineAbove(), + pTextDecoratedPortionPrimitive2D->getTextStrikeout(), + + // reset WordLineMode when BreakupUnit::Word is executed; else copy original + !bWordLineMode && pTextDecoratedPortionPrimitive2D->getWordLineMode(), + + pTextDecoratedPortionPrimitive2D->getTextEmphasisMark(), + pTextDecoratedPortionPrimitive2D->getEmphasisMarkAbove(), + pTextDecoratedPortionPrimitive2D->getEmphasisMarkBelow(), + pTextDecoratedPortionPrimitive2D->getTextRelief(), + pTextDecoratedPortionPrimitive2D->getShadow())); + } + else + { + // create a SimpleTextPrimitive + rTempResult.push_back( + new TextSimplePortionPrimitive2D( + aNewTransform, + mrSource.getText(), + nIndex, + nLength, + aNewDXArray, + mrSource.getFontAttribute(), + mrSource.getLocale(), + mrSource.getFontColor())); } } @@ -184,84 +184,84 @@ namespace drawinglayer::primitive2d void TextBreakupHelper::breakup(BreakupUnit aBreakupUnit) { - if(mrSource.getTextLength()) + if(!mrSource.getTextLength()) + return; + + Primitive2DContainer aTempResult; + static css::uno::Reference< css::i18n::XBreakIterator > xBreakIterator; + + if(!xBreakIterator.is()) { - Primitive2DContainer aTempResult; - static css::uno::Reference< css::i18n::XBreakIterator > xBreakIterator; + css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + xBreakIterator = css::i18n::BreakIterator::create(xContext); + } - if(!xBreakIterator.is()) + const OUString& rTxt = mrSource.getText(); + const sal_Int32 nTextLength(mrSource.getTextLength()); + const css::lang::Locale& rLocale = mrSource.getLocale(); + const sal_Int32 nTextPosition(mrSource.getTextPosition()); + sal_Int32 nCurrent(nTextPosition); + + switch(aBreakupUnit) + { + case BreakupUnit::Character: { - css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); - xBreakIterator = css::i18n::BreakIterator::create(xContext); - } + sal_Int32 nDone; + sal_Int32 nNextCellBreak(xBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone)); + sal_Int32 a(nTextPosition); - const OUString& rTxt = mrSource.getText(); - const sal_Int32 nTextLength(mrSource.getTextLength()); - const css::lang::Locale& rLocale = mrSource.getLocale(); - const sal_Int32 nTextPosition(mrSource.getTextPosition()); - sal_Int32 nCurrent(nTextPosition); + for(; a < nTextPosition + nTextLength; a++) + { + if(a == nNextCellBreak) + { + breakupPortion(aTempResult, nCurrent, a - nCurrent, false); + nCurrent = a; + nNextCellBreak = xBreakIterator->nextCharacters(rTxt, a, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone); + } + } - switch(aBreakupUnit) + breakupPortion(aTempResult, nCurrent, a - nCurrent, false); + break; + } + case BreakupUnit::Word: { - case BreakupUnit::Character: - { - sal_Int32 nDone; - sal_Int32 nNextCellBreak(xBreakIterator->nextCharacters(rTxt, nTextPosition, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 0, nDone)); - sal_Int32 a(nTextPosition); + css::i18n::Boundary nNextWordBoundary(xBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, css::i18n::WordType::ANY_WORD, true)); + sal_Int32 a(nTextPosition); - for(; a < nTextPosition + nTextLength; a++) + for(; a < nTextPosition + nTextLength; a++) + { + if(a == nNextWordBoundary.endPos) { - if(a == nNextCellBreak) + if(a > nCurrent) { - breakupPortion(aTempResult, nCurrent, a - nCurrent, false); - nCurrent = a; - nNextCellBreak = xBreakIterator->nextCharacters(rTxt, a, rLocale, css::i18n::CharacterIteratorMode::SKIPCELL, 1, nDone); + breakupPortion(aTempResult, nCurrent, a - nCurrent, true); } - } - breakupPortion(aTempResult, nCurrent, a - nCurrent, false); - break; - } - case BreakupUnit::Word: - { - css::i18n::Boundary nNextWordBoundary(xBreakIterator->getWordBoundary(rTxt, nTextPosition, rLocale, css::i18n::WordType::ANY_WORD, true)); - sal_Int32 a(nTextPosition); + nCurrent = a; - for(; a < nTextPosition + nTextLength; a++) - { - if(a == nNextWordBoundary.endPos) + // skip spaces (maybe enhanced with a bool later if needed) { - if(a > nCurrent) - { - breakupPortion(aTempResult, nCurrent, a - nCurrent, true); - } - - nCurrent = a; + const sal_Int32 nEndOfSpaces(xBreakIterator->endOfCharBlock(rTxt, a, rLocale, css::i18n::CharType::SPACE_SEPARATOR)); - // skip spaces (maybe enhanced with a bool later if needed) + if(nEndOfSpaces > a) { - const sal_Int32 nEndOfSpaces(xBreakIterator->endOfCharBlock(rTxt, a, rLocale, css::i18n::CharType::SPACE_SEPARATOR)); - - if(nEndOfSpaces > a) - { - nCurrent = nEndOfSpaces; - } + nCurrent = nEndOfSpaces; } - - nNextWordBoundary = xBreakIterator->getWordBoundary(rTxt, a + 1, rLocale, css::i18n::WordType::ANY_WORD, true); } - } - if(a > nCurrent) - { - breakupPortion(aTempResult, nCurrent, a - nCurrent, true); + nNextWordBoundary = xBreakIterator->getWordBoundary(rTxt, a + 1, rLocale, css::i18n::WordType::ANY_WORD, true); } - break; } - } - mxResult = aTempResult; + if(a > nCurrent) + { + breakupPortion(aTempResult, nCurrent, a - nCurrent, true); + } + break; + } } + + mxResult = aTempResult; } const Primitive2DContainer& TextBreakupHelper::getResult(BreakupUnit aBreakupUnit) const diff --git a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx index 2f354f7d67b0..28e9eccdacc5 100644 --- a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx @@ -55,95 +55,95 @@ namespace drawinglayer::primitive2d const bool bUnderlineUsed(TEXT_LINE_NONE != getFontUnderline()); const bool bStrikeoutUsed(TEXT_STRIKEOUT_NONE != getTextStrikeout()); - if(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed) - { - // common preparations - TextLayouterDevice aTextLayouter; + if(!(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed)) + return; - // TextLayouterDevice is needed to get metrics for text decorations like - // underline/strikeout/emphasis marks from it. For setup, the font size is needed - aTextLayouter.setFontAttribute( - getFontAttribute(), - rDecTrans.getScale().getX(), - rDecTrans.getScale().getY(), - getLocale()); + // common preparations + TextLayouterDevice aTextLayouter; - // get text width - double fTextWidth(0.0); + // TextLayouterDevice is needed to get metrics for text decorations like + // underline/strikeout/emphasis marks from it. For setup, the font size is needed + aTextLayouter.setFontAttribute( + getFontAttribute(), + rDecTrans.getScale().getX(), + rDecTrans.getScale().getY(), + getLocale()); - if(rDXArray.empty()) - { - fTextWidth = aTextLayouter.getTextWidth(rText, nTextPosition, nTextLength); - } - else - { - fTextWidth = rDXArray.back() * rDecTrans.getScale().getX(); - const double fFontScaleX(rDecTrans.getScale().getX()); + // get text width + double fTextWidth(0.0); - if(!basegfx::fTools::equal(fFontScaleX, 1.0) - && !basegfx::fTools::equalZero(fFontScaleX)) - { - // need to take FontScaling out of the DXArray - fTextWidth /= fFontScaleX; - } - } + if(rDXArray.empty()) + { + fTextWidth = aTextLayouter.getTextWidth(rText, nTextPosition, nTextLength); + } + else + { + fTextWidth = rDXArray.back() * rDecTrans.getScale().getX(); + const double fFontScaleX(rDecTrans.getScale().getX()); - if(bOverlineUsed) + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) { - // create primitive geometry for overline - rTarget.push_back(Primitive2DReference( - new TextLinePrimitive2D( - rDecTrans.getB2DHomMatrix(), - fTextWidth, - aTextLayouter.getOverlineOffset(), - aTextLayouter.getOverlineHeight(), - getFontOverline(), - getOverlineColor()))); + // need to take FontScaling out of the DXArray + fTextWidth /= fFontScaleX; } + } - if(bUnderlineUsed) - { - // create primitive geometry for underline - rTarget.push_back(Primitive2DReference( - new TextLinePrimitive2D( - rDecTrans.getB2DHomMatrix(), - fTextWidth, - aTextLayouter.getUnderlineOffset(), - aTextLayouter.getUnderlineHeight(), - getFontUnderline(), - getTextlineColor()))); - } + if(bOverlineUsed) + { + // create primitive geometry for overline + rTarget.push_back(Primitive2DReference( + new TextLinePrimitive2D( + rDecTrans.getB2DHomMatrix(), + fTextWidth, + aTextLayouter.getOverlineOffset(), + aTextLayouter.getOverlineHeight(), + getFontOverline(), + getOverlineColor()))); + } - if(bStrikeoutUsed) - { - // create primitive geometry for strikeout - if(TEXT_STRIKEOUT_SLASH == getTextStrikeout() || TEXT_STRIKEOUT_X == getTextStrikeout()) - { - // strikeout with character - const sal_Unicode aStrikeoutChar(TEXT_STRIKEOUT_SLASH == getTextStrikeout() ? '/' : 'X'); - - rTarget.push_back(Primitive2DReference( - new TextCharacterStrikeoutPrimitive2D( - rDecTrans.getB2DHomMatrix(), - fTextWidth, - getFontColor(), - aStrikeoutChar, - getFontAttribute(), - getLocale()))); - } - else - { - // strikeout with geometry - rTarget.push_back(Primitive2DReference( - new TextGeometryStrikeoutPrimitive2D( - rDecTrans.getB2DHomMatrix(), - fTextWidth, - getFontColor(), - aTextLayouter.getUnderlineHeight(), - aTextLayouter.getStrikeoutOffset(), - getTextStrikeout()))); - } - } + if(bUnderlineUsed) + { + // create primitive geometry for underline + rTarget.push_back(Primitive2DReference( + new TextLinePrimitive2D( + rDecTrans.getB2DHomMatrix(), + fTextWidth, + aTextLayouter.getUnderlineOffset(), + aTextLayouter.getUnderlineHeight(), + getFontUnderline(), + getTextlineColor()))); + } + + if(!bStrikeoutUsed) + return; + + // create primitive geometry for strikeout + if(TEXT_STRIKEOUT_SLASH == getTextStrikeout() || TEXT_STRIKEOUT_X == getTextStrikeout()) + { + // strikeout with character + const sal_Unicode aStrikeoutChar(TEXT_STRIKEOUT_SLASH == getTextStrikeout() ? '/' : 'X'); + + rTarget.push_back(Primitive2DReference( + new TextCharacterStrikeoutPrimitive2D( + rDecTrans.getB2DHomMatrix(), + fTextWidth, + getFontColor(), + aStrikeoutChar, + getFontAttribute(), + getLocale()))); + } + else + { + // strikeout with geometry + rTarget.push_back(Primitive2DReference( + new TextGeometryStrikeoutPrimitive2D( + rDecTrans.getB2DHomMatrix(), + fTextWidth, + getFontColor(), + aTextLayouter.getUnderlineHeight(), + aTextLayouter.getStrikeoutOffset(), + getTextStrikeout()))); } // TODO: Handle Font Emphasis Above/Below diff --git a/drawinglayer/source/primitive2d/textlineprimitive2d.cxx b/drawinglayer/source/primitive2d/textlineprimitive2d.cxx index 0a8905164fcd..2238fc383d5c 100644 --- a/drawinglayer/source/primitive2d/textlineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textlineprimitive2d.cxx @@ -30,220 +30,220 @@ namespace drawinglayer::primitive2d { void TextLinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if(TEXT_LINE_NONE != getTextLine()) + if(TEXT_LINE_NONE == getTextLine()) + return; + + bool bDoubleLine(false); + bool bWaveLine(false); + bool bBoldLine(false); + const int* pDotDashArray(nullptr); + basegfx::B2DLineJoin eLineJoin(basegfx::B2DLineJoin::NONE); + double fOffset(getOffset()); + double fHeight(getHeight()); + + static const int aDottedArray[] = { 1, 1, 0}; // DOTTED LINE + static const int aDotDashArray[] = { 1, 1, 4, 1, 0}; // DASHDOT + static const int aDashDotDotArray[] = { 1, 1, 1, 1, 4, 1, 0}; // DASHDOTDOT + static const int aDashedArray[] = { 5, 2, 0}; // DASHED LINE + static const int aLongDashArray[] = { 7, 2, 0}; // LONGDASH + + // get decomposition + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getObjectTransformation().decompose(aScale, aTranslate, fRotate, fShearX); + + switch(getTextLine()) { - bool bDoubleLine(false); - bool bWaveLine(false); - bool bBoldLine(false); - const int* pDotDashArray(nullptr); - basegfx::B2DLineJoin eLineJoin(basegfx::B2DLineJoin::NONE); - double fOffset(getOffset()); - double fHeight(getHeight()); - - static const int aDottedArray[] = { 1, 1, 0}; // DOTTED LINE - static const int aDotDashArray[] = { 1, 1, 4, 1, 0}; // DASHDOT - static const int aDashDotDotArray[] = { 1, 1, 1, 1, 4, 1, 0}; // DASHDOTDOT - static const int aDashedArray[] = { 5, 2, 0}; // DASHED LINE - static const int aLongDashArray[] = { 7, 2, 0}; // LONGDASH - - // get decomposition - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - getObjectTransformation().decompose(aScale, aTranslate, fRotate, fShearX); - - switch(getTextLine()) + default: // case TEXT_LINE_SINGLE: { - default: // case TEXT_LINE_SINGLE: - { - break; - } - case TEXT_LINE_DOUBLE: - { - bDoubleLine = true; - break; - } - case TEXT_LINE_DOTTED: - { - pDotDashArray = aDottedArray; - break; - } - case TEXT_LINE_DASH: - { - pDotDashArray = aDashedArray; - break; - } - case TEXT_LINE_LONGDASH: - { - pDotDashArray = aLongDashArray; - break; - } - case TEXT_LINE_DASHDOT: - { - pDotDashArray = aDotDashArray; - break; - } - case TEXT_LINE_DASHDOTDOT: - { - pDotDashArray = aDashDotDotArray; - break; - } - case TEXT_LINE_SMALLWAVE: - { - bWaveLine = true; - break; - } - case TEXT_LINE_WAVE: - { - bWaveLine = true; - break; - } - case TEXT_LINE_DOUBLEWAVE: - { - bDoubleLine = true; - bWaveLine = true; - break; - } - case TEXT_LINE_BOLD: - { - bBoldLine = true; - break; - } - case TEXT_LINE_BOLDDOTTED: - { - bBoldLine = true; - pDotDashArray = aDottedArray; - break; - } - case TEXT_LINE_BOLDDASH: - { - bBoldLine = true; - pDotDashArray = aDashedArray; - break; - } - case TEXT_LINE_BOLDLONGDASH: - { - bBoldLine = true; - pDotDashArray = aLongDashArray; - break; - } - case TEXT_LINE_BOLDDASHDOT: - { - bBoldLine = true; - pDotDashArray = aDotDashArray; - break; - } - case TEXT_LINE_BOLDDASHDOTDOT: - { - bBoldLine = true; - pDotDashArray = aDashDotDotArray; - break; - } - case TEXT_LINE_BOLDWAVE: - { - bWaveLine = true; - bBoldLine = true; - break; - } + break; } - - if(bBoldLine) + case TEXT_LINE_DOUBLE: { - fHeight *= 2.0; + bDoubleLine = true; + break; } - - if(bDoubleLine) + case TEXT_LINE_DOTTED: { - fOffset -= 0.50 * fHeight; - fHeight *= 0.64; + pDotDashArray = aDottedArray; + break; } - - if(bWaveLine) + case TEXT_LINE_DASH: + { + pDotDashArray = aDashedArray; + break; + } + case TEXT_LINE_LONGDASH: + { + pDotDashArray = aLongDashArray; + break; + } + case TEXT_LINE_DASHDOT: + { + pDotDashArray = aDotDashArray; + break; + } + case TEXT_LINE_DASHDOTDOT: + { + pDotDashArray = aDashDotDotArray; + break; + } + case TEXT_LINE_SMALLWAVE: + { + bWaveLine = true; + break; + } + case TEXT_LINE_WAVE: + { + bWaveLine = true; + break; + } + case TEXT_LINE_DOUBLEWAVE: + { + bDoubleLine = true; + bWaveLine = true; + break; + } + case TEXT_LINE_BOLD: + { + bBoldLine = true; + break; + } + case TEXT_LINE_BOLDDOTTED: + { + bBoldLine = true; + pDotDashArray = aDottedArray; + break; + } + case TEXT_LINE_BOLDDASH: + { + bBoldLine = true; + pDotDashArray = aDashedArray; + break; + } + case TEXT_LINE_BOLDLONGDASH: + { + bBoldLine = true; + pDotDashArray = aLongDashArray; + break; + } + case TEXT_LINE_BOLDDASHDOT: + { + bBoldLine = true; + pDotDashArray = aDotDashArray; + break; + } + case TEXT_LINE_BOLDDASHDOTDOT: + { + bBoldLine = true; + pDotDashArray = aDashDotDotArray; + break; + } + case TEXT_LINE_BOLDWAVE: { - eLineJoin = basegfx::B2DLineJoin::Round; - fHeight *= 0.25; + bWaveLine = true; + bBoldLine = true; + break; } + } - // prepare Line and Stroke Attributes - const attribute::LineAttribute aLineAttribute(getLineColor(), fHeight, eLineJoin); - attribute::StrokeAttribute aStrokeAttribute; + if(bBoldLine) + { + fHeight *= 2.0; + } - if(pDotDashArray) - { - std::vector< double > aDoubleArray; + if(bDoubleLine) + { + fOffset -= 0.50 * fHeight; + fHeight *= 0.64; + } - for(const int* p = pDotDashArray; *p; ++p) - { - aDoubleArray.push_back(static_cast<double>(*p) * fHeight); - } + if(bWaveLine) + { + eLineJoin = basegfx::B2DLineJoin::Round; + fHeight *= 0.25; + } - aStrokeAttribute = attribute::StrokeAttribute(aDoubleArray); + // prepare Line and Stroke Attributes + const attribute::LineAttribute aLineAttribute(getLineColor(), fHeight, eLineJoin); + attribute::StrokeAttribute aStrokeAttribute; + + if(pDotDashArray) + { + std::vector< double > aDoubleArray; + + for(const int* p = pDotDashArray; *p; ++p) + { + aDoubleArray.push_back(static_cast<double>(*p) * fHeight); } - // create base polygon and new primitive - basegfx::B2DPolygon aLine; - Primitive2DReference aNewPrimitive; + aStrokeAttribute = attribute::StrokeAttribute(aDoubleArray); + } + + // create base polygon and new primitive + basegfx::B2DPolygon aLine; + Primitive2DReference aNewPrimitive; - aLine.append(basegfx::B2DPoint(0.0, fOffset)); - aLine.append(basegfx::B2DPoint(getWidth(), fOffset)); + aLine.append(basegfx::B2DPoint(0.0, fOffset)); + aLine.append(basegfx::B2DPoint(getWidth(), fOffset)); - const basegfx::B2DHomMatrix aUnscaledTransform( - basegfx::utils::createShearXRotateTranslateB2DHomMatrix( - fShearX, fRotate, aTranslate)); + const basegfx::B2DHomMatrix aUnscaledTransform( + basegfx::utils::createShearXRotateTranslateB2DHomMatrix( + fShearX, fRotate, aTranslate)); - aLine.transform(aUnscaledTransform); + aLine.transform(aUnscaledTransform); - if(bWaveLine) + if(bWaveLine) + { + double fWaveWidth(10.6 * fHeight); + + if(TEXT_LINE_SMALLWAVE == getTextLine()) { - double fWaveWidth(10.6 * fHeight); - - if(TEXT_LINE_SMALLWAVE == getTextLine()) - { - fWaveWidth *= 0.7; - } - else if(TEXT_LINE_WAVE == getTextLine()) - { - // extra multiply to get the same WaveWidth as with the bold version - fWaveWidth *= 2.0; - } - - aNewPrimitive = Primitive2DReference(new PolygonWavePrimitive2D(aLine, aLineAttribute, aStrokeAttribute, fWaveWidth, fWaveWidth * 0.5)); + fWaveWidth *= 0.7; } - else + else if(TEXT_LINE_WAVE == getTextLine()) { - aNewPrimitive = Primitive2DReference(new PolygonStrokePrimitive2D(aLine, aLineAttribute, aStrokeAttribute)); + // extra multiply to get the same WaveWidth as with the bold version + fWaveWidth *= 2.0; } - // add primitive - rContainer.push_back(aNewPrimitive); + aNewPrimitive = Primitive2DReference(new PolygonWavePrimitive2D(aLine, aLineAttribute, aStrokeAttribute, fWaveWidth, fWaveWidth * 0.5)); + } + else + { + aNewPrimitive = Primitive2DReference(new PolygonStrokePrimitive2D(aLine, aLineAttribute, aStrokeAttribute)); + } - if(bDoubleLine) - { - // double line, create 2nd primitive with offset using TransformPrimitive based on - // already created NewPrimitive - double fLineDist(2.3 * fHeight); - - if(bWaveLine) - { - fLineDist = 6.3 * fHeight; - } - - // move base point of text to 0.0 and de-rotate - basegfx::B2DHomMatrix aTransform(basegfx::utils::createTranslateB2DHomMatrix( - -aTranslate.getX(), -aTranslate.getY())); - aTransform.rotate(-fRotate); - - // translate in Y by offset - aTransform.translate(0.0, fLineDist); - - // move back and rotate - aTransform.rotate(fRotate); - aTransform.translate(aTranslate.getX(), aTranslate.getY()); - - // add transform primitive - const Primitive2DContainer aContent { aNewPrimitive }; - rContainer.push_back( new TransformPrimitive2D(aTransform, aContent) ); - } + // add primitive + rContainer.push_back(aNewPrimitive); + + if(!bDoubleLine) + return; + + // double line, create 2nd primitive with offset using TransformPrimitive based on + // already created NewPrimitive + double fLineDist(2.3 * fHeight); + + if(bWaveLine) + { + fLineDist = 6.3 * fHeight; } + + // move base point of text to 0.0 and de-rotate + basegfx::B2DHomMatrix aTransform(basegfx::utils::createTranslateB2DHomMatrix( + -aTranslate.getX(), -aTranslate.getY())); + aTransform.rotate(-fRotate); + + // translate in Y by offset + aTransform.translate(0.0, fLineDist); + + // move back and rotate + aTransform.rotate(fRotate); + aTransform.translate(aTranslate.getX(), aTranslate.getY()); + + // add transform primitive + const Primitive2DContainer aContent { aNewPrimitive }; + rContainer.push_back( new TransformPrimitive2D(aTransform, aContent) ); } TextLinePrimitive2D::TextLinePrimitive2D( diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx index 02aa6195ebb6..e85d61009632 100644 --- a/drawinglayer/source/primitive2d/textprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -85,80 +85,80 @@ namespace drawinglayer::primitive2d { void TextSimplePortionPrimitive2D::getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const { - if(getTextLength()) - { - // decompose object transformation to single values - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; + if(!getTextLength()) + return; - // if decomposition returns false, create no geometry since e.g. scaling may - // be zero - if (getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX) && aScale.getX() != 0.0) - { - // handle special case: If scale is negative in (x,y) (3rd quadrant), it can - // be expressed as rotation by PI - if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) - { - aScale = basegfx::absolute(aScale); - fRotate += F_PI; - } + // decompose object transformation to single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; - // for the TextLayouterDevice, it is necessary to have a scaling representing - // the font size. Since we want to extract polygons here, it is okay to - // work just with scaling and to ignore shear, rotation and translation, - // all that can be applied to the polygons later - const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale)); - - // prepare textlayoutdevice - TextLayouterDevice aTextLayouter; - aTextLayouter.setFontAttribute( - getFontAttribute(), - aFontScale.getX(), - aFontScale.getY(), - getLocale()); + // if decomposition returns false, create no geometry since e.g. scaling may + // be zero + if (!(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX) && aScale.getX() != 0.0)) + return; - // When getting outlines from stretched text (aScale.getX() != 1.0) it - // is necessary to inverse-scale the DXArray (if used) to not get the - // outlines already aligned to given, but wrong DXArray - if(!getDXArray().empty() && !basegfx::fTools::equal(aScale.getX(), 1.0)) - { - std::vector< double > aScaledDXArray = getDXArray(); - const double fDXArrayScale(1.0 / aScale.getX()); - - for(double & a : aScaledDXArray) - { - a *= fDXArrayScale; - } - - // get the text outlines - aTextLayouter.getTextOutlines( - rTarget, - getText(), - getTextPosition(), - getTextLength(), - aScaledDXArray); - } - else - { - // get the text outlines - aTextLayouter.getTextOutlines( - rTarget, - getText(), - getTextPosition(), - getTextLength(), - getDXArray()); - } + // handle special case: If scale is negative in (x,y) (3rd quadrant), it can + // be expressed as rotation by PI + if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + { + aScale = basegfx::absolute(aScale); + fRotate += F_PI; + } - // create primitives for the outlines - const sal_uInt32 nCount(rTarget.size()); + // for the TextLayouterDevice, it is necessary to have a scaling representing + // the font size. Since we want to extract polygons here, it is okay to + // work just with scaling and to ignore shear, rotation and translation, + // all that can be applied to the polygons later + const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale)); + + // prepare textlayoutdevice + TextLayouterDevice aTextLayouter; + aTextLayouter.setFontAttribute( + getFontAttribute(), + aFontScale.getX(), + aFontScale.getY(), + getLocale()); + + // When getting outlines from stretched text (aScale.getX() != 1.0) it + // is necessary to inverse-scale the DXArray (if used) to not get the + // outlines already aligned to given, but wrong DXArray + if(!getDXArray().empty() && !basegfx::fTools::equal(aScale.getX(), 1.0)) + { + std::vector< double > aScaledDXArray = getDXArray(); + const double fDXArrayScale(1.0 / aScale.getX()); - if(nCount) - { - // prepare object transformation for polygons - rTransformation = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( - aScale, fShearX, fRotate, aTranslate); - } + for(double & a : aScaledDXArray) + { + a *= fDXArrayScale; } + + // get the text outlines + aTextLayouter.getTextOutlines( + rTarget, + getText(), + getTextPosition(), + getTextLength(), + aScaledDXArray); + } + else + { + // get the text outlines + aTextLayouter.getTextOutlines( + rTarget, + getText(), + getTextPosition(), + getTextLength(), + getDXArray()); + } + + // create primitives for the outlines + const sal_uInt32 nCount(rTarget.size()); + + if(nCount) + { + // prepare object transformation for polygons + rTransformation = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, fShearX, fRotate, aTranslate); } } diff --git a/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx index e62b4973fb00..afe030ac77b9 100644 --- a/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx +++ b/drawinglayer/source/primitive3d/sdrextrudelathetools3d.cxx @@ -71,33 +71,33 @@ namespace { rOuterPolyPolygon = rPolygon; - if(basegfx::fTools::more(fOffset, 0.0)) + if(!basegfx::fTools::more(fOffset, 0.0)) + return; + + if(bCharacterMode) { - if(bCharacterMode) - { - // grow the outside polygon and scale all polygons to original size. This is done - // to avoid a shrink which potentially would lead to self-intersections, but changes - // the original polygon -> not a precision step, so e.g. not usable for charts - const basegfx::B2DRange aRange(basegfx::utils::getRange(rPolygon)); - rPolygon = basegfx::utils::growInNormalDirection(rPolygon, fOffset); - const basegfx::B2DRange aGrownRange(basegfx::utils::getRange(rPolygon)); - const double fScaleX(basegfx::fTools::equalZero(aGrownRange.getWidth()) ? 1.0 : aRange.getWidth() / aGrownRange.getWidth()); - const double fScaleY(basegfx::fTools::equalZero(aGrownRange.getHeight())? 1.0 : aRange.getHeight() / aGrownRange.getHeight()); - basegfx::B2DHomMatrix aScaleTrans; - - aScaleTrans.translate(-aGrownRange.getMinX(), -aGrownRange.getMinY()); - aScaleTrans.scale(fScaleX, fScaleY); - aScaleTrans.translate(aRange.getMinX(), aRange.getMinY()); - rPolygon.transform(aScaleTrans); - rOuterPolyPolygon.transform(aScaleTrans); - } - else - { - // use more precision, shrink the outer polygons. Since this may lead to self-intersections, - // some kind of correction should be applied here after that step - rOuterPolyPolygon = basegfx::utils::growInNormalDirection(rPolygon, -fOffset); - // basegfx::utils::correctGrowShrinkPolygonPair(rPolygon, rOuterPolyPolygon); - } + // grow the outside polygon and scale all polygons to original size. This is done + // to avoid a shrink which potentially would lead to self-intersections, but changes + // the original polygon -> not a precision step, so e.g. not usable for charts + const basegfx::B2DRange aRange(basegfx::utils::getRange(rPolygon)); + rPolygon = basegfx::utils::growInNormalDirection(rPolygon, fOffset); + const basegfx::B2DRange aGrownRange(basegfx::utils::getRange(rPolygon)); + const double fScaleX(basegfx::fTools::equalZero(aGrownRange.getWidth()) ? 1.0 : aRange.getWidth() / aGrownRange.getWidth()); + const double fScaleY(basegfx::fTools::equalZero(aGrownRange.getHeight())? 1.0 : aRange.getHeight() / aGrownRange.getHeight()); + basegfx::B2DHomMatrix aScaleTrans; + + aScaleTrans.translate(-aGrownRange.getMinX(), -aGrownRange.getMinY()); + aScaleTrans.scale(fScaleX, fScaleY); + aScaleTrans.translate(aRange.getMinX(), aRange.getMinY()); + rPolygon.transform(aScaleTrans); + rOuterPolyPolygon.transform(aScaleTrans); + } + else + { + // use more precision, shrink the outer polygons. Since this may lead to self-intersections, + // some kind of correction should be applied here after that step + rOuterPolyPolygon = basegfx::utils::growInNormalDirection(rPolygon, -fOffset); + // basegfx::utils::correctGrowShrinkPolygonPair(rPolygon, rOuterPolyPolygon); } } @@ -576,313 +576,313 @@ namespace drawinglayer::primitive3d { const sal_uInt32 nNumSlices(rSliceVector.size()); - if(nNumSlices) - { - // common parameters - const sal_uInt32 nLoopCount(bClosed ? nNumSlices : nNumSlices - 1); - basegfx::B3DPolyPolygon aEdgeRounding; - sal_uInt32 a; + if(!nNumSlices) + return; - // texture parameters - double fInvTexHeight(1.0); - std::vector<double> aTexHeightArray; - basegfx::B3DRange aTexRangeFront; - basegfx::B3DRange aTexRangeBack; + // common parameters + const sal_uInt32 nLoopCount(bClosed ? nNumSlices : nNumSlices - 1); + basegfx::B3DPolyPolygon aEdgeRounding; + sal_uInt32 a; - if(bCreateTextureCoordinates) - { - aTexRangeFront = basegfx::utils::getRange(rSliceVector[0].getB3DPolyPolygon()); - aTexRangeBack = basegfx::utils::getRange(rSliceVector[nNumSlices - 1].getB3DPolyPolygon()); + // texture parameters + double fInvTexHeight(1.0); + std::vector<double> aTexHeightArray; + basegfx::B3DRange aTexRangeFront; + basegfx::B3DRange aTexRangeBack; - if(aTexRangeBack.getDepth() > aTexRangeBack.getWidth()) - { - // last polygon is rotated so that depth is bigger than width, exchange X and Z - // for making applyDefaultTextureCoordinatesParallel use Z instead of X for - // horizontal texture coordinate - aTexRangeBack = basegfx::B3DRange( - aTexRangeBack.getMinZ(), aTexRangeBack.getMinY(), aTexRangeBack.getMinX(), - aTexRangeBack.getMaxZ(), aTexRangeBack.getMaxY(), aTexRangeBack.getMaxX()); - } + if(bCreateTextureCoordinates) + { + aTexRangeFront = basegfx::utils::getRange(rSliceVector[0].getB3DPolyPolygon()); + aTexRangeBack = basegfx::utils::getRange(rSliceVector[nNumSlices - 1].getB3DPolyPolygon()); - basegfx::B3DPoint aCenter(basegfx::utils::getRange(rSliceVector[0].getB3DPolyPolygon()).getCenter()); + if(aTexRangeBack.getDepth() > aTexRangeBack.getWidth()) + { + // last polygon is rotated so that depth is bigger than width, exchange X and Z + // for making applyDefaultTextureCoordinatesParallel use Z instead of X for + // horizontal texture coordinate + aTexRangeBack = basegfx::B3DRange( + aTexRangeBack.getMinZ(), aTexRangeBack.getMinY(), aTexRangeBack.getMinX(), + aTexRangeBack.getMaxZ(), aTexRangeBack.getMaxY(), aTexRangeBack.getMaxX()); + } - for(a = 0; a < nLoopCount; a++) - { - const basegfx::B3DPoint aNextCenter(basegfx::utils::getRange(rSliceVector[(a + 1) % nNumSlices].getB3DPolyPolygon()).getCenter()); - const double fLength(basegfx::B3DVector(aNextCenter - aCenter).getLength()); - aTexHeightArray.push_back(fLength); - aCenter = aNextCenter; - } + basegfx::B3DPoint aCenter(basegfx::utils::getRange(rSliceVector[0].getB3DPolyPolygon()).getCenter()); - const double fTexHeight(std::accumulate(aTexHeightArray.begin(), aTexHeightArray.end(), 0.0)); + for(a = 0; a < nLoopCount; a++) + { + const basegfx::B3DPoint aNextCenter(basegfx::utils::getRange(rSliceVector[(a + 1) % nNumSlices].getB3DPolyPolygon()).getCenter()); + const double fLength(basegfx::B3DVector(aNextCenter - aCenter).getLength()); + aTexHeightArray.push_back(fLength); + aCenter = aNextCenter; + } - if(!basegfx::fTools::equalZero(fTexHeight)) - { - fInvTexHeight = 1.0 / fTexHeight; - } + const double fTexHeight(std::accumulate(aTexHeightArray.begin(), aTexHeightArray.end(), 0.0)); + + if(!basegfx::fTools::equalZero(fTexHeight)) + { + fInvTexHeight = 1.0 / fTexHeight; } + } - if(nLoopCount) + if(nLoopCount) + { + double fTexHeightPos(0.0); + for(a = 0; a < nLoopCount; a++) { - double fTexHeightPos(0.0); - for(a = 0; a < nLoopCount; a++) + const Slice3D& rSliceA(rSliceVector[a]); + const Slice3D& rSliceB(rSliceVector[(a + 1) % nNumSlices]); + const bool bAcceptPair(SLICETYPE3D_REGULAR == rSliceA.getSliceType() && SLICETYPE3D_REGULAR == rSliceB.getSliceType()); + basegfx::B3DPolyPolygon aPolA(rSliceA.getB3DPolyPolygon()); + basegfx::B3DPolyPolygon aPolB(rSliceB.getB3DPolyPolygon()); + + if(bAcceptPair) { - const Slice3D& rSliceA(rSliceVector[a]); - const Slice3D& rSliceB(rSliceVector[(a + 1) % nNumSlices]); - const bool bAcceptPair(SLICETYPE3D_REGULAR == rSliceA.getSliceType() && SLICETYPE3D_REGULAR == rSliceB.getSliceType()); - basegfx::B3DPolyPolygon aPolA(rSliceA.getB3DPolyPolygon()); - basegfx::B3DPolyPolygon aPolB(rSliceB.getB3DPolyPolygon()); + if(bCreateNormals) + { + impCreateInBetweenNormals(aPolB, aPolA); + } - if(bAcceptPair) { - if(bCreateNormals) - { - impCreateInBetweenNormals(aPolB, aPolA); - } + const sal_uInt32 nIndPrev((a + nNumSlices - 1) % nNumSlices); + const Slice3D& rSlicePrev(rSliceVector[nIndPrev]); + basegfx::B3DPolyPolygon aPrev(rSlicePrev.getB3DPolyPolygon()); + basegfx::B3DPolyPolygon aPolAA(rSliceA.getB3DPolyPolygon()); + if(SLICETYPE3D_FRONTCAP == rSlicePrev.getSliceType()) { - const sal_uInt32 nIndPrev((a + nNumSlices - 1) % nNumSlices); - const Slice3D& rSlicePrev(rSliceVector[nIndPrev]); - basegfx::B3DPolyPolygon aPrev(rSlicePrev.getB3DPolyPolygon()); - basegfx::B3DPolyPolygon aPolAA(rSliceA.getB3DPolyPolygon()); + basegfx::B3DPolyPolygon aFront(rSlicePrev.getB3DPolyPolygon()); + const bool bHasSlant(aPolAA != aPrev); - if(SLICETYPE3D_FRONTCAP == rSlicePrev.getSliceType()) + if(bCreateTextureCoordinates) { - basegfx::B3DPolyPolygon aFront(rSlicePrev.getB3DPolyPolygon()); - const bool bHasSlant(aPolAA != aPrev); + aFront = basegfx::utils::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront); + } - if(bCreateTextureCoordinates) + if(bCreateNormals) + { + basegfx::B3DVector aNormal(0.0, 0.0, -1.0); + + if(aFront.count()) { - aFront = basegfx::utils::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront); + aNormal = -aFront.getB3DPolygon(0).getNormal(); } - if(bCreateNormals) + impSetNormal(aFront, aNormal); + + if(bHasSlant) { - basegfx::B3DVector aNormal(0.0, 0.0, -1.0); + impCreateInBetweenNormals(aPolAA, aPrev); - if(aFront.count()) + if(bSmoothNormals) { - aNormal = -aFront.getB3DPolygon(0).getNormal(); + // smooth and copy + impMixNormals(aPolA, aPolAA, fSmoothNormalsMix); + aPolAA = aPolA; + } + else + { + // take over from surface + aPolAA = aPolA; } - impSetNormal(aFront, aNormal); - - if(bHasSlant) + if(bSmoothLids) { - impCreateInBetweenNormals(aPolAA, aPrev); - - if(bSmoothNormals) - { - // smooth and copy - impMixNormals(aPolA, aPolAA, fSmoothNormalsMix); - aPolAA = aPolA; - } - else - { - // take over from surface - aPolAA = aPolA; - } - - if(bSmoothLids) - { - // smooth and copy - impMixNormals(aFront, aPrev, fSmoothLidsMix); - aPrev = aFront; - } - else - { - // take over from front - aPrev = aFront; - } + // smooth and copy + impMixNormals(aFront, aPrev, fSmoothLidsMix); + aPrev = aFront; } else { - if(bSmoothNormals) - { - // smooth - impMixNormals(aPolA, aFront, fSmoothNormalsMix); - } - - if(bSmoothLids) - { - // smooth and copy - impMixNormals(aFront, aPolA, fSmoothLidsMix); - aPolA = aFront; - } + // take over from front + aPrev = aFront; } } - - if(bHasSlant) + else { - double fTexStart{}; - double fTexStop{}; - if(bCreateTextureCoordinates) + if(bSmoothNormals) { - fTexStart = fTexHeightPos * fInvTexHeight; - fTexStop = (fTexHeightPos - aTexHeightArray[(a + nLoopCount - 1) % nLoopCount]) * fInvTexHeight; + // smooth + impMixNormals(aPolA, aFront, fSmoothNormalsMix); } - impAddInBetweenFill(aEdgeRounding, aPolAA, aPrev, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); + if(bSmoothLids) + { + // smooth and copy + impMixNormals(aFront, aPolA, fSmoothLidsMix); + aPolA = aFront; + } } - - aFront.flip(); - rFill.push_back(aFront); } - else + + if(bHasSlant) { - if(bCreateNormals && bSmoothNormals && (nIndPrev != a + 1)) + double fTexStart{}; + double fTexStop{}; + if(bCreateTextureCoordinates) { - impCreateInBetweenNormals(aPolAA, aPrev); - impMixNormals(aPolA, aPolAA, 0.5); + fTexStart = fTexHeightPos * fInvTexHeight; + fTexStop = (fTexHeightPos - aTexHeightArray[(a + nLoopCount - 1) % nLoopCount]) * fInvTexHeight; } + + impAddInBetweenFill(aEdgeRounding, aPolAA, aPrev, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); } + + aFront.flip(); + rFill.push_back(aFront); } + else + { + if(bCreateNormals && bSmoothNormals && (nIndPrev != a + 1)) + { + impCreateInBetweenNormals(aPolAA, aPrev); + impMixNormals(aPolA, aPolAA, 0.5); + } + } + } + + { + const sal_uInt32 nIndNext((a + 2) % nNumSlices); + const Slice3D& rSliceNext(rSliceVector[nIndNext]); + basegfx::B3DPolyPolygon aNext(rSliceNext.getB3DPolyPolygon()); + basegfx::B3DPolyPolygon aPolBB(rSliceB.getB3DPolyPolygon()); + if(SLICETYPE3D_BACKCAP == rSliceNext.getSliceType()) { - const sal_uInt32 nIndNext((a + 2) % nNumSlices); - const Slice3D& rSliceNext(rSliceVector[nIndNext]); - basegfx::B3DPolyPolygon aNext(rSliceNext.getB3DPolyPolygon()); - basegfx::B3DPolyPolygon aPolBB(rSliceB.getB3DPolyPolygon()); + basegfx::B3DPolyPolygon aBack(rSliceNext.getB3DPolyPolygon()); + const bool bHasSlant(aPolBB != aNext); - if(SLICETYPE3D_BACKCAP == rSliceNext.getSliceType()) + if(bCreateTextureCoordinates) { - basegfx::B3DPolyPolygon aBack(rSliceNext.getB3DPolyPolygon()); - const bool bHasSlant(aPolBB != aNext); + aBack = basegfx::utils::applyDefaultTextureCoordinatesParallel(aBack, aTexRangeBack); + } - if(bCreateTextureCoordinates) - { - aBack = basegfx::utils::applyDefaultTextureCoordinatesParallel(aBack, aTexRangeBack); - } + if(bCreateNormals) + { + const basegfx::B3DVector aNormal(aBack.count() ? aBack.getB3DPolygon(0).getNormal() : basegfx::B3DVector(0.0, 0.0, 1.0)); + impSetNormal(aBack, aNormal); - if(bCreateNormals) + if(bHasSlant) { - const basegfx::B3DVector aNormal(aBack.count() ? aBack.getB3DPolygon(0).getNormal() : basegfx::B3DVector(0.0, 0.0, 1.0)); - impSetNormal(aBack, aNormal); + impCreateInBetweenNormals(aNext, aPolBB); - if(bHasSlant) + if(bSmoothNormals) { - impCreateInBetweenNormals(aNext, aPolBB); - - if(bSmoothNormals) - { - // smooth and copy - impMixNormals(aPolB, aPolBB, fSmoothNormalsMix); - aPolBB = aPolB; - } - else - { - // take over from surface - aPolBB = aPolB; - } - - if(bSmoothLids) - { - // smooth and copy - impMixNormals(aBack, aNext, fSmoothLidsMix); - aNext = aBack; - } - else - { - // take over from back - aNext = aBack; - } + // smooth and copy + impMixNormals(aPolB, aPolBB, fSmoothNormalsMix); + aPolBB = aPolB; } else { - if(bSmoothNormals) - { - // smooth - impMixNormals(aPolB, aBack, fSmoothNormalsMix); - } - - if(bSmoothLids) - { - // smooth and copy - impMixNormals(aBack, aPolB, fSmoothLidsMix); - aPolB = aBack; - } + // take over from surface + aPolBB = aPolB; } - } - if(bHasSlant) + if(bSmoothLids) + { + // smooth and copy + impMixNormals(aBack, aNext, fSmoothLidsMix); + aNext = aBack; + } + else + { + // take over from back + aNext = aBack; + } + } + else { - double fTexStart{}; - double fTexStop{}; - if(bCreateTextureCoordinates) + if(bSmoothNormals) { - fTexStart = (fTexHeightPos + aTexHeightArray[a] + aTexHeightArray[(a + 1) % nLoopCount]) * fInvTexHeight; - fTexStop = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight; + // smooth + impMixNormals(aPolB, aBack, fSmoothNormalsMix); } - impAddInBetweenFill(aEdgeRounding, aNext, aPolBB, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); + if(bSmoothLids) + { + // smooth and copy + impMixNormals(aBack, aPolB, fSmoothLidsMix); + aPolB = aBack; + } } - - rFill.push_back(aBack); } - else + + if(bHasSlant) { - if(bCreateNormals && bSmoothNormals && (nIndNext != a)) + double fTexStart{}; + double fTexStop{}; + if(bCreateTextureCoordinates) { - impCreateInBetweenNormals(aNext, aPolBB); - impMixNormals(aPolB, aPolBB, 0.5); + fTexStart = (fTexHeightPos + aTexHeightArray[a] + aTexHeightArray[(a + 1) % nLoopCount]) * fInvTexHeight; + fTexStop = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight; } + + impAddInBetweenFill(aEdgeRounding, aNext, aPolBB, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); } - } - double fTexStart{}; - double fTexStop{}; - if(bCreateTextureCoordinates) + rFill.push_back(aBack); + } + else { - fTexStart = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight; - fTexStop = fTexHeightPos * fInvTexHeight; + if(bCreateNormals && bSmoothNormals && (nIndNext != a)) + { + impCreateInBetweenNormals(aNext, aPolBB); + impMixNormals(aPolB, aPolBB, 0.5); + } } - - impAddInBetweenFill(aEdgeRounding, aPolB, aPolA, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); } + double fTexStart{}; + double fTexStop{}; if(bCreateTextureCoordinates) { - fTexHeightPos += aTexHeightArray[a]; + fTexStart = (fTexHeightPos + aTexHeightArray[a]) * fInvTexHeight; + fTexStop = fTexHeightPos * fInvTexHeight; } + + impAddInBetweenFill(aEdgeRounding, aPolB, aPolA, fTexStart, fTexStop, bCreateNormals, bCreateTextureCoordinates); } - } - else - { - // no loop, but a single slice (1 == nNumSlices), create a filling from the single - // front plane - const Slice3D& rSlice(rSliceVector[0]); - basegfx::B3DPolyPolygon aFront(rSlice.getB3DPolyPolygon()); if(bCreateTextureCoordinates) { - aFront = basegfx::utils::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront); + fTexHeightPos += aTexHeightArray[a]; } - - if(bCreateNormals) - { - basegfx::B3DVector aNormal(0.0, 0.0, -1.0); - - if(aFront.count()) - { - aNormal = -aFront.getB3DPolygon(0).getNormal(); - } - - impSetNormal(aFront, aNormal); - } - - aFront.flip(); - rFill.push_back(aFront); } + } + else + { + // no loop, but a single slice (1 == nNumSlices), create a filling from the single + // front plane + const Slice3D& rSlice(rSliceVector[0]); + basegfx::B3DPolyPolygon aFront(rSlice.getB3DPolyPolygon()); if(bCreateTextureCoordinates) { - aEdgeRounding.transformTextureCoordinates(rTexTransform); + aFront = basegfx::utils::applyDefaultTextureCoordinatesParallel(aFront, aTexRangeFront); } - for(a = 0; a < aEdgeRounding.count(); a++) + if(bCreateNormals) { - rFill.emplace_back(aEdgeRounding.getB3DPolygon(a)); + basegfx::B3DVector aNormal(0.0, 0.0, -1.0); + + if(aFront.count()) + { + aNormal = -aFront.getB3DPolygon(0).getNormal(); + } + + impSetNormal(aFront, aNormal); } + + aFront.flip(); + rFill.push_back(aFront); + } + + if(bCreateTextureCoordinates) + { + aEdgeRounding.transformTextureCoordinates(rTexTransform); + } + + for(a = 0; a < aEdgeRounding.count(); a++) + { + rFill.emplace_back(aEdgeRounding.getB3DPolygon(a)); } } @@ -896,85 +896,85 @@ namespace drawinglayer::primitive3d const sal_uInt32 nPointCount(rLoopA.count()); // with identical polygons there are no outlines - if(rLoopA != rLoopB) + if(rLoopA == rLoopB) + return; + + if(!(nPointCount && nPointCount == rLoopB.count())) + return; + + const basegfx::B3DHomMatrix aObjectTransform(rViewInformation.getObjectToView() * rObjectTransform); + const basegfx::B2DPolygon a2DLoopA(basegfx::utils::createB2DPolygonFromB3DPolygon(rLoopA, aObjectTransform)); + const basegfx::B2DPolygon a2DLoopB(basegfx::utils::createB2DPolygonFromB3DPolygon(rLoopB, aObjectTransform)); + const basegfx::B2DPoint a2DCenterA(a2DLoopA.getB2DRange().getCenter()); + const basegfx::B2DPoint a2DCenterB(a2DLoopB.getB2DRange().getCenter()); + + // without detectable Y-Axis there are no outlines + if(a2DCenterA.equal(a2DCenterB)) + return; + + // search for outmost left and right inter-loop-edges which do not cut the loops + const basegfx::B2DPoint aCommonCenter(basegfx::average(a2DCenterA, a2DCenterB)); + const basegfx::B2DVector aAxisVector(a2DCenterA - a2DCenterB); + double fMaxLeft(0.0); + double fMaxRight(0.0); + sal_uInt32 nIndexLeft(0); + sal_uInt32 nIndexRight(0); + + for(sal_uInt32 a(0); a < nPointCount; a++) { - if(nPointCount && nPointCount == rLoopB.count()) + const basegfx::B2DPoint aStart(a2DLoopA.getB2DPoint(a)); + const basegfx::B2DPoint aEnd(a2DLoopB.getB2DPoint(a)); + const basegfx::B2DPoint aMiddle(basegfx::average(aStart, aEnd)); + + if(!basegfx::utils::isInside(a2DLoopA, aMiddle)) { - const basegfx::B3DHomMatrix aObjectTransform(rViewInformation.getObjectToView() * rObjectTransform); - const basegfx::B2DPolygon a2DLoopA(basegfx::utils::createB2DPolygonFromB3DPolygon(rLoopA, aObjectTransform)); - const basegfx::B2DPolygon a2DLoopB(basegfx::utils::createB2DPolygonFromB3DPolygon(rLoopB, aObjectTransform)); - const basegfx::B2DPoint a2DCenterA(a2DLoopA.getB2DRange().getCenter()); - const basegfx::B2DPoint a2DCenterB(a2DLoopB.getB2DRange().getCenter()); - - // without detectable Y-Axis there are no outlines - if(!a2DCenterA.equal(a2DCenterB)) + if(!basegfx::utils::isInside(a2DLoopB, aMiddle)) { - // search for outmost left and right inter-loop-edges which do not cut the loops - const basegfx::B2DPoint aCommonCenter(basegfx::average(a2DCenterA, a2DCenterB)); - const basegfx::B2DVector aAxisVector(a2DCenterA - a2DCenterB); - double fMaxLeft(0.0); - double fMaxRight(0.0); - sal_uInt32 nIndexLeft(0); - sal_uInt32 nIndexRight(0); - - for(sal_uInt32 a(0); a < nPointCount; a++) + if(!impHasCutWith(a2DLoopA, aStart, aEnd)) { - const basegfx::B2DPoint aStart(a2DLoopA.getB2DPoint(a)); - const basegfx::B2DPoint aEnd(a2DLoopB.getB2DPoint(a)); - const basegfx::B2DPoint aMiddle(basegfx::average(aStart, aEnd)); - - if(!basegfx::utils::isInside(a2DLoopA, aMiddle)) + if(!impHasCutWith(a2DLoopB, aStart, aEnd)) { - if(!basegfx::utils::isInside(a2DLoopB, aMiddle)) + const basegfx::B2DVector aCandidateVector(aMiddle - aCommonCenter); + const double fCross(aCandidateVector.cross(aAxisVector)); + const double fDistance(aCandidateVector.getLength()); + + if(fCross > 0.0) { - if(!impHasCutWith(a2DLoopA, aStart, aEnd)) + if(fDistance > fMaxLeft) { - if(!impHasCutWith(a2DLoopB, aStart, aEnd)) - { - const basegfx::B2DVector aCandidateVector(aMiddle - aCommonCenter); - const double fCross(aCandidateVector.cross(aAxisVector)); - const double fDistance(aCandidateVector.getLength()); - - if(fCross > 0.0) - { - if(fDistance > fMaxLeft) - { - fMaxLeft = fDistance; - nIndexLeft = a; - } - } - else if(fCross < 0.0) - { - if(fDistance > fMaxRight) - { - fMaxRight = fDistance; - nIndexRight = a; - } - } - } + fMaxLeft = fDistance; + nIndexLeft = a; + } + } + else if(fCross < 0.0) + { + if(fDistance > fMaxRight) + { + fMaxRight = fDistance; + nIndexRight = a; } } } } - - if(fMaxLeft != 0.0) - { - basegfx::B3DPolygon aToBeAdded; - aToBeAdded.append(rLoopA.getB3DPoint(nIndexLeft)); - aToBeAdded.append(rLoopB.getB3DPoint(nIndexLeft)); - rTarget.append(aToBeAdded); - } - - if(fMaxRight != 0.0) - { - basegfx::B3DPolygon aToBeAdded; - aToBeAdded.append(rLoopA.getB3DPoint(nIndexRight)); - aToBeAdded.append(rLoopB.getB3DPoint(nIndexRight)); - rTarget.append(aToBeAdded); - } } } } + + if(fMaxLeft != 0.0) + { + basegfx::B3DPolygon aToBeAdded; + aToBeAdded.append(rLoopA.getB3DPoint(nIndexLeft)); + aToBeAdded.append(rLoopB.getB3DPoint(nIndexLeft)); + rTarget.append(aToBeAdded); + } + + if(fMaxRight != 0.0) + { + basegfx::B3DPolygon aToBeAdded; + aToBeAdded.append(rLoopA.getB3DPoint(nIndexRight)); + aToBeAdded.append(rLoopB.getB3DPoint(nIndexRight)); + rTarget.append(aToBeAdded); + } } } // end of namespace diff --git a/drawinglayer/source/processor2d/baseprocessor2d.cxx b/drawinglayer/source/processor2d/baseprocessor2d.cxx index ca766a3d01c5..9d1671dcf959 100644 --- a/drawinglayer/source/processor2d/baseprocessor2d.cxx +++ b/drawinglayer/source/processor2d/baseprocessor2d.cxx @@ -48,31 +48,31 @@ namespace drawinglayer::processor2d void BaseProcessor2D::process(const primitive2d::Primitive2DContainer& rSource) { - if(!rSource.empty()) + if(rSource.empty()) + return; + + const sal_Int32 nCount(rSource.size()); + + for(sal_Int32 a(0); a < nCount; a++) { - const sal_Int32 nCount(rSource.size()); + // get reference + const primitive2d::Primitive2DReference xReference(rSource[a]); - for(sal_Int32 a(0); a < nCount; a++) + if(xReference.is()) { - // get reference - const primitive2d::Primitive2DReference xReference(rSource[a]); + // try to cast to BasePrimitive2D implementation + const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get()); - if(xReference.is()) + if(pBasePrimitive) { - // try to cast to BasePrimitive2D implementation - const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get()); - - if(pBasePrimitive) - { - // it is a BasePrimitive2D implementation, use local processor - processBasePrimitive2D(*pBasePrimitive); - } - else - { - // unknown implementation, use UNO API call instead and process recursively - const uno::Sequence< beans::PropertyValue >& rViewParameters(getViewInformation2D().getViewInformationSequence()); - process(comphelper::sequenceToContainer<primitive2d::Primitive2DContainer>(xReference->getDecomposition(rViewParameters))); - } + // it is a BasePrimitive2D implementation, use local processor + processBasePrimitive2D(*pBasePrimitive); + } + else + { + // unknown implementation, use UNO API call instead and process recursively + const uno::Sequence< beans::PropertyValue >& rViewParameters(getViewInformation2D().getViewInformationSequence()); + process(comphelper::sequenceToContainer<primitive2d::Primitive2DContainer>(xReference->getDecomposition(rViewParameters))); } } } diff --git a/drawinglayer/source/processor2d/objectinfoextractor2d.cxx b/drawinglayer/source/processor2d/objectinfoextractor2d.cxx index d15fc36523be..552406d53f68 100644 --- a/drawinglayer/source/processor2d/objectinfoextractor2d.cxx +++ b/drawinglayer/source/processor2d/objectinfoextractor2d.cxx @@ -27,37 +27,37 @@ namespace drawinglayer::processor2d { void ObjectInfoPrimitiveExtractor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { - if(!mpFound) + if(mpFound) + return; + + switch(rCandidate.getPrimitive2DID()) { - switch(rCandidate.getPrimitive2DID()) + case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D : + { + mpFound = dynamic_cast< const primitive2d::ObjectInfoPrimitive2D* >(&rCandidate); + break; + } + default : { - case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D : + // we look for an encapsulated primitive, so do not decompose primitives + // based on GroupPrimitive2D, just visit their children. It may be that more + // group-like primitives need to be added here, but all primitives with + // grouping functionality should be implemented based on the GroupPrimitive2D + // class and have their main content accessible as children + const primitive2d::GroupPrimitive2D* pGroupPrimitive2D = dynamic_cast< const primitive2d::GroupPrimitive2D* >(&rCandidate); + + if(pGroupPrimitive2D) { - mpFound = dynamic_cast< const primitive2d::ObjectInfoPrimitive2D* >(&rCandidate); - break; + // process group children recursively + process(pGroupPrimitive2D->getChildren()); } - default : + else { - // we look for an encapsulated primitive, so do not decompose primitives - // based on GroupPrimitive2D, just visit their children. It may be that more - // group-like primitives need to be added here, but all primitives with - // grouping functionality should be implemented based on the GroupPrimitive2D - // class and have their main content accessible as children - const primitive2d::GroupPrimitive2D* pGroupPrimitive2D = dynamic_cast< const primitive2d::GroupPrimitive2D* >(&rCandidate); - - if(pGroupPrimitive2D) - { - // process group children recursively - process(pGroupPrimitive2D->getChildren()); - } - else - { - // do not process recursively, we *only* want to find existing - // ObjectInfoPrimitive2D entries - } - - break; + // do not process recursively, we *only* want to find existing + // ObjectInfoPrimitive2D entries } + + break; } } } diff --git a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx index ae753a40a39b..f362559d12bf 100644 --- a/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx +++ b/drawinglayer/source/processor2d/vclhelperbufferdevice.cxx @@ -267,40 +267,40 @@ namespace drawinglayer maDestPixel = ::tools::Rectangle(aEmptyPoint, mrOutDev.GetOutputSizePixel()); maDestPixel.Intersection(aRectPixel); - if(isVisible()) - { + if(!isVisible()) + return; + #ifdef IOS - // Exact mechanism unknown, but for some reason SmartArt - // rendering, especially shadows, is broken on iOS unless - // we pass 'true' here. Are virtual devices always de - // facto cleared when created on other platforms? - mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, false); + // Exact mechanism unknown, but for some reason SmartArt + // rendering, especially shadows, is broken on iOS unless + // we pass 'true' here. Are virtual devices always de + // facto cleared when created on other platforms? + mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), true, false); #else - mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), false, false); + mpContent = getVDevBuffer().alloc(mrOutDev, maDestPixel.GetSize(), false, false); #endif - // #i93485# assert when copying from window to VDev is used - OSL_ENSURE(mrOutDev.GetOutDevType() != OUTDEV_WINDOW, - "impBufferDevice render helper: Copying from Window to VDev, this should be avoided (!)"); + // #i93485# assert when copying from window to VDev is used + OSL_ENSURE(mrOutDev.GetOutDevType() != OUTDEV_WINDOW, + "impBufferDevice render helper: Copying from Window to VDev, this should be avoided (!)"); - const bool bWasEnabledSrc(mrOutDev.IsMapModeEnabled()); - mrOutDev.EnableMapMode(false); - mpContent->DrawOutDev(aEmptyPoint, maDestPixel.GetSize(), maDestPixel.TopLeft(), maDestPixel.GetSize(), mrOutDev); - mrOutDev.EnableMapMode(bWasEnabledSrc); + const bool bWasEnabledSrc(mrOutDev.IsMapModeEnabled()); + mrOutDev.EnableMapMode(false); + mpContent->DrawOutDev(aEmptyPoint, maDestPixel.GetSize(), maDestPixel.TopLeft(), maDestPixel.GetSize(), mrOutDev); + mrOutDev.EnableMapMode(bWasEnabledSrc); - MapMode aNewMapMode(mrOutDev.GetMapMode()); + MapMode aNewMapMode(mrOutDev.GetMapMode()); - const Point aLogicTopLeft(mrOutDev.PixelToLogic(maDestPixel.TopLeft())); - aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y())); + const Point aLogicTopLeft(mrOutDev.PixelToLogic(maDestPixel.TopLeft())); + aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y())); - mpContent->SetMapMode(aNewMapMode); + mpContent->SetMapMode(aNewMapMode); - // copy AA flag for new target - mpContent->SetAntialiasing(mrOutDev.GetAntialiasing()); + // copy AA flag for new target + mpContent->SetAntialiasing(mrOutDev.GetAntialiasing()); - // copy RasterOp (e.g. may be RasterOp::Xor on destination) - mpContent->SetRasterOp(mrOutDev.GetRasterOp()); - } + // copy RasterOp (e.g. may be RasterOp::Xor on destination) + mpContent->SetRasterOp(mrOutDev.GetRasterOp()); } impBufferDevice::~impBufferDevice() @@ -323,98 +323,98 @@ namespace drawinglayer void impBufferDevice::paint(double fTrans) { - if(isVisible()) - { - const Point aEmptyPoint; - const Size aSizePixel(maDestPixel.GetSize()); - const bool bWasEnabledDst(mrOutDev.IsMapModeEnabled()); + if(!isVisible()) + return; + + const Point aEmptyPoint; + const Size aSizePixel(maDestPixel.GetSize()); + const bool bWasEnabledDst(mrOutDev.IsMapModeEnabled()); #ifdef DBG_UTIL - static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore + static bool bDoSaveForVisualControl(false); // loplugin:constvars:ignore #endif - mrOutDev.EnableMapMode(false); - mpContent->EnableMapMode(false); + mrOutDev.EnableMapMode(false); + mpContent->EnableMapMode(false); #ifdef DBG_UTIL - if(bDoSaveForVisualControl) - { - SvFileStream aNew( + if(bDoSaveForVisualControl) + { + SvFileStream aNew( #ifdef _WIN32 - "c:\\content.bmp", + "c:\\content.bmp", #else - "~/content.bmp", + "~/content.bmp", #endif - StreamMode::WRITE|StreamMode::TRUNC); - Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); - WriteDIB(aContent, aNew, false, true); - } + StreamMode::WRITE|StreamMode::TRUNC); + Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); + WriteDIB(aContent, aNew, false, true); + } #endif - // during painting the buffer, disable evtl. set RasterOp (may be RasterOp::Xor) - const RasterOp aOrigRasterOp(mrOutDev.GetRasterOp()); - mrOutDev.SetRasterOp(RasterOp::OverPaint); + // during painting the buffer, disable evtl. set RasterOp (may be RasterOp::Xor) + const RasterOp aOrigRasterOp(mrOutDev.GetRasterOp()); + mrOutDev.SetRasterOp(RasterOp::OverPaint); - if(mpAlpha) - { - mpAlpha->EnableMapMode(false); - const AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel)); + if(mpAlpha) + { + mpAlpha->EnableMapMode(false); + const AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel)); #ifdef DBG_UTIL - if(bDoSaveForVisualControl) - { - SvFileStream aNew( + if(bDoSaveForVisualControl) + { + SvFileStream aNew( #ifdef _WIN32 - "c:\\transparence.bmp", + "c:\\transparence.bmp", #else - "~/transparence.bmp", + "~/transparence.bmp", #endif - StreamMode::WRITE|StreamMode::TRUNC); - WriteDIB(aAlphaMask.GetBitmap(), aNew, false, true); - } + StreamMode::WRITE|StreamMode::TRUNC); + WriteDIB(aAlphaMask.GetBitmap(), aNew, false, true); + } #endif - Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); - mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask)); - } - else if(mpMask) - { - mpMask->EnableMapMode(false); - const Bitmap aMask(mpMask->GetBitmap(aEmptyPoint, aSizePixel)); + Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); + mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask)); + } + else if(mpMask) + { + mpMask->EnableMapMode(false); + const Bitmap aMask(mpMask->GetBitmap(aEmptyPoint, aSizePixel)); #ifdef DBG_UTIL - if(bDoSaveForVisualControl) - { - SvFileStream aNew( + if(bDoSaveForVisualControl) + { + SvFileStream aNew( #ifdef _WIN32 - "c:\\mask.bmp", + "c:\\mask.bmp", #else - "~/mask.bmp", -#endif - StreamMode::WRITE|StreamMode::TRUNC); - WriteDIB(aMask, aNew, false, true); - } + "~/mask.bmp", #endif - - Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); - mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aMask)); - } - else if(0.0 != fTrans) - { - sal_uInt8 nMaskValue(static_cast<sal_uInt8>(basegfx::fround(fTrans * 255.0))); - const AlphaMask aAlphaMask(aSizePixel, &nMaskValue); - Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); - mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask)); - } - else - { - mrOutDev.DrawOutDev(maDestPixel.TopLeft(), aSizePixel, - aEmptyPoint, aSizePixel, - *mpContent); + StreamMode::WRITE|StreamMode::TRUNC); + WriteDIB(aMask, aNew, false, true); } +#endif - mrOutDev.SetRasterOp(aOrigRasterOp); - mrOutDev.EnableMapMode(bWasEnabledDst); + Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); + mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aMask)); } + else if(0.0 != fTrans) + { + sal_uInt8 nMaskValue(static_cast<sal_uInt8>(basegfx::fround(fTrans * 255.0))); + const AlphaMask aAlphaMask(aSizePixel, &nMaskValue); + Bitmap aContent(mpContent->GetBitmap(aEmptyPoint, aSizePixel)); + mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask)); + } + else + { + mrOutDev.DrawOutDev(maDestPixel.TopLeft(), aSizePixel, + aEmptyPoint, aSizePixel, + *mpContent); + } + + mrOutDev.SetRasterOp(aOrigRasterOp); + mrOutDev.EnableMapMode(bWasEnabledDst); } VirtualDevice& impBufferDevice::getContent() diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 77d83a649ad5..e3e03e6a7f69 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -129,87 +129,87 @@ namespace { const sal_uInt32 nPolyCount(rPolyPolygon.count()); - if(nPolyCount) - { - basegfx::B2DPolyPolygon aSplitted; + if(!nPolyCount) + return; - for(sal_uInt32 a(0); a < nPolyCount; a++) - { - const basegfx::B2DPolygon& aCandidate(rPolyPolygon.getB2DPolygon(a)); - const sal_uInt32 nPointCount(aCandidate.count()); - bool bNeedToSplit(false); + basegfx::B2DPolyPolygon aSplitted; - if(aCandidate.areControlPointsUsed()) - { - // compare with the maximum for bezier curved polygons - bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1); - } - else - { - // compare with the maximum for simple point polygons - bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1); - } + for(sal_uInt32 a(0); a < nPolyCount; a++) + { + const basegfx::B2DPolygon& aCandidate(rPolyPolygon.getB2DPolygon(a)); + const sal_uInt32 nPointCount(aCandidate.count()); + bool bNeedToSplit(false); - if(bNeedToSplit) - { - // need to split the partial polygon - const basegfx::B2DRange aRange(aCandidate.getB2DRange()); - const basegfx::B2DPoint aCenter(aRange.getCenter()); + if(aCandidate.areControlPointsUsed()) + { + // compare with the maximum for bezier curved polygons + bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1); + } + else + { + // compare with the maximum for simple point polygons + bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1); + } - if(aRange.getWidth() > aRange.getHeight()) - { - // clip in left and right - const basegfx::B2DPolyPolygon aLeft( - basegfx::utils::clipPolygonOnParallelAxis( - aCandidate, - false, - true, - aCenter.getX(), - false)); - const basegfx::B2DPolyPolygon aRight( - basegfx::utils::clipPolygonOnParallelAxis( - aCandidate, - false, - false, - aCenter.getX(), - false)); - - aSplitted.append(aLeft); - aSplitted.append(aRight); - } - else - { - // clip in top and bottom - const basegfx::B2DPolyPolygon aTop( - basegfx::utils::clipPolygonOnParallelAxis( - aCandidate, - true, - true, - aCenter.getY(), - false)); - const basegfx::B2DPolyPolygon aBottom( - basegfx::utils::clipPolygonOnParallelAxis( - aCandidate, - true, - false, - aCenter.getY(), - false)); - - aSplitted.append(aTop); - aSplitted.append(aBottom); - } + if(bNeedToSplit) + { + // need to split the partial polygon + const basegfx::B2DRange aRange(aCandidate.getB2DRange()); + const basegfx::B2DPoint aCenter(aRange.getCenter()); + + if(aRange.getWidth() > aRange.getHeight()) + { + // clip in left and right + const basegfx::B2DPolyPolygon aLeft( + basegfx::utils::clipPolygonOnParallelAxis( + aCandidate, + false, + true, + aCenter.getX(), + false)); + const basegfx::B2DPolyPolygon aRight( + basegfx::utils::clipPolygonOnParallelAxis( + aCandidate, + false, + false, + aCenter.getX(), + false)); + + aSplitted.append(aLeft); + aSplitted.append(aRight); } else { - aSplitted.append(aCandidate); + // clip in top and bottom + const basegfx::B2DPolyPolygon aTop( + basegfx::utils::clipPolygonOnParallelAxis( + aCandidate, + true, + true, + aCenter.getY(), + false)); + const basegfx::B2DPolyPolygon aBottom( + basegfx::utils::clipPolygonOnParallelAxis( + aCandidate, + true, + false, + aCenter.getY(), + false)); + + aSplitted.append(aTop); + aSplitted.append(aBottom); } } - - if(aSplitted.count() != nPolyCount) + else { - rPolyPolygon = aSplitted; + aSplitted.append(aCandidate); } } + + if(aSplitted.count() != nPolyCount) + { + rPolyPolygon = aSplitted; + } } /** Filter input polypolygon for effectively empty sub-fills @@ -975,97 +975,97 @@ namespace drawinglayer::processor2d // process recursively and add MetaFile comment process(rGraphicPrimitive); - if(bUsingPDFExtOutDevData) + if(!bUsingPDFExtOutDevData) + return; + + // 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()) { - // 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); + // 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; - } + { + 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(fDivY)) - { - fFactorY = aScale.getY() / fDivY; - } + if(!basegfx::fTools::equalZero(fDivX)) + { + fFactorX = aScale.getX() / fDivX; } - // 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()))); + if(!basegfx::fTools::equalZero(fDivY)) + { + fFactorY = aScale.getY() / fDivY; + } } - // Create image alternative description from ObjectInfoPrimitive2D info - // for PDF export - if(mpPDFExtOutDevData->GetIsExportTaggedPDF() && nullptr != getObjectInfoPrimitive2D()) - { - OUString aAlternateDescription; + // 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)); - if(!getObjectInfoPrimitive2D()->getTitle().isEmpty()) - { - aAlternateDescription += getObjectInfoPrimitive2D()->getTitle(); - } + aCropRect = ::tools::Rectangle( + sal_Int32(floor(aCropRange.getMinX())), sal_Int32(floor(aCropRange.getMinY())), + sal_Int32(ceil(aCropRange.getMaxX())), sal_Int32(ceil(aCropRange.getMaxY()))); + } - if(!getObjectInfoPrimitive2D()->getDesc().isEmpty()) - { - if(!aAlternateDescription.isEmpty()) - { - aAlternateDescription += " - "; - } + // Create image alternative description from ObjectInfoPrimitive2D info + // for PDF export + if(mpPDFExtOutDevData->GetIsExportTaggedPDF() && nullptr != getObjectInfoPrimitive2D()) + { + OUString aAlternateDescription; - aAlternateDescription += getObjectInfoPrimitive2D()->getDesc(); - } + if(!getObjectInfoPrimitive2D()->getTitle().isEmpty()) + { + aAlternateDescription += getObjectInfoPrimitive2D()->getTitle(); + } - // Use SetAlternateText to set it. This will work as long as some - // structure is used (see PDFWriterImpl::setAlternateText and - // m_nCurrentStructElement - tagged PDF export works with this in - // Draw/Impress/Writer, but not in Calc due to too less structure...) - //Z maybe add structure to Calc PDF export, may need some BeginGroup/EndGroup stuff ..? + if(!getObjectInfoPrimitive2D()->getDesc().isEmpty()) + { if(!aAlternateDescription.isEmpty()) { - mpPDFExtOutDevData->SetAlternateText(aAlternateDescription); + aAlternateDescription += " - "; } + + aAlternateDescription += getObjectInfoPrimitive2D()->getDesc(); } - // #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); + // Use SetAlternateText to set it. This will work as long as some + // structure is used (see PDFWriterImpl::setAlternateText and + // m_nCurrentStructElement - tagged PDF export works with this in + // Draw/Impress/Writer, but not in Calc due to too less structure...) + //Z maybe add structure to Calc PDF export, may need some BeginGroup/EndGroup stuff ..? + if(!aAlternateDescription.isEmpty()) + { + mpPDFExtOutDevData->SetAlternateText(aAlternateDescription); + } } + + // #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) @@ -1096,88 +1096,88 @@ namespace drawinglayer::processor2d } // PDF export and printing only for printable controls - if(bIsPrintableControl) + if(!bIsPrintableControl) + return; + + const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields()); + bool bDoProcessRecursively(true); + + if(bPDFExport) { - const bool bPDFExport(mpPDFExtOutDevData && mpPDFExtOutDevData->GetIsExportFormFields()); - bool bDoProcessRecursively(true); + // 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(bPDFExport) + if (pPDFControl) { - // 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 ) ); + // 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 (pPDFControl) - { - // 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); - 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); + + mpPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::Form); + mpPDFExtOutDevData->CreateControl(*pPDFControl); + mpPDFExtOutDevData->EndStructureElement(); + + // no normal paint needed (see original UnoControlPDFExportContact::do_PaintObject); + // do not process recursively + bDoProcessRecursively = false; + } + else + { + // PDF export did not work, try simple output. + // Fallback to printer output by not setting bDoProcessRecursively + // to false. } + } - // #i93169# used flag the wrong way; true means that nothing was done yet - if(bDoProcessRecursively) + // #i93169# used flag the wrong way; true means that nothing was done yet + if(bDoProcessRecursively) + { + // printer output + try { - // 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()); + // 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); + 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)); + // 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; + // draw it + xControlView->draw(basegfx::fround(aTopLeftDiscrete.getX()), basegfx::fround(aTopLeftDiscrete.getY())); + bDoProcessRecursively = false; - // restore original graphics - xControlView->setGraphics(xOriginalGraphics); - } - } - catch( const uno::Exception& ) - { - TOOLS_WARN_EXCEPTION("drawinglayer", "VclMetafileProcessor2D: Printing of Control failed"); + // restore original graphics + xControlView->setGraphics(xOriginalGraphics); } } - - // process recursively if not done yet to export as decomposition (bitmap) - if(bDoProcessRecursively) + catch( const uno::Exception& ) { - process(rControlPrimitive); + TOOLS_WARN_EXCEPTION("drawinglayer", "VclMetafileProcessor2D: Printing of Control failed"); } } + + // process recursively if not done yet to export as decomposition (bitmap) + if(bDoProcessRecursively) + { + process(rControlPrimitive); + } } void VclMetafileProcessor2D::processTextHierarchyFieldPrimitive2D(const primitive2d::TextHierarchyFieldPrimitive2D& rFieldPrimitive) @@ -1222,19 +1222,19 @@ namespace drawinglayer::processor2d // for the end comment the type is not relevant yet, they are all the same. Just add. mpMetaFile->AddAction(new MetaCommentAction(aCommentStringEnd)); - if(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType()) - { - // emulate data handling from ImpEditEngine::Paint - const basegfx::B2DRange aViewRange(rContent.getB2DRange(getViewInformation2D())); - const ::tools::Rectangle aRectLogic( - static_cast<sal_Int32>(floor(aViewRange.getMinX())), static_cast<sal_Int32>(floor(aViewRange.getMinY())), - static_cast<sal_Int32>(ceil(aViewRange.getMaxX())), static_cast<sal_Int32>(ceil(aViewRange.getMaxY()))); - vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic); - aBookmark.aBookmark = aURL; - std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks(); - rBookmarks.push_back( aBookmark ); - } + if(!(mpPDFExtOutDevData && drawinglayer::primitive2d::FIELD_TYPE_URL == rFieldPrimitive.getType())) + return; + + // emulate data handling from ImpEditEngine::Paint + const basegfx::B2DRange aViewRange(rContent.getB2DRange(getViewInformation2D())); + const ::tools::Rectangle aRectLogic( + static_cast<sal_Int32>(floor(aViewRange.getMinX())), static_cast<sal_Int32>(floor(aViewRange.getMinY())), + static_cast<sal_Int32>(ceil(aViewRange.getMaxX())), static_cast<sal_Int32>(ceil(aViewRange.getMaxY()))); + vcl::PDFExtOutDevBookmarkEntry aBookmark; + aBookmark.nLinkId = mpPDFExtOutDevData->CreateLink(aRectLogic); + aBookmark.aBookmark = aURL; + std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = mpPDFExtOutDevData->GetBookmarks(); + rBookmarks.push_back( aBookmark ); } void VclMetafileProcessor2D::processTextHierarchyLinePrimitive2D(const primitive2d::TextHierarchyLinePrimitive2D& rLinePrimitive) @@ -1969,57 +1969,57 @@ namespace drawinglayer::processor2d void VclMetafileProcessor2D::processMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate) { // mask group. Special handling for MetaFiles. - if(!rMaskCandidate.getChildren().empty()) - { - basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); + if(rMaskCandidate.getChildren().empty()) + return; - if(aMask.count()) - { - // prepare new mask polygon and rescue current one - aMask.transform(maCurrentTransformation); - const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon); + basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); - 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. An 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(); - } + if(aMask.count()) + { + // prepare new mask polygon and rescue current one + aMask.transform(maCurrentTransformation); + const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon); - // restore to rescued clip polygon - maClipPolyPolygon = aLastClipPolyPolygon; + 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 { - // no mask, no clipping. recursively paint content + // 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. An 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()); } } @@ -2133,126 +2133,126 @@ namespace drawinglayer::processor2d 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); // loplugin:constvars:ignore - - if(!bForceToBigTransparentVDev && 1 == rTransparence.size()) - { - const primitive2d::Primitive2DReference xReference(rTransparence[0]); - pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get()); - } + if(rContent.empty() || rTransparence.empty()) + return; - // Check also for correct ID to exclude derived implementations - if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID()) - { - // various content, create content-metafile - GDIMetaFile aContentMetafile; - const ::tools::Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile)); + // try to identify a single FillGradientPrimitive2D in the + // transparence part of the primitive + const primitive2d::FillGradientPrimitive2D* pFiGradient = nullptr; + static bool bForceToBigTransparentVDev(false); // loplugin:constvars:ignore - // re-create a VCL-gradient from FillGradientPrimitive2D - Gradient aVCLGradient; - impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true); + if(!bForceToBigTransparentVDev && 1 == rTransparence.size()) + { + const primitive2d::Primitive2DReference xReference(rTransparence[0]); + pFiGradient = dynamic_cast< const primitive2d::FillGradientPrimitive2D* >(xReference.get()); + } - // render it to VCL - mpOutputDevice->DrawTransparent( - aContentMetafile, aPrimitiveRectangle.TopLeft(), - aPrimitiveRectangle.GetSize(), aVCLGradient); - } - else - { - // sub-transparence group. Draw to VDev first. - // this may get refined to tiling when resolution is too big here + // Check also for correct ID to exclude derived implementations + if(pFiGradient && PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D == pFiGradient->getPrimitive2DID()) + { + // various content, create content-metafile + GDIMetaFile aContentMetafile; + const ::tools::Rectangle aPrimitiveRectangle(impDumpToMetaFile(rContent, aContentMetafile)); + + // re-create a VCL-gradient from FillGradientPrimitive2D + Gradient aVCLGradient; + impConvertFillGradientAttributeToVCLGradient(aVCLGradient, pFiGradient->getFillGradient(), true); + + // render it to VCL + mpOutputDevice->DrawTransparent( + aContentMetafile, aPrimitiveRectangle.TopLeft(), + aPrimitiveRectangle.GetSize(), aVCLGradient); + } + else + { + // sub-transparence group. Draw to VDev first. + // this may get refined to tiling when resolution is too big here - // need to avoid switching off MapMode stuff here; maybe need another - // tooling class, cannot just do the same as with the pixel renderer. - // Need to experiment... + // 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. + // 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) + 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)) { - // 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)); + aViewTransform.scale(fDPIXChange, fDPIYChange); } - if(aBufferDevice->SetOutputSizePixel(aSizePixel)) + // also take scaling from Size reduction into account + if(!basegfx::fTools::equal(fReduceFactor, 1.0)) { - // 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); - - // 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)); + 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); + + // 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)); } } } diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index e94637a9a7fe..654fa6e6168f 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -462,22 +462,22 @@ namespace drawinglayer::processor2d basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor())); basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); - if(aLocalPolyPolygon.count()) - { - aLocalPolyPolygon.transform(maCurrentTransformation); + if(!aLocalPolyPolygon.count()) + return; - if(aStartColor == aEndColor) - { - // no gradient at all, draw as polygon in AA and non-AA case - mpOutputDevice->SetLineColor(); - mpOutputDevice->SetFillColor(Color(aStartColor)); - mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); - } - else - { - // use the primitive decomposition of the metafile - process(rPolygonCandidate); - } + aLocalPolyPolygon.transform(maCurrentTransformation); + + if(aStartColor == aEndColor) + { + // no gradient at all, draw as polygon in AA and non-AA case + mpOutputDevice->SetLineColor(); + mpOutputDevice->SetFillColor(Color(aStartColor)); + mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); + } + else + { + // use the primitive decomposition of the metafile + process(rPolygonCandidate); } } @@ -492,27 +492,27 @@ namespace drawinglayer::processor2d // when AA is on and this filled polygons are the result of stroked line geometry, // draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons // Caution: This is needed in both cases (!) - if(mnPolygonStrokePrimitive2D + if(!(mnPolygonStrokePrimitive2D && getOptionsDrawinglayer().IsAntiAliasing() - && (mpOutputDevice->GetAntialiasing() & AntialiasingFlags::EnableB2dDraw)) - { - const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolyPolygonColorPrimitive2D.getBColor())); - sal_uInt32 nCount(aLocalPolyPolygon.count()); + && (mpOutputDevice->GetAntialiasing() & AntialiasingFlags::EnableB2dDraw))) + return; - if(!nCount) - { - aLocalPolyPolygon = rPolyPolygonColorPrimitive2D.getB2DPolyPolygon(); - aLocalPolyPolygon.transform(maCurrentTransformation); - nCount = aLocalPolyPolygon.count(); - } + const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolyPolygonColorPrimitive2D.getBColor())); + sal_uInt32 nCount(aLocalPolyPolygon.count()); - mpOutputDevice->SetFillColor(); - mpOutputDevice->SetLineColor(Color(aPolygonColor)); + if(!nCount) + { + aLocalPolyPolygon = rPolyPolygonColorPrimitive2D.getB2DPolyPolygon(); + aLocalPolyPolygon.transform(maCurrentTransformation); + nCount = aLocalPolyPolygon.count(); + } - for(sal_uInt32 a(0); a < nCount; a++) - { - mpOutputDevice->DrawPolyLine(aLocalPolyPolygon.getB2DPolygon(a), 0.0); - } + mpOutputDevice->SetFillColor(); + mpOutputDevice->SetLineColor(Color(aPolygonColor)); + + for(sal_uInt32 a(0); a < nCount; a++) + { + mpOutputDevice->DrawPolyLine(aLocalPolyPolygon.getB2DPolygon(a), 0.0); } } @@ -522,75 +522,75 @@ namespace drawinglayer::processor2d // use the faster OutputDevice::DrawTransparent method const primitive2d::Primitive2DContainer& rContent = rUniTransparenceCandidate.getChildren(); - if(!rContent.empty()) + if(rContent.empty()) + return; + + if(0.0 == rUniTransparenceCandidate.getTransparence()) { - if(0.0 == rUniTransparenceCandidate.getTransparence()) - { - // not transparent at all, use content - process(rUniTransparenceCandidate.getChildren()); - } - else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0) + // not transparent at all, use content + process(rUniTransparenceCandidate.getChildren()); + } + else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0) + { + bool bDrawTransparentUsed(false); + + if(1 == rContent.size()) { - bool bDrawTransparentUsed(false); + const primitive2d::Primitive2DReference xReference(rContent[0]); + const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get()); - if(1 == rContent.size()) + if(pBasePrimitive) { - const primitive2d::Primitive2DReference xReference(rContent[0]); - const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get()); - - if(pBasePrimitive) + switch(pBasePrimitive->getPrimitive2DID()) { - switch(pBasePrimitive->getPrimitive2DID()) + case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D: + { + // single transparent tools::PolyPolygon identified, use directly + const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = static_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(pBasePrimitive); + SAL_WARN_IF(!pPoPoColor, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)"); + bDrawTransparentUsed = true; + tryDrawPolyPolygonColorPrimitive2DDirect(*pPoPoColor, rUniTransparenceCandidate.getTransparence()); + break; + } + case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D: { - case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D: - { - // single transparent tools::PolyPolygon identified, use directly - const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = static_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(pBasePrimitive); - SAL_WARN_IF(!pPoPoColor, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)"); - bDrawTransparentUsed = true; - tryDrawPolyPolygonColorPrimitive2DDirect(*pPoPoColor, rUniTransparenceCandidate.getTransparence()); - break; - } - case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D: - { - // single transparent PolygonHairlinePrimitive2D identified, use directly - const primitive2d::PolygonHairlinePrimitive2D* pPoHair = static_cast< const primitive2d::PolygonHairlinePrimitive2D* >(pBasePrimitive); - SAL_WARN_IF(!pPoHair, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)"); - - // do no tallow by default - problem is that self-overlapping parts of this geometry will - // not be in an all-same transparency but will already alpha-cover themselves with blending. - // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its - // content to be uniformly transparent. - // For hairline the effect is pretty minimal, but still not correct. - bDrawTransparentUsed = false; - break; - } - case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D: - { - // single transparent PolygonStrokePrimitive2D identified, use directly - const primitive2d::PolygonStrokePrimitive2D* pPoStroke = static_cast< const primitive2d::PolygonStrokePrimitive2D* >(pBasePrimitive); - SAL_WARN_IF(!pPoStroke, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)"); - - // do no tallow by default - problem is that self-overlapping parts of this geometry will - // not be in an all-same transparency but will already alpha-cover themselves with blending. - // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its - // content to be uniformly transparent. - // To check, activate and draw a wide transparent self-crossing line/curve - bDrawTransparentUsed = false; - break; - } - default: - SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(rUniTransparenceCandidate.getPrimitive2DID())); + // single transparent PolygonHairlinePrimitive2D identified, use directly + const primitive2d::PolygonHairlinePrimitive2D* pPoHair = static_cast< const primitive2d::PolygonHairlinePrimitive2D* >(pBasePrimitive); + SAL_WARN_IF(!pPoHair, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)"); + + // do no tallow by default - problem is that self-overlapping parts of this geometry will + // not be in an all-same transparency but will already alpha-cover themselves with blending. + // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its + // content to be uniformly transparent. + // For hairline the effect is pretty minimal, but still not correct. + bDrawTransparentUsed = false; break; } + case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D: + { + // single transparent PolygonStrokePrimitive2D identified, use directly + const primitive2d::PolygonStrokePrimitive2D* pPoStroke = static_cast< const primitive2d::PolygonStrokePrimitive2D* >(pBasePrimitive); + SAL_WARN_IF(!pPoStroke, "drawinglayer", "OOps, PrimitiveID and PrimitiveType do not match (!)"); + + // do no tallow by default - problem is that self-overlapping parts of this geometry will + // not be in an all-same transparency but will already alpha-cover themselves with blending. + // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its + // content to be uniformly transparent. + // To check, activate and draw a wide transparent self-crossing line/curve + bDrawTransparentUsed = false; + break; + } + default: + SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(rUniTransparenceCandidate.getPrimitive2DID())); + break; } } + } - if(!bDrawTransparentUsed) - { - // unified sub-transparence. Draw to VDev first. - RenderUnifiedTransparencePrimitive2D(rUniTransparenceCandidate); - } + if(!bDrawTransparentUsed) + { + // unified sub-transparence. Draw to VDev first. + RenderUnifiedTransparencePrimitive2D(rUniTransparenceCandidate); } } } diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index 34ff2992934f..f44c85c54eef 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -708,57 +708,56 @@ namespace drawinglayer::processor2d // mask group. Force output to VDev and create mask from given mask void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate) { - if(!rMaskCandidate.getChildren().empty()) - { - basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); + if(rMaskCandidate.getChildren().empty()) + return; - if(aMask.count()) - { - aMask.transform(maCurrentTransformation); - const basegfx::B2DRange aRange(basegfx::utils::getRange(aMask)); - impBufferDevice aBufferDevice(*mpOutputDevice, aRange); + basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask()); - if(aBufferDevice.isVisible()) - { - // remember last OutDev and set to content - OutputDevice* pLastOutputDevice = mpOutputDevice; - mpOutputDevice = &aBufferDevice.getContent(); + if(!aMask.count()) + return; - // paint to it - process(rMaskCandidate.getChildren()); + aMask.transform(maCurrentTransformation); + const basegfx::B2DRange aRange(basegfx::utils::getRange(aMask)); + impBufferDevice aBufferDevice(*mpOutputDevice, aRange); - // back to old OutDev - mpOutputDevice = pLastOutputDevice; + if(!aBufferDevice.isVisible()) + return; - // if the mask fills the whole area we can skip - // creating a transparent vd and filling it. - if (!basegfx::utils::isRectangle(aMask)) - { - // draw mask - if(getOptionsDrawinglayer().IsAntiAliasing()) - { - // with AA, use 8bit AlphaMask to get nice borders - VirtualDevice& rTransparence = aBufferDevice.getTransparence(); - rTransparence.SetLineColor(); - rTransparence.SetFillColor(COL_BLACK); - rTransparence.DrawPolyPolygon(aMask); - } - else - { - // No AA, use 1bit mask - VirtualDevice& rMask = aBufferDevice.getMask(); - rMask.SetLineColor(); - rMask.SetFillColor(COL_BLACK); - rMask.DrawPolyPolygon(aMask); - } - } + // remember last OutDev and set to content + OutputDevice* pLastOutputDevice = mpOutputDevice; + mpOutputDevice = &aBufferDevice.getContent(); - // dump buffer to outdev - aBufferDevice.paint(); + // paint to it + process(rMaskCandidate.getChildren()); - } + // back to old OutDev + mpOutputDevice = pLastOutputDevice; + + // if the mask fills the whole area we can skip + // creating a transparent vd and filling it. + if (!basegfx::utils::isRectangle(aMask)) + { + // draw mask + if(getOptionsDrawinglayer().IsAntiAliasing()) + { + // with AA, use 8bit AlphaMask to get nice borders + VirtualDevice& rTransparence = aBufferDevice.getTransparence(); + rTransparence.SetLineColor(); + rTransparence.SetFillColor(COL_BLACK); + rTransparence.DrawPolyPolygon(aMask); + } + else + { + // No AA, use 1bit mask + VirtualDevice& rMask = aBufferDevice.getMask(); + rMask.SetLineColor(); + rMask.SetFillColor(COL_BLACK); + rMask.DrawPolyPolygon(aMask); } } + + // dump buffer to outdev + aBufferDevice.paint(); } // modified color group. Force output to unified color. @@ -775,44 +774,17 @@ namespace drawinglayer::processor2d // unified sub-transparence. Draw to VDev first. void VclProcessor2D::RenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rTransCandidate) { - if(!rTransCandidate.getChildren().empty()) - { - if(0.0 == rTransCandidate.getTransparence()) - { - // no transparence used, so just use the content - process(rTransCandidate.getChildren()); - } - else if(rTransCandidate.getTransparence() > 0.0 && rTransCandidate.getTransparence() < 1.0) - { - // transparence is in visible range - basegfx::B2DRange aRange(rTransCandidate.getChildren().getB2DRange(getViewInformation2D())); - aRange.transform(maCurrentTransformation); - impBufferDevice aBufferDevice(*mpOutputDevice, aRange); + if(rTransCandidate.getChildren().empty()) + return; - if(aBufferDevice.isVisible()) - { - // remember last OutDev and set to content - OutputDevice* pLastOutputDevice = mpOutputDevice; - mpOutputDevice = &aBufferDevice.getContent(); - - // paint content to it - process(rTransCandidate.getChildren()); - - // back to old OutDev - mpOutputDevice = pLastOutputDevice; - - // dump buffer to outdev using given transparence - aBufferDevice.paint(rTransCandidate.getTransparence()); - } - } + if(0.0 == rTransCandidate.getTransparence()) + { + // no transparence used, so just use the content + process(rTransCandidate.getChildren()); } - } - - // sub-transparence group. Draw to VDev first. - void VclProcessor2D::RenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransCandidate) - { - if(!rTransCandidate.getChildren().empty()) + else if(rTransCandidate.getTransparence() > 0.0 && rTransCandidate.getTransparence() < 1.0) { + // transparence is in visible range basegfx::B2DRange aRange(rTransCandidate.getChildren().getB2DRange(getViewInformation2D())); aRange.transform(maCurrentTransformation); impBufferDevice aBufferDevice(*mpOutputDevice, aRange); @@ -826,28 +798,55 @@ namespace drawinglayer::processor2d // paint content to it process(rTransCandidate.getChildren()); - // set to mask - mpOutputDevice = &aBufferDevice.getTransparence(); - - // when painting transparence masks, reset the color stack - basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack); - maBColorModifierStack = basegfx::BColorModifierStack(); - - // paint mask to it (always with transparence intensities, evtl. with AA) - process(rTransCandidate.getTransparence()); - - // back to old color stack - maBColorModifierStack = aLastBColorModifierStack; - // back to old OutDev mpOutputDevice = pLastOutputDevice; - // dump buffer to outdev - aBufferDevice.paint(); + // dump buffer to outdev using given transparence + aBufferDevice.paint(rTransCandidate.getTransparence()); } } } + // sub-transparence group. Draw to VDev first. + void VclProcessor2D::RenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransCandidate) + { + if(rTransCandidate.getChildren().empty()) + return; + + basegfx::B2DRange aRange(rTransCandidate.getChildren().getB2DRange(getViewInformation2D())); + aRange.transform(maCurrentTransformation); + impBufferDevice aBufferDevice(*mpOutputDevice, aRange); + + if(!aBufferDevice.isVisible()) + return; + + // remember last OutDev and set to content + OutputDevice* pLastOutputDevice = mpOutputDevice; + mpOutputDevice = &aBufferDevice.getContent(); + + // paint content to it + process(rTransCandidate.getChildren()); + + // set to mask + mpOutputDevice = &aBufferDevice.getTransparence(); + + // when painting transparence masks, reset the color stack + basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack); + maBColorModifierStack = basegfx::BColorModifierStack(); + + // paint mask to it (always with transparence intensities, evtl. with AA) + process(rTransCandidate.getTransparence()); + + // back to old color stack + maBColorModifierStack = aLastBColorModifierStack; + + // back to old OutDev + mpOutputDevice = pLastOutputDevice; + + // dump buffer to outdev + aBufferDevice.paint(); + } + // transform group. void VclProcessor2D::RenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D& rTransformCandidate) { @@ -905,40 +904,40 @@ namespace drawinglayer::processor2d const std::vector< basegfx::B2DPoint >& rPositions = rMarkArrayCandidate.getPositions(); const sal_uInt32 nCount(rPositions.size()); - if(nCount && !rMarkArrayCandidate.getMarker().IsEmpty()) - { - // get pixel size - const BitmapEx& rMarker(rMarkArrayCandidate.getMarker()); - const Size aBitmapSize(rMarker.GetSizePixel()); + if(!(nCount && !rMarkArrayCandidate.getMarker().IsEmpty())) + return; - if(aBitmapSize.Width() && aBitmapSize.Height()) - { - // get discrete half size - const basegfx::B2DVector aDiscreteHalfSize( - (aBitmapSize.getWidth() - 1.0) * 0.5, - (aBitmapSize.getHeight() - 1.0) * 0.5); - const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled()); - - // do not forget evtl. moved origin in target device MapMode when - // switching it off; it would be missing and lead to wrong positions. - // All his could be done using logic sizes and coordinates, too, but - // we want a 1:1 bitmap rendering here, so it's more safe and faster - // to work with switching off MapMode usage completely. - const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin()); - - mpOutputDevice->EnableMapMode(false); - - for (auto const& pos : rPositions) - { - const basegfx::B2DPoint aDiscreteTopLeft((maCurrentTransformation * pos) - aDiscreteHalfSize); - const Point aDiscretePoint(basegfx::fround(aDiscreteTopLeft.getX()), basegfx::fround(aDiscreteTopLeft.getY())); + // get pixel size + const BitmapEx& rMarker(rMarkArrayCandidate.getMarker()); + const Size aBitmapSize(rMarker.GetSizePixel()); - mpOutputDevice->DrawBitmapEx(aDiscretePoint + aOrigin, rMarker); - } + if(!(aBitmapSize.Width() && aBitmapSize.Height())) + return; - mpOutputDevice->EnableMapMode(bWasEnabled); - } + // get discrete half size + const basegfx::B2DVector aDiscreteHalfSize( + (aBitmapSize.getWidth() - 1.0) * 0.5, + (aBitmapSize.getHeight() - 1.0) * 0.5); + const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled()); + + // do not forget evtl. moved origin in target device MapMode when + // switching it off; it would be missing and lead to wrong positions. + // All his could be done using logic sizes and coordinates, too, but + // we want a 1:1 bitmap rendering here, so it's more safe and faster + // to work with switching off MapMode usage completely. + const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin()); + + mpOutputDevice->EnableMapMode(false); + + for (auto const& pos : rPositions) + { + const basegfx::B2DPoint aDiscreteTopLeft((maCurrentTransformation * pos) - aDiscreteHalfSize); + const Point aDiscretePoint(basegfx::fround(aDiscreteTopLeft.getX()), basegfx::fround(aDiscreteTopLeft.getY())); + + mpOutputDevice->DrawBitmapEx(aDiscretePoint + aOrigin, rMarker); } + + mpOutputDevice->EnableMapMode(bWasEnabled); } // point @@ -1182,29 +1181,29 @@ namespace drawinglayer::processor2d basegfx::B2DRange aRange(0.0, 0.0, 1.0, 1.0); aRange.transform(maCurrentTransformation * rEpsPrimitive2D.getEpsTransform()); - if(!aRange.isEmpty()) - { - const ::tools::Rectangle aRectangle( - static_cast<sal_Int32>(floor(aRange.getMinX())), static_cast<sal_Int32>(floor(aRange.getMinY())), - static_cast<sal_Int32>(ceil(aRange.getMaxX())), static_cast<sal_Int32>(ceil(aRange.getMaxY()))); + if(aRange.isEmpty()) + return; - if(!aRectangle.IsEmpty()) - { - bool bWillReallyRender = mpOutputDevice->IsDeviceOutputNecessary(); - // try to paint EPS directly without fallback visualisation - const bool bEPSPaintedDirectly = bWillReallyRender && - mpOutputDevice->DrawEPS( - aRectangle.TopLeft(), - aRectangle.GetSize(), - rEpsPrimitive2D.getGfxLink()); - - if(!bEPSPaintedDirectly) - { - // use the decomposition which will correctly handle the - // fallback visualisation using full transformation (e.g. rotation) - process(rEpsPrimitive2D); - } - } + const ::tools::Rectangle aRectangle( + static_cast<sal_Int32>(floor(aRange.getMinX())), static_cast<sal_Int32>(floor(aRange.getMinY())), + static_cast<sal_Int32>(ceil(aRange.getMaxX())), static_cast<sal_Int32>(ceil(aRange.getMaxY()))); + + if(aRectangle.IsEmpty()) + return; + + bool bWillReallyRender = mpOutputDevice->IsDeviceOutputNecessary(); + // try to paint EPS directly without fallback visualisation + const bool bEPSPaintedDirectly = bWillReallyRender && + mpOutputDevice->DrawEPS( + aRectangle.TopLeft(), + aRectangle.GetSize(), + rEpsPrimitive2D.getGfxLink()); + + if(!bEPSPaintedDirectly) + { + // use the decomposition which will correctly handle the + // fallback visualisation using full transformation (e.g. rotation) + process(rEpsPrimitive2D); } } @@ -1225,44 +1224,44 @@ namespace drawinglayer::processor2d { const double fDelta(rCandidate.getOffsetB() - rCandidate.getOffsetA()); - if(basegfx::fTools::more(fDelta, 0.0)) - { - const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA())); - const basegfx::BColor aColorB(maBColorModifierStack.getModifiedColor(rCandidate.getColorB())); + if(!basegfx::fTools::more(fDelta, 0.0)) + return; - // calculate discrete unit in WorldCoordinates; use diagonal (1.0, 1.0) and divide by sqrt(2) - const basegfx::B2DVector aDiscreteVector(getViewInformation2D().getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); - const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373)); + const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA())); + const basegfx::BColor aColorB(maBColorModifierStack.getModifiedColor(rCandidate.getColorB())); - // use color distance and discrete lengths to calculate step count - const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDelta, fDiscreteUnit)); + // calculate discrete unit in WorldCoordinates; use diagonal (1.0, 1.0) and divide by sqrt(2) + const basegfx::B2DVector aDiscreteVector(getViewInformation2D().getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373)); - // switch off line painting - mpOutputDevice->SetLineColor(); + // use color distance and discrete lengths to calculate step count + const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDelta, fDiscreteUnit)); - // prepare polygon in needed width at start position (with discrete overlap) - const basegfx::B2DPolygon aPolygon( - basegfx::utils::createPolygonFromRect( - basegfx::B2DRange( - rCandidate.getOffsetA() - fDiscreteUnit, - 0.0, - rCandidate.getOffsetA() + (fDelta / nSteps) + fDiscreteUnit, - 1.0))); + // switch off line painting + mpOutputDevice->SetLineColor(); + // prepare polygon in needed width at start position (with discrete overlap) + const basegfx::B2DPolygon aPolygon( + basegfx::utils::createPolygonFromRect( + basegfx::B2DRange( + rCandidate.getOffsetA() - fDiscreteUnit, + 0.0, + rCandidate.getOffsetA() + (fDelta / nSteps) + fDiscreteUnit, + 1.0))); - // prepare loop ([0.0 .. 1.0[) - double fUnitScale(0.0); - const double fUnitStep(1.0 / nSteps); - // loop and paint - for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep) - { - basegfx::B2DPolygon aNew(aPolygon); + // prepare loop ([0.0 .. 1.0[) + double fUnitScale(0.0); + const double fUnitStep(1.0 / nSteps); - aNew.transform(maCurrentTransformation * basegfx::utils::createTranslateB2DHomMatrix(fDelta * fUnitScale, 0.0)); - mpOutputDevice->SetFillColor(Color(basegfx::interpolate(aColorA, aColorB, fUnitScale))); - mpOutputDevice->DrawPolyPolygon(basegfx::B2DPolyPolygon(aNew)); - } + // loop and paint + for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep) + { + basegfx::B2DPolygon aNew(aPolygon); + + aNew.transform(maCurrentTransformation * basegfx::utils::createTranslateB2DHomMatrix(fDelta * fUnitScale, 0.0)); + mpOutputDevice->SetFillColor(Color(basegfx::interpolate(aColorA, aColorB, fUnitScale))); + mpOutputDevice->DrawPolyPolygon(basegfx::B2DPolyPolygon(aNew)); } } @@ -1270,57 +1269,57 @@ namespace drawinglayer::processor2d { const double fDeltaScale(rCandidate.getScaleB() - rCandidate.getScaleA()); - if(basegfx::fTools::more(fDeltaScale, 0.0)) - { - const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA())); - const basegfx::BColor aColorB(maBColorModifierStack.getModifiedColor(rCandidate.getColorB())); + if(!basegfx::fTools::more(fDeltaScale, 0.0)) + return; - // calculate discrete unit in WorldCoordinates; use diagonal (1.0, 1.0) and divide by sqrt(2) - const basegfx::B2DVector aDiscreteVector(getViewInformation2D().getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); - const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373)); + const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA())); + const basegfx::BColor aColorB(maBColorModifierStack.getModifiedColor(rCandidate.getColorB())); - // use color distance and discrete lengths to calculate step count - const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDeltaScale, fDiscreteUnit)); + // calculate discrete unit in WorldCoordinates; use diagonal (1.0, 1.0) and divide by sqrt(2) + const basegfx::B2DVector aDiscreteVector(getViewInformation2D().getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373)); - // switch off line painting - mpOutputDevice->SetLineColor(); + // use color distance and discrete lengths to calculate step count + const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDeltaScale, fDiscreteUnit)); - // prepare loop ([0.0 .. 1.0[, full polygons, no polypolygons with holes) - double fUnitScale(0.0); - const double fUnitStep(1.0 / nSteps); + // switch off line painting + mpOutputDevice->SetLineColor(); - for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep) - { - basegfx::B2DHomMatrix aTransform; - const double fEndScale(rCandidate.getScaleB() - (fDeltaScale * fUnitScale)); + // prepare loop ([0.0 .. 1.0[, full polygons, no polypolygons with holes) + double fUnitScale(0.0); + const double fUnitStep(1.0 / nSteps); - if(rCandidate.isTranslateSet()) - { - const basegfx::B2DVector aTranslate( - basegfx::interpolate( - rCandidate.getTranslateB(), - rCandidate.getTranslateA(), - fUnitScale)); - - aTransform = basegfx::utils::createScaleTranslateB2DHomMatrix( - fEndScale, - fEndScale, - aTranslate.getX(), - aTranslate.getY()); - } - else - { - aTransform = basegfx::utils::createScaleB2DHomMatrix( - fEndScale, - fEndScale); - } - - basegfx::B2DPolygon aNew(basegfx::utils::createPolygonFromUnitCircle()); + for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep) + { + basegfx::B2DHomMatrix aTransform; + const double fEndScale(rCandidate.getScaleB() - (fDeltaScale * fUnitScale)); - aNew.transform(maCurrentTransformation * aTransform); - mpOutputDevice->SetFillColor(Color(basegfx::interpolate(aColorB, aColorA, fUnitScale))); - mpOutputDevice->DrawPolyPolygon(basegfx::B2DPolyPolygon(aNew)); + if(rCandidate.isTranslateSet()) + { + const basegfx::B2DVector aTranslate( + basegfx::interpolate( + rCandidate.getTranslateB(), + rCandidate.getTranslateA(), + fUnitScale)); + + aTransform = basegfx::utils::createScaleTranslateB2DHomMatrix( + fEndScale, + fEndScale, + aTranslate.getX(), + aTranslate.getY()); + } + else + { + aTransform = basegfx::utils::createScaleB2DHomMatrix( + fEndScale, + fEndScale); } + + basegfx::B2DPolygon aNew(basegfx::utils::createPolygonFromUnitCircle()); + + aNew.transform(maCurrentTransformation * aTransform); + mpOutputDevice->SetFillColor(Color(basegfx::interpolate(aColorB, aColorA, fUnitScale))); + mpOutputDevice->DrawPolyPolygon(basegfx::B2DPolyPolygon(aNew)); } } @@ -1328,95 +1327,95 @@ namespace drawinglayer::processor2d { const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode()); - if(nOriginalDrawMode & (DrawModeFlags::BlackLine|DrawModeFlags::GrayLine|DrawModeFlags::WhiteLine|DrawModeFlags::SettingsLine)) - { - DrawModeFlags nAdaptedDrawMode(nOriginalDrawMode); + if(!(nOriginalDrawMode & (DrawModeFlags::BlackLine|DrawModeFlags::GrayLine|DrawModeFlags::WhiteLine|DrawModeFlags::SettingsLine))) + return; - if(nOriginalDrawMode & DrawModeFlags::BlackLine) - { - nAdaptedDrawMode |= DrawModeFlags::BlackFill; - } - else - { - nAdaptedDrawMode &= ~DrawModeFlags::BlackFill; - } + DrawModeFlags nAdaptedDrawMode(nOriginalDrawMode); - if(nOriginalDrawMode & DrawModeFlags::GrayLine) - { - nAdaptedDrawMode |= DrawModeFlags::GrayFill; - } - else - { - nAdaptedDrawMode &= ~DrawModeFlags::GrayFill; - } + if(nOriginalDrawMode & DrawModeFlags::BlackLine) + { + nAdaptedDrawMode |= DrawModeFlags::BlackFill; + } + else + { + nAdaptedDrawMode &= ~DrawModeFlags::BlackFill; + } - if(nOriginalDrawMode & DrawModeFlags::WhiteLine) - { - nAdaptedDrawMode |= DrawModeFlags::WhiteFill; - } - else - { - nAdaptedDrawMode &= ~DrawModeFlags::WhiteFill; - } + if(nOriginalDrawMode & DrawModeFlags::GrayLine) + { + nAdaptedDrawMode |= DrawModeFlags::GrayFill; + } + else + { + nAdaptedDrawMode &= ~DrawModeFlags::GrayFill; + } - if(nOriginalDrawMode & DrawModeFlags::SettingsLine) - { - nAdaptedDrawMode |= DrawModeFlags::SettingsFill; - } - else - { - nAdaptedDrawMode &= ~DrawModeFlags::SettingsFill; - } + if(nOriginalDrawMode & DrawModeFlags::WhiteLine) + { + nAdaptedDrawMode |= DrawModeFlags::WhiteFill; + } + else + { + nAdaptedDrawMode &= ~DrawModeFlags::WhiteFill; + } - mpOutputDevice->SetDrawMode(nAdaptedDrawMode); + if(nOriginalDrawMode & DrawModeFlags::SettingsLine) + { + nAdaptedDrawMode |= DrawModeFlags::SettingsFill; + } + else + { + nAdaptedDrawMode &= ~DrawModeFlags::SettingsFill; } + + mpOutputDevice->SetDrawMode(nAdaptedDrawMode); } void VclProcessor2D::adaptTextToFillDrawMode() const { const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode()); - if(nOriginalDrawMode & (DrawModeFlags::BlackText|DrawModeFlags::GrayText|DrawModeFlags::WhiteText|DrawModeFlags::SettingsText)) - { - DrawModeFlags nAdaptedDrawMode(nOriginalDrawMode); + if(!(nOriginalDrawMode & (DrawModeFlags::BlackText|DrawModeFlags::GrayText|DrawModeFlags::WhiteText|DrawModeFlags::SettingsText))) + return; - if(nOriginalDrawMode & DrawModeFlags::BlackText) - { - nAdaptedDrawMode |= DrawModeFlags::BlackFill; - } - else - { - nAdaptedDrawMode &= ~DrawModeFlags::BlackFill; - } + DrawModeFlags nAdaptedDrawMode(nOriginalDrawMode); - if(nOriginalDrawMode & DrawModeFlags::GrayText) - { - nAdaptedDrawMode |= DrawModeFlags::GrayFill; - } - else - { - nAdaptedDrawMode &= ~DrawModeFlags::GrayFill; - } + if(nOriginalDrawMode & DrawModeFlags::BlackText) + { + nAdaptedDrawMode |= DrawModeFlags::BlackFill; + } + else + { + nAdaptedDrawMode &= ~DrawModeFlags::BlackFill; + } - if(nOriginalDrawMode & DrawModeFlags::WhiteText) - { - nAdaptedDrawMode |= DrawModeFlags::WhiteFill; - } - else - { - nAdaptedDrawMode &= ~DrawModeFlags::WhiteFill; - } + if(nOriginalDrawMode & DrawModeFlags::GrayText) + { + nAdaptedDrawMode |= DrawModeFlags::GrayFill; + } + else + { + nAdaptedDrawMode &= ~DrawModeFlags::GrayFill; + } - if(nOriginalDrawMode & DrawModeFlags::SettingsText) - { - nAdaptedDrawMode |= DrawModeFlags::SettingsFill; - } - else - { - nAdaptedDrawMode &= ~DrawModeFlags::SettingsFill; - } + if(nOriginalDrawMode & DrawModeFlags::WhiteText) + { + nAdaptedDrawMode |= DrawModeFlags::WhiteFill; + } + else + { + nAdaptedDrawMode &= ~DrawModeFlags::WhiteFill; + } - mpOutputDevice->SetDrawMode(nAdaptedDrawMode); + if(nOriginalDrawMode & DrawModeFlags::SettingsText) + { + nAdaptedDrawMode |= DrawModeFlags::SettingsFill; } + else + { + nAdaptedDrawMode &= ~DrawModeFlags::SettingsFill; + } + + mpOutputDevice->SetDrawMode(nAdaptedDrawMode); } // process support diff --git a/drawinglayer/source/processor3d/baseprocessor3d.cxx b/drawinglayer/source/processor3d/baseprocessor3d.cxx index a21cc1a19145..508ee553f31c 100644 --- a/drawinglayer/source/processor3d/baseprocessor3d.cxx +++ b/drawinglayer/source/processor3d/baseprocessor3d.cxx @@ -41,30 +41,30 @@ namespace drawinglayer::processor3d void BaseProcessor3D::process(const primitive3d::Primitive3DContainer& rSource) { - if(!rSource.empty()) + if(rSource.empty()) + return; + + const size_t nCount(rSource.size()); + + for(size_t a(0); a < nCount; a++) { - const size_t nCount(rSource.size()); + // get reference + const primitive3d::Primitive3DReference xReference(rSource[a]); - for(size_t a(0); a < nCount; a++) + if(xReference.is()) { - // get reference - const primitive3d::Primitive3DReference xReference(rSource[a]); + // try to cast to BasePrimitive3D implementation + const primitive3d::BasePrimitive3D* pBasePrimitive = dynamic_cast< const primitive3d::BasePrimitive3D* >(xReference.get()); - if(xReference.is()) + if(pBasePrimitive) { - // try to cast to BasePrimitive3D implementation - const primitive3d::BasePrimitive3D* pBasePrimitive = dynamic_cast< const primitive3d::BasePrimitive3D* >(xReference.get()); - - if(pBasePrimitive) - { - processBasePrimitive3D(*pBasePrimitive); - } - else - { - // unknown implementation, use UNO API call instead and process recursively - const uno::Sequence< beans::PropertyValue >& rViewParameters(getViewInformation3D().getViewInformationSequence()); - process(comphelper::sequenceToContainer<primitive3d::Primitive3DContainer>(xReference->getDecomposition(rViewParameters))); - } + processBasePrimitive3D(*pBasePrimitive); + } + else + { + // unknown implementation, use UNO API call instead and process recursively + const uno::Sequence< beans::PropertyValue >& rViewParameters(getViewInformation3D().getViewInformationSequence()); + process(comphelper::sequenceToContainer<primitive3d::Primitive3DContainer>(xReference->getDecomposition(rViewParameters))); } } } diff --git a/drawinglayer/source/processor3d/defaultprocessor3d.cxx b/drawinglayer/source/processor3d/defaultprocessor3d.cxx index dc25be5edd1b..b754c980637f 100644 --- a/drawinglayer/source/processor3d/defaultprocessor3d.cxx +++ b/drawinglayer/source/processor3d/defaultprocessor3d.cxx @@ -47,160 +47,160 @@ namespace drawinglayer::processor3d { const primitive3d::Primitive3DContainer& rSubSequence = rPrimitive.getChildren(); - if(!rSubSequence.empty()) + if(rSubSequence.empty()) + return; + + // rescue values + const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate(); + const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter(); + const bool bOldSimpleTextureActive(getSimpleTextureActive()); + std::shared_ptr< texture::GeoTexSvx > pOldTex = bTransparence ? mpTransparenceGeoTexSvx : mpGeoTexSvx; + + // create texture + const attribute::FillGradientAttribute& rFillGradient = rPrimitive.getGradient(); + const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY()); + const attribute::GradientStyle aGradientStyle(rFillGradient.getStyle()); + sal_uInt32 nSteps(rFillGradient.getSteps()); + const basegfx::BColor& aStart(rFillGradient.getStartColor()); + const basegfx::BColor& aEnd(rFillGradient.getEndColor()); + const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5)); + std::shared_ptr< texture::GeoTexSvx > pNewTex; + + if(nMaxSteps) { - // rescue values - const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate(); - const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter(); - const bool bOldSimpleTextureActive(getSimpleTextureActive()); - std::shared_ptr< texture::GeoTexSvx > pOldTex = bTransparence ? mpTransparenceGeoTexSvx : mpGeoTexSvx; - - // create texture - const attribute::FillGradientAttribute& rFillGradient = rPrimitive.getGradient(); - const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY()); - const attribute::GradientStyle aGradientStyle(rFillGradient.getStyle()); - sal_uInt32 nSteps(rFillGradient.getSteps()); - const basegfx::BColor& aStart(rFillGradient.getStartColor()); - const basegfx::BColor& aEnd(rFillGradient.getEndColor()); - const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5)); - std::shared_ptr< texture::GeoTexSvx > pNewTex; - - if(nMaxSteps) + // there IS a color distance + if(nSteps == 0) + { + nSteps = nMaxSteps; + } + + if(nSteps < 2) + { + nSteps = 2; + } + + if(nSteps > nMaxSteps) + { + nSteps = nMaxSteps; + } + + switch(aGradientStyle) { - // there IS a color distance - if(nSteps == 0) + case attribute::GradientStyle::Linear: { - nSteps = nMaxSteps; + pNewTex = std::make_shared<texture::GeoTexSvxGradientLinear>( + aOutlineRange, + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getAngle()); + break; } - - if(nSteps < 2) + case attribute::GradientStyle::Axial: { - nSteps = 2; + pNewTex = std::make_shared<texture::GeoTexSvxGradientAxial>( + aOutlineRange, + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getAngle()); + break; } - - if(nSteps > nMaxSteps) + case attribute::GradientStyle::Radial: { - nSteps = nMaxSteps; + pNewTex = + std::make_shared<texture::GeoTexSvxGradientRadial>( + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getOffsetX(), + rFillGradient.getOffsetY()); + break; } - - switch(aGradientStyle) + case attribute::GradientStyle::Elliptical: { - case attribute::GradientStyle::Linear: - { - pNewTex = std::make_shared<texture::GeoTexSvxGradientLinear>( - aOutlineRange, - aOutlineRange, - aStart, - aEnd, - nSteps, - rFillGradient.getBorder(), - rFillGradient.getAngle()); - break; - } - case attribute::GradientStyle::Axial: - { - pNewTex = std::make_shared<texture::GeoTexSvxGradientAxial>( - aOutlineRange, - aOutlineRange, - aStart, - aEnd, - nSteps, - rFillGradient.getBorder(), - rFillGradient.getAngle()); - break; - } - case attribute::GradientStyle::Radial: - { - pNewTex = - std::make_shared<texture::GeoTexSvxGradientRadial>( - aOutlineRange, - aStart, - aEnd, - nSteps, - rFillGradient.getBorder(), - rFillGradient.getOffsetX(), - rFillGradient.getOffsetY()); - break; - } - case attribute::GradientStyle::Elliptical: - { - pNewTex = - std::make_shared<texture::GeoTexSvxGradientElliptical>( - aOutlineRange, - aStart, - aEnd, - nSteps, - rFillGradient.getBorder(), - rFillGradient.getOffsetX(), - rFillGradient.getOffsetY(), - rFillGradient.getAngle()); - break; - } - case attribute::GradientStyle::Square: - { - pNewTex = - std::make_shared<texture::GeoTexSvxGradientSquare>( - aOutlineRange, - aStart, - aEnd, - nSteps, - rFillGradient.getBorder(), - rFillGradient.getOffsetX(), - rFillGradient.getOffsetY(), - rFillGradient.getAngle()); - break; - } - case attribute::GradientStyle::Rect: - { - pNewTex = - std::make_shared<texture::GeoTexSvxGradientRect>( - aOutlineRange, - aStart, - aEnd, - nSteps, - rFillGradient.getBorder(), - rFillGradient.getOffsetX(), - rFillGradient.getOffsetY(), - rFillGradient.getAngle()); - break; - } + pNewTex = + std::make_shared<texture::GeoTexSvxGradientElliptical>( + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getOffsetX(), + rFillGradient.getOffsetY(), + rFillGradient.getAngle()); + break; + } + case attribute::GradientStyle::Square: + { + pNewTex = + std::make_shared<texture::GeoTexSvxGradientSquare>( + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getOffsetX(), + rFillGradient.getOffsetY(), + rFillGradient.getAngle()); + break; + } + case attribute::GradientStyle::Rect: + { + pNewTex = + std::make_shared<texture::GeoTexSvxGradientRect>( + aOutlineRange, + aStart, + aEnd, + nSteps, + rFillGradient.getBorder(), + rFillGradient.getOffsetX(), + rFillGradient.getOffsetY(), + rFillGradient.getAngle()); + break; } - - mbSimpleTextureActive = false; - } - else - { - // no color distance -> same color, use simple texture - pNewTex = std::make_shared<texture::GeoTexSvxMono>(aStart, 1.0 - aStart.luminance()); - mbSimpleTextureActive = true; } - // set created texture - if(bTransparence) - { - mpTransparenceGeoTexSvx = pNewTex; - } - else - { - mpGeoTexSvx = pNewTex; - } + mbSimpleTextureActive = false; + } + else + { + // no color distance -> same color, use simple texture + pNewTex = std::make_shared<texture::GeoTexSvxMono>(aStart, 1.0 - aStart.luminance()); + mbSimpleTextureActive = true; + } - // process sub-list - process(rSubSequence); + // set created texture + if(bTransparence) + { + mpTransparenceGeoTexSvx = pNewTex; + } + else + { + mpGeoTexSvx = pNewTex; + } - // restore values - mbModulate = bOldModulate; - mbFilter = bOldFilter; - mbSimpleTextureActive = bOldSimpleTextureActive; + // process sub-list + process(rSubSequence); - if(bTransparence) - { - mpTransparenceGeoTexSvx = pOldTex; - } - else - { - mpGeoTexSvx = pOldTex; - } + // restore values + mbModulate = bOldModulate; + mbFilter = bOldFilter; + mbSimpleTextureActive = bOldSimpleTextureActive; + + if(bTransparence) + { + mpTransparenceGeoTexSvx = pOldTex; + } + else + { + mpGeoTexSvx = pOldTex; } } @@ -208,92 +208,92 @@ namespace drawinglayer::processor3d { const primitive3d::Primitive3DContainer& rSubSequence = rPrimitive.getChildren(); - if(!rSubSequence.empty()) - { - // rescue values - const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate(); - const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter(); - std::shared_ptr< texture::GeoTexSvx > pOldTex = mpGeoTexSvx; - - // calculate logic pixel size in object coordinates. Create transformation view - // to object by inverting ObjectToView - basegfx::B3DHomMatrix aInvObjectToView(getViewInformation3D().getObjectToView()); - aInvObjectToView.invert(); - - // back-project discrete coordinates to object coordinates and extract - // maximum distance - const basegfx::B3DPoint aZero(aInvObjectToView * basegfx::B3DPoint(0.0, 0.0, 0.0)); - const basegfx::B3DPoint aOne(aInvObjectToView * basegfx::B3DPoint(1.0, 1.0, 1.0)); - const basegfx::B3DVector aLogicPixel(aOne - aZero); - double fLogicPixelSizeWorld(std::max(std::max(fabs(aLogicPixel.getX()), fabs(aLogicPixel.getY())), fabs(aLogicPixel.getZ()))); - - // calculate logic pixel size in texture coordinates - const double fLogicTexSizeX(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getX()); - const double fLogicTexSizeY(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getY()); - const double fLogicTexSize(std::max(fLogicTexSizeX, fLogicTexSizeY)); - - // create texture and set - mpGeoTexSvx = std::make_shared<texture::GeoTexSvxMultiHatch>(rPrimitive, fLogicTexSize); - - // process sub-list - process(rSubSequence); - - // restore values - mbModulate = bOldModulate; - mbFilter = bOldFilter; - mpGeoTexSvx = pOldTex; - } + if(rSubSequence.empty()) + return; + + // rescue values + const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate(); + const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter(); + std::shared_ptr< texture::GeoTexSvx > pOldTex = mpGeoTexSvx; + + // calculate logic pixel size in object coordinates. Create transformation view + // to object by inverting ObjectToView + basegfx::B3DHomMatrix aInvObjectToView(getViewInformation3D().getObjectToView()); + aInvObjectToView.invert(); + + // back-project discrete coordinates to object coordinates and extract + // maximum distance + const basegfx::B3DPoint aZero(aInvObjectToView * basegfx::B3DPoint(0.0, 0.0, 0.0)); + const basegfx::B3DPoint aOne(aInvObjectToView * basegfx::B3DPoint(1.0, 1.0, 1.0)); + const basegfx::B3DVector aLogicPixel(aOne - aZero); + double fLogicPixelSizeWorld(std::max(std::max(fabs(aLogicPixel.getX()), fabs(aLogicPixel.getY())), fabs(aLogicPixel.getZ()))); + + // calculate logic pixel size in texture coordinates + const double fLogicTexSizeX(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getX()); + const double fLogicTexSizeY(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getY()); + const double fLogicTexSize(std::max(fLogicTexSizeX, fLogicTexSizeY)); + + // create texture and set + mpGeoTexSvx = std::make_shared<texture::GeoTexSvxMultiHatch>(rPrimitive, fLogicTexSize); + + // process sub-list + process(rSubSequence); + + // restore values + mbModulate = bOldModulate; + mbFilter = bOldFilter; + mpGeoTexSvx = pOldTex; } void DefaultProcessor3D::impRenderBitmapTexturePrimitive3D(const primitive3d::BitmapTexturePrimitive3D& rPrimitive) { const primitive3d::Primitive3DContainer& rSubSequence = rPrimitive.getChildren(); - if(!rSubSequence.empty()) - { - // rescue values - const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate(); - const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter(); - std::shared_ptr< texture::GeoTexSvx > pOldTex = mpGeoTexSvx; - - // create texture - const attribute::FillGraphicAttribute& rFillGraphicAttribute = rPrimitive.getFillGraphicAttribute(); + if(rSubSequence.empty()) + return; - // #121194# For 3D texture we will use the BitmapRex representation - const BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx()); + // rescue values + const bool bOldModulate(getModulate()); mbModulate = rPrimitive.getModulate(); + const bool bOldFilter(getFilter()); mbFilter = rPrimitive.getFilter(); + std::shared_ptr< texture::GeoTexSvx > pOldTex = mpGeoTexSvx; - // create range scaled by texture size - basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange()); + // create texture + const attribute::FillGraphicAttribute& rFillGraphicAttribute = rPrimitive.getFillGraphicAttribute(); - aGraphicRange.transform( - basegfx::utils::createScaleB2DHomMatrix( - rPrimitive.getTextureSize())); + // #121194# For 3D texture we will use the BitmapRex representation + const BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx()); - if(rFillGraphicAttribute.getTiling()) - { - mpGeoTexSvx = - std::make_shared<texture::GeoTexSvxBitmapExTiled>( - aBitmapEx, - aGraphicRange, - rFillGraphicAttribute.getOffsetX(), - rFillGraphicAttribute.getOffsetY()); - } - else - { - mpGeoTexSvx = - std::make_shared<texture::GeoTexSvxBitmapEx>( - aBitmapEx, - aGraphicRange); - } + // create range scaled by texture size + basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange()); - // process sub-list - process(rSubSequence); + aGraphicRange.transform( + basegfx::utils::createScaleB2DHomMatrix( + rPrimitive.getTextureSize())); - // restore values - mbModulate = bOldModulate; - mbFilter = bOldFilter; - mpGeoTexSvx = pOldTex; + if(rFillGraphicAttribute.getTiling()) + { + mpGeoTexSvx = + std::make_shared<texture::GeoTexSvxBitmapExTiled>( + aBitmapEx, + aGraphicRange, + rFillGraphicAttribute.getOffsetX(), + rFillGraphicAttribute.getOffsetY()); } + else + { + mpGeoTexSvx = + std::make_shared<texture::GeoTexSvxBitmapEx>( + aBitmapEx, + aGraphicRange); + } + + // process sub-list + process(rSubSequence); + + // restore values + mbModulate = bOldModulate; + mbFilter = bOldFilter; + mpGeoTexSvx = pOldTex; } void DefaultProcessor3D::impRenderModifiedColorPrimitive3D(const primitive3d::ModifiedColorPrimitive3D& rModifiedCandidate) @@ -317,24 +317,24 @@ namespace drawinglayer::processor3d { basegfx::B3DPolygon aHairline(rPrimitive.getB3DPolygon()); - if(aHairline.count()) - { - // hairlines need no extra data, clear it - aHairline.clearTextureCoordinates(); - aHairline.clearNormals(); - aHairline.clearBColors(); + if(!aHairline.count()) + return; - // transform to device coordinates (-1.0 .. 1.0) and check for visibility - aHairline.transform(getViewInformation3D().getObjectToView()); - const basegfx::B3DRange a3DRange(basegfx::utils::getRange(aHairline)); - const basegfx::B2DRange a2DRange(a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY()); + // hairlines need no extra data, clear it + aHairline.clearTextureCoordinates(); + aHairline.clearNormals(); + aHairline.clearBColors(); - if(a2DRange.overlaps(maRasterRange)) - { - const attribute::MaterialAttribute3D aMaterial(maBColorModifierStack.getModifiedColor(rPrimitive.getBColor())); + // transform to device coordinates (-1.0 .. 1.0) and check for visibility + aHairline.transform(getViewInformation3D().getObjectToView()); + const basegfx::B3DRange a3DRange(basegfx::utils::getRange(aHairline)); + const basegfx::B2DRange a2DRange(a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY()); - rasterconvertB3DPolygon(aMaterial, aHairline); - } + if(a2DRange.overlaps(maRasterRange)) + { + const attribute::MaterialAttribute3D aMaterial(maBColorModifierStack.getModifiedColor(rPrimitive.getBColor())); + + rasterconvertB3DPolygon(aMaterial, aHairline); } } @@ -385,95 +385,95 @@ namespace drawinglayer::processor3d } } - if(bPaintIt) + if(!bPaintIt) + return; + + // prepare ObjectToEye in NormalTransform + basegfx::B3DHomMatrix aNormalTransform(getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation()); + + if(getSdrSceneAttribute().getTwoSidedLighting()) { - // prepare ObjectToEye in NormalTransform - basegfx::B3DHomMatrix aNormalTransform(getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation()); + // get plane normal of polygon in view coordinates (with ZBuffer values), + // left-handed coordinate system + const basegfx::B3DVector aPlaneNormal(aFill.getB3DPolygon(0).getNormal()); - if(getSdrSceneAttribute().getTwoSidedLighting()) + if(aPlaneNormal.getZ() > 0.0) { - // get plane normal of polygon in view coordinates (with ZBuffer values), - // left-handed coordinate system - const basegfx::B3DVector aPlaneNormal(aFill.getB3DPolygon(0).getNormal()); - - if(aPlaneNormal.getZ() > 0.0) - { - // mirror normals - aNormalTransform.scale(-1.0, -1.0, -1.0); - } + // mirror normals + aNormalTransform.scale(-1.0, -1.0, -1.0); } + } - switch(aShadeMode) + switch(aShadeMode) + { + case css::drawing::ShadeMode_PHONG: { - case css::drawing::ShadeMode_PHONG: - { - // phong shading. Transform normals to eye coor - aFill.transformNormals(aNormalTransform); - break; - } - case css::drawing::ShadeMode_SMOOTH: - { - // gouraud shading. Transform normals to eye coor - aFill.transformNormals(aNormalTransform); + // phong shading. Transform normals to eye coor + aFill.transformNormals(aNormalTransform); + break; + } + case css::drawing::ShadeMode_SMOOTH: + { + // gouraud shading. Transform normals to eye coor + aFill.transformNormals(aNormalTransform); - // prepare color model parameters, evtl. use blend color - const basegfx::BColor aColor(getModulate() ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor()); - const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular()); - const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission()); - const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity()); + // prepare color model parameters, evtl. use blend color + const basegfx::BColor aColor(getModulate() ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor()); + const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular()); + const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission()); + const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity()); - // solve color model for each normal vector, set colors at points. Clear normals. - for(sal_uInt32 a(0); a < aFill.count(); a++) - { - basegfx::B3DPolygon aPartFill(aFill.getB3DPolygon(a)); - - for(sal_uInt32 b(0); b < aPartFill.count(); b++) - { - // solve color model. Transform normal to eye coor - const basegfx::B3DVector aNormal(aPartFill.getNormal(b)); - const basegfx::BColor aSolvedColor(getSdrLightingAttribute().solveColorModel(aNormal, aColor, rSpecular, rEmission, nSpecularIntensity)); - aPartFill.setBColor(b, aSolvedColor); - } - - // clear normals on this part polygon and write it back - aPartFill.clearNormals(); - aFill.setB3DPolygon(a, aPartFill); - } - break; - } - case css::drawing::ShadeMode_FLAT: + // solve color model for each normal vector, set colors at points. Clear normals. + for(sal_uInt32 a(0); a < aFill.count(); a++) { - // flat shading. Get plane vector in eye coordinates - const basegfx::B3DVector aPlaneEyeNormal(aNormalTransform * rPrimitive.getB3DPolyPolygon().getB3DPolygon(0).getNormal()); + basegfx::B3DPolygon aPartFill(aFill.getB3DPolygon(a)); - // prepare color model parameters, evtl. use blend color - const basegfx::BColor aColor(getModulate() ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor()); - const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular()); - const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission()); - const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity()); + for(sal_uInt32 b(0); b < aPartFill.count(); b++) + { + // solve color model. Transform normal to eye coor + const basegfx::B3DVector aNormal(aPartFill.getNormal(b)); + const basegfx::BColor aSolvedColor(getSdrLightingAttribute().solveColorModel(aNormal, aColor, rSpecular, rEmission, nSpecularIntensity)); + aPartFill.setBColor(b, aSolvedColor); + } - // solve color model for plane vector and use that color for whole plane - aObjectColor = getSdrLightingAttribute().solveColorModel(aPlaneEyeNormal, aColor, rSpecular, rEmission, nSpecularIntensity); - break; - } - default: // case css::drawing::ShadeMode_DRAFT: - { - // draft, just use object color which is already set. Delete all other infos - aFill.clearNormals(); - aFill.clearBColors(); - break; + // clear normals on this part polygon and write it back + aPartFill.clearNormals(); + aFill.setB3DPolygon(a, aPartFill); } + break; } + case css::drawing::ShadeMode_FLAT: + { + // flat shading. Get plane vector in eye coordinates + const basegfx::B3DVector aPlaneEyeNormal(aNormalTransform * rPrimitive.getB3DPolyPolygon().getB3DPolygon(0).getNormal()); - // draw it to ZBuffer - const attribute::MaterialAttribute3D aMaterial( - maBColorModifierStack.getModifiedColor(aObjectColor), - rPrimitive.getMaterial().getSpecular(), - rPrimitive.getMaterial().getEmission(), - rPrimitive.getMaterial().getSpecularIntensity()); + // prepare color model parameters, evtl. use blend color + const basegfx::BColor aColor(getModulate() ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor()); + const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular()); + const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission()); + const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity()); - rasterconvertB3DPolyPolygon(aMaterial, aFill); + // solve color model for plane vector and use that color for whole plane + aObjectColor = getSdrLightingAttribute().solveColorModel(aPlaneEyeNormal, aColor, rSpecular, rEmission, nSpecularIntensity); + break; + } + default: // case css::drawing::ShadeMode_DRAFT: + { + // draft, just use object color which is already set. Delete all other infos + aFill.clearNormals(); + aFill.clearBColors(); + break; + } } + + // draw it to ZBuffer + const attribute::MaterialAttribute3D aMaterial( + maBColorModifierStack.getModifiedColor(aObjectColor), + rPrimitive.getMaterial().getSpecular(), + rPrimitive.getMaterial().getEmission(), + rPrimitive.getMaterial().getSpecularIntensity()); + + rasterconvertB3DPolyPolygon(aMaterial, aFill); } void DefaultProcessor3D::impRenderTransformPrimitive3D(const primitive3d::TransformPrimitive3D& rTransformCandidate) diff --git a/drawinglayer/source/processor3d/shadow3dextractor.cxx b/drawinglayer/source/processor3d/shadow3dextractor.cxx index 69f0ecb8156f..45fca6d8dd38 100644 --- a/drawinglayer/source/processor3d/shadow3dextractor.cxx +++ b/drawinglayer/source/processor3d/shadow3dextractor.cxx @@ -226,22 +226,22 @@ namespace drawinglayer::processor3d mfLightPlaneScalar = maLightNormal.scalar(maShadowPlaneNormal); // use only when scalar is > 0.0, so the light is in front of the object - if(basegfx::fTools::more(mfLightPlaneScalar, 0.0)) - { - // prepare buffered WorldToEye and EyeToView - maWorldToEye = getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation(); - maEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection(); - - // calculate range to get front edge around which to rotate the shadow's projection - basegfx::B3DRange aContained3DRange(rContained3DRange); - aContained3DRange.transform(getWorldToEye()); - maPlanePoint.setX(maShadowPlaneNormal.getX() < 0.0 ? aContained3DRange.getMinX() : aContained3DRange.getMaxX()); - maPlanePoint.setY(maShadowPlaneNormal.getY() > 0.0 ? aContained3DRange.getMinY() : aContained3DRange.getMaxY()); - maPlanePoint.setZ(aContained3DRange.getMinZ() - (aContained3DRange.getDepth() / 8.0)); - - // set flag that shadow projection is prepared and allowed - mbShadowProjectionIsValid = true; - } + if(!basegfx::fTools::more(mfLightPlaneScalar, 0.0)) + return; + + // prepare buffered WorldToEye and EyeToView + maWorldToEye = getViewInformation3D().getOrientation() * getViewInformation3D().getObjectTransformation(); + maEyeToView = getViewInformation3D().getDeviceToView() * getViewInformation3D().getProjection(); + + // calculate range to get front edge around which to rotate the shadow's projection + basegfx::B3DRange aContained3DRange(rContained3DRange); + aContained3DRange.transform(getWorldToEye()); + maPlanePoint.setX(maShadowPlaneNormal.getX() < 0.0 ? aContained3DRange.getMinX() : aContained3DRange.getMaxX()); + maPlanePoint.setY(maShadowPlaneNormal.getY() > 0.0 ? aContained3DRange.getMinY() : aContained3DRange.getMaxY()); + maPlanePoint.setZ(aContained3DRange.getMinZ() - (aContained3DRange.getDepth() / 8.0)); + + // set flag that shadow projection is prepared and allowed + mbShadowProjectionIsValid = true; } Shadow3DExtractingProcessor::~Shadow3DExtractingProcessor() diff --git a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx index 3c5945af41b7..49a6a78c7003 100644 --- a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx +++ b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx @@ -271,86 +271,86 @@ public: void ZBufferRasterConverter3D::processLineSpan(const basegfx::RasterConversionLineEntry3D& rA, const basegfx::RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) { - if(!(nSpanCount & 0x0001)) + if(nSpanCount & 0x0001) + return; + + if(!(nLine >= 0 && nLine < static_cast<sal_Int32>(mrBuffer.getHeight()))) + return; + + sal_uInt32 nXA(std::min(mrBuffer.getWidth(), static_cast<sal_uInt32>(std::max(sal_Int32(0), basegfx::fround(rA.getX().getVal()))))); + const sal_uInt32 nXB(std::min(mrBuffer.getWidth(), static_cast<sal_uInt32>(std::max(sal_Int32(0), basegfx::fround(rB.getX().getVal()))))); + + if(nXA >= nXB) + return; + + // prepare the span interpolators + setupLineSpanInterpolators(rA, rB); + + // bring span interpolators to start condition by incrementing with the possible difference of + // clamped and non-clamped XStart. Interpolators are setup relying on double precision + // X-values, so that difference is the correct value to compensate for possible clampings + incrementLineSpanInterpolators(static_cast<double>(nXA) - rA.getX().getVal()); + + // prepare scanline index + sal_uInt32 nScanlineIndex(mrBuffer.getIndexFromXY(nXA, static_cast<sal_uInt32>(nLine))); + basegfx::BColor aNewColor; + + while(nXA < nXB) { - if(nLine >= 0 && nLine < static_cast<sal_Int32>(mrBuffer.getHeight())) + // early-test Z values if we need to do anything at all + const double fNewZ(std::max(0.0, std::min(double(0xffff), maIntZ.getVal()))); + const sal_uInt16 nNewZ(static_cast< sal_uInt16 >(fNewZ)); + sal_uInt16& rOldZ(mrBuffer.getZ(nScanlineIndex)); + + if(nNewZ > rOldZ) { - sal_uInt32 nXA(std::min(mrBuffer.getWidth(), static_cast<sal_uInt32>(std::max(sal_Int32(0), basegfx::fround(rA.getX().getVal()))))); - const sal_uInt32 nXB(std::min(mrBuffer.getWidth(), static_cast<sal_uInt32>(std::max(sal_Int32(0), basegfx::fround(rB.getX().getVal()))))); + // detect color and opacity for this pixel + const sal_uInt16 nOpacity(std::max(sal_Int16(0), static_cast< sal_Int16 >(decideColorAndOpacity(aNewColor) * 255.0))); - if(nXA < nXB) + if(nOpacity > 0) { - // prepare the span interpolators - setupLineSpanInterpolators(rA, rB); - - // bring span interpolators to start condition by incrementing with the possible difference of - // clamped and non-clamped XStart. Interpolators are setup relying on double precision - // X-values, so that difference is the correct value to compensate for possible clampings - incrementLineSpanInterpolators(static_cast<double>(nXA) - rA.getX().getVal()); - - // prepare scanline index - sal_uInt32 nScanlineIndex(mrBuffer.getIndexFromXY(nXA, static_cast<sal_uInt32>(nLine))); - basegfx::BColor aNewColor; + // avoid color overrun + aNewColor.clamp(); - while(nXA < nXB) + if(nOpacity >= 0x00ff) { - // early-test Z values if we need to do anything at all - const double fNewZ(std::max(0.0, std::min(double(0xffff), maIntZ.getVal()))); - const sal_uInt16 nNewZ(static_cast< sal_uInt16 >(fNewZ)); - sal_uInt16& rOldZ(mrBuffer.getZ(nScanlineIndex)); + // full opacity (not transparent), set z and color + rOldZ = nNewZ; + mrBuffer.getBPixel(nScanlineIndex) = basegfx::BPixel(aNewColor, 0xff); + } + else + { + basegfx::BPixel& rDest = mrBuffer.getBPixel(nScanlineIndex); - if(nNewZ > rOldZ) + if(rDest.getOpacity()) { - // detect color and opacity for this pixel - const sal_uInt16 nOpacity(std::max(sal_Int16(0), static_cast< sal_Int16 >(decideColorAndOpacity(aNewColor) * 255.0))); - - if(nOpacity > 0) + // mix new color by using + // color' = color * (1 - opacity) + newcolor * opacity + const sal_uInt16 nTransparence(0x0100 - nOpacity); + rDest.setRed(static_cast<sal_uInt8>(((rDest.getRed() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getRed()) * nOpacity)) >> 8)); + rDest.setGreen(static_cast<sal_uInt8>(((rDest.getGreen() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getGreen()) * nOpacity)) >> 8)); + rDest.setBlue(static_cast<sal_uInt8>(((rDest.getBlue() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getBlue()) * nOpacity)) >> 8)); + + if(0xff != rDest.getOpacity()) { - // avoid color overrun - aNewColor.clamp(); - - if(nOpacity >= 0x00ff) - { - // full opacity (not transparent), set z and color - rOldZ = nNewZ; - mrBuffer.getBPixel(nScanlineIndex) = basegfx::BPixel(aNewColor, 0xff); - } - else - { - basegfx::BPixel& rDest = mrBuffer.getBPixel(nScanlineIndex); - - if(rDest.getOpacity()) - { - // mix new color by using - // color' = color * (1 - opacity) + newcolor * opacity - const sal_uInt16 nTransparence(0x0100 - nOpacity); - rDest.setRed(static_cast<sal_uInt8>(((rDest.getRed() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getRed()) * nOpacity)) >> 8)); - rDest.setGreen(static_cast<sal_uInt8>(((rDest.getGreen() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getGreen()) * nOpacity)) >> 8)); - rDest.setBlue(static_cast<sal_uInt8>(((rDest.getBlue() * nTransparence) + (static_cast<sal_uInt16>(255.0 * aNewColor.getBlue()) * nOpacity)) >> 8)); - - if(0xff != rDest.getOpacity()) - { - // both are transparent, mix new opacity by using - // opacity = newopacity * (1 - oldopacity) + oldopacity - rDest.setOpacity(static_cast<sal_uInt8>((nOpacity * (0x0100 - rDest.getOpacity())) >> 8) + rDest.getOpacity()); - } - } - else - { - // dest is unused, set color - rDest = basegfx::BPixel(aNewColor, static_cast<sal_uInt8>(nOpacity)); - } - } + // both are transparent, mix new opacity by using + // opacity = newopacity * (1 - oldopacity) + oldopacity + rDest.setOpacity(static_cast<sal_uInt8>((nOpacity * (0x0100 - rDest.getOpacity())) >> 8) + rDest.getOpacity()); } } - - // increments - nScanlineIndex++; - nXA++; - incrementLineSpanInterpolators(1.0); + else + { + // dest is unused, set color + rDest = basegfx::BPixel(aNewColor, static_cast<sal_uInt8>(nOpacity)); + } } } } + + // increments + nScanlineIndex++; + nXA++; + incrementLineSpanInterpolators(1.0); } } @@ -605,47 +605,47 @@ namespace drawinglayer::processor3d void ZBufferProcessor3D::finish() { - if(mpRasterPrimitive3Ds) + if(!mpRasterPrimitive3Ds) + return; + + // there are transparent rasterprimitives + const sal_uInt32 nSize(mpRasterPrimitive3Ds->size()); + + if(nSize > 1) + { + // sort them from back to front + std::sort(mpRasterPrimitive3Ds->begin(), mpRasterPrimitive3Ds->end()); + } + + for(sal_uInt32 a(0); a < nSize; a++) { - // there are transparent rasterprimitives - const sal_uInt32 nSize(mpRasterPrimitive3Ds->size()); + // paint each one by setting the remembered data and calling + // the render method + const RasterPrimitive3D& rCandidate = (*mpRasterPrimitive3Ds)[a]; + + mpGeoTexSvx = rCandidate.getGeoTexSvx(); + mpTransparenceGeoTexSvx = rCandidate.getTransparenceGeoTexSvx(); + mbModulate = rCandidate.getModulate(); + mbFilter = rCandidate.getFilter(); + mbSimpleTextureActive = rCandidate.getSimpleTextureActive(); - if(nSize > 1) + if(rCandidate.getIsLine()) { - // sort them from back to front - std::sort(mpRasterPrimitive3Ds->begin(), mpRasterPrimitive3Ds->end()); + rasterconvertB3DPolygon( + rCandidate.getMaterial(), + rCandidate.getPolyPolygon().getB3DPolygon(0)); } - - for(sal_uInt32 a(0); a < nSize; a++) + else { - // paint each one by setting the remembered data and calling - // the render method - const RasterPrimitive3D& rCandidate = (*mpRasterPrimitive3Ds)[a]; - - mpGeoTexSvx = rCandidate.getGeoTexSvx(); - mpTransparenceGeoTexSvx = rCandidate.getTransparenceGeoTexSvx(); - mbModulate = rCandidate.getModulate(); - mbFilter = rCandidate.getFilter(); - mbSimpleTextureActive = rCandidate.getSimpleTextureActive(); - - if(rCandidate.getIsLine()) - { - rasterconvertB3DPolygon( - rCandidate.getMaterial(), - rCandidate.getPolyPolygon().getB3DPolygon(0)); - } - else - { - rasterconvertB3DPolyPolygon( - rCandidate.getMaterial(), - rCandidate.getPolyPolygon()); - } + rasterconvertB3DPolyPolygon( + rCandidate.getMaterial(), + rCandidate.getPolyPolygon()); } - - // delete them to signal the destructor that all is done and - // to allow asserting there - mpRasterPrimitive3Ds.reset(); } + + // delete them to signal the destructor that all is done and + // to allow asserting there + mpRasterPrimitive3Ds.reset(); } } // end of namespace diff --git a/drawinglayer/source/texture/texture.cxx b/drawinglayer/source/texture/texture.cxx index 4787718195d8..a7e9dca54c79 100644 --- a/drawinglayer/source/texture/texture.cxx +++ b/drawinglayer/source/texture/texture.cxx @@ -138,44 +138,44 @@ namespace drawinglayer::texture { rOuterColor = maStart; - if(maGradientInfo.getSteps()) - { - const double fStripeWidth(1.0 / maGradientInfo.getSteps()); - B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; - basegfx::B2DHomMatrix aPattern; + if(!maGradientInfo.getSteps()) + return; - // bring from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1] - aPattern.scale(0.5, 0.5); - aPattern.translate(0.5, 0.5); + const double fStripeWidth(1.0 / maGradientInfo.getSteps()); + B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + basegfx::B2DHomMatrix aPattern; - // scale and translate in X - aPattern.scale(mfUnitWidth, 1.0); - aPattern.translate(mfUnitMinX, 0.0); + // bring from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1] + aPattern.scale(0.5, 0.5); + aPattern.translate(0.5, 0.5); - for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) - { - const double fPos(fStripeWidth * a); - basegfx::B2DHomMatrix aNew(aPattern); + // scale and translate in X + aPattern.scale(mfUnitWidth, 1.0); + aPattern.translate(mfUnitMinX, 0.0); - // scale and translate in Y - double fHeight(1.0 - fPos); + for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) + { + const double fPos(fStripeWidth * a); + basegfx::B2DHomMatrix aNew(aPattern); - if(a + 1 == maGradientInfo.getSteps() && mfUnitMaxY > 1.0) - { - fHeight += mfUnitMaxY - 1.0; - } + // scale and translate in Y + double fHeight(1.0 - fPos); + + if(a + 1 == maGradientInfo.getSteps() && mfUnitMaxY > 1.0) + { + fHeight += mfUnitMaxY - 1.0; + } - aNew.scale(1.0, fHeight); - aNew.translate(0.0, fPos); + aNew.scale(1.0, fHeight); + aNew.translate(0.0, fPos); - // set at target - aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew; + // set at target + aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew; - // interpolate and set color - aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); + // interpolate and set color + aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); - rEntries.push_back(aB2DHomMatrixAndBColor); - } + rEntries.push_back(aB2DHomMatrixAndBColor); } } @@ -224,35 +224,35 @@ namespace drawinglayer::texture { rOuterColor = maEnd; - if(maGradientInfo.getSteps()) - { - const double fStripeWidth(1.0 / maGradientInfo.getSteps()); - B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + if(!maGradientInfo.getSteps()) + return; - for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) - { - const double fPos(fStripeWidth * a); - basegfx::B2DHomMatrix aNew; + const double fStripeWidth(1.0 / maGradientInfo.getSteps()); + B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; - // bring in X from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1] - aNew.scale(0.5, 1.0); - aNew.translate(0.5, 0.0); + for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) + { + const double fPos(fStripeWidth * a); + basegfx::B2DHomMatrix aNew; - // scale/translate in X - aNew.scale(mfUnitWidth, 1.0); - aNew.translate(mfUnitMinX, 0.0); + // bring in X from unit circle [-1, -1, 1, 1] to unit range [0, 0, 1, 1] + aNew.scale(0.5, 1.0); + aNew.translate(0.5, 0.0); - // already centered in Y on X-Axis, just scale in Y - aNew.scale(1.0, 1.0 - fPos); + // scale/translate in X + aNew.scale(mfUnitWidth, 1.0); + aNew.translate(mfUnitMinX, 0.0); - // set at target - aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew; + // already centered in Y on X-Axis, just scale in Y + aNew.scale(1.0, 1.0 - fPos); - // interpolate and set color - aB2DHomMatrixAndBColor.maBColor = interpolate(maEnd, maStart, double(a) / double(maGradientInfo.getSteps() - 1)); + // set at target + aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * aNew; - rEntries.push_back(aB2DHomMatrixAndBColor); - } + // interpolate and set color + aB2DHomMatrixAndBColor.maBColor = interpolate(maEnd, maStart, double(a) / double(maGradientInfo.getSteps() - 1)); + + rEntries.push_back(aB2DHomMatrixAndBColor); } } @@ -291,18 +291,18 @@ namespace drawinglayer::texture { rOuterColor = maStart; - if(maGradientInfo.getSteps()) - { - const double fStepSize(1.0 / maGradientInfo.getSteps()); - B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + if(!maGradientInfo.getSteps()) + return; - for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) - { - const double fSize(1.0 - (fStepSize * a)); - aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize); - aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); - rEntries.push_back(aB2DHomMatrixAndBColor); - } + const double fStepSize(1.0 / maGradientInfo.getSteps()); + B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + + for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) + { + const double fSize(1.0 - (fStepSize * a)); + aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize); + aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); + rEntries.push_back(aB2DHomMatrixAndBColor); } } @@ -343,36 +343,36 @@ namespace drawinglayer::texture { rOuterColor = maStart; - if(maGradientInfo.getSteps()) - { - double fWidth(1.0); - double fHeight(1.0); - double fIncrementX(0.0); - double fIncrementY(0.0); + if(!maGradientInfo.getSteps()) + return; - if(maGradientInfo.getAspectRatio() > 1.0) - { - fIncrementY = fHeight / maGradientInfo.getSteps(); - fIncrementX = fIncrementY / maGradientInfo.getAspectRatio(); - } - else - { - fIncrementX = fWidth / maGradientInfo.getSteps(); - fIncrementY = fIncrementX * maGradientInfo.getAspectRatio(); - } + double fWidth(1.0); + double fHeight(1.0); + double fIncrementX(0.0); + double fIncrementY(0.0); - B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + if(maGradientInfo.getAspectRatio() > 1.0) + { + fIncrementY = fHeight / maGradientInfo.getSteps(); + fIncrementX = fIncrementY / maGradientInfo.getAspectRatio(); + } + else + { + fIncrementX = fWidth / maGradientInfo.getSteps(); + fIncrementY = fIncrementX * maGradientInfo.getAspectRatio(); + } - for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) - { - // next step - fWidth -= fIncrementX; - fHeight -= fIncrementY; + B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; - aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fWidth, fHeight); - aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); - rEntries.push_back(aB2DHomMatrixAndBColor); - } + for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) + { + // next step + fWidth -= fIncrementX; + fHeight -= fIncrementY; + + aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fWidth, fHeight); + aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); + rEntries.push_back(aB2DHomMatrixAndBColor); } } @@ -413,18 +413,18 @@ namespace drawinglayer::texture { rOuterColor = maStart; - if(maGradientInfo.getSteps()) - { - const double fStepSize(1.0 / maGradientInfo.getSteps()); - B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + if(!maGradientInfo.getSteps()) + return; - for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) - { - const double fSize(1.0 - (fStepSize * a)); - aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize); - aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); - rEntries.push_back(aB2DHomMatrixAndBColor); - } + const double fStepSize(1.0 / maGradientInfo.getSteps()); + B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + + for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) + { + const double fSize(1.0 - (fStepSize * a)); + aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fSize, fSize); + aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); + rEntries.push_back(aB2DHomMatrixAndBColor); } } @@ -465,36 +465,36 @@ namespace drawinglayer::texture { rOuterColor = maStart; - if(maGradientInfo.getSteps()) - { - double fWidth(1.0); - double fHeight(1.0); - double fIncrementX(0.0); - double fIncrementY(0.0); + if(!maGradientInfo.getSteps()) + return; - if(maGradientInfo.getAspectRatio() > 1.0) - { - fIncrementY = fHeight / maGradientInfo.getSteps(); - fIncrementX = fIncrementY / maGradientInfo.getAspectRatio(); - } - else - { - fIncrementX = fWidth / maGradientInfo.getSteps(); - fIncrementY = fIncrementX * maGradientInfo.getAspectRatio(); - } + double fWidth(1.0); + double fHeight(1.0); + double fIncrementX(0.0); + double fIncrementY(0.0); - B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; + if(maGradientInfo.getAspectRatio() > 1.0) + { + fIncrementY = fHeight / maGradientInfo.getSteps(); + fIncrementX = fIncrementY / maGradientInfo.getAspectRatio(); + } + else + { + fIncrementX = fWidth / maGradientInfo.getSteps(); + fIncrementY = fIncrementX * maGradientInfo.getAspectRatio(); + } - for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) - { - // next step - fWidth -= fIncrementX; - fHeight -= fIncrementY; + B2DHomMatrixAndBColor aB2DHomMatrixAndBColor; - aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fWidth, fHeight); - aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); - rEntries.push_back(aB2DHomMatrixAndBColor); - } + for(sal_uInt32 a(1); a < maGradientInfo.getSteps(); a++) + { + // next step + fWidth -= fIncrementX; + fHeight -= fIncrementY; + + aB2DHomMatrixAndBColor.maB2DHomMatrix = maGradientInfo.getTextureTransform() * basegfx::utils::createScaleB2DHomMatrix(fWidth, fHeight); + aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, double(a) / double(maGradientInfo.getSteps() - 1)); + rEntries.push_back(aB2DHomMatrixAndBColor); } } @@ -699,67 +699,67 @@ namespace drawinglayer::texture { const double fWidth(maRange.getWidth()); - if(!basegfx::fTools::equalZero(fWidth)) + if(basegfx::fTools::equalZero(fWidth)) + return; + + const double fHeight(maRange.getHeight()); + + if(basegfx::fTools::equalZero(fHeight)) + return; + + double fStartX(maRange.getMinX()); + double fStartY(maRange.getMinY()); + sal_Int32 nPosX(0); + sal_Int32 nPosY(0); + + if(basegfx::fTools::more(fStartX, 0.0)) { - const double fHeight(maRange.getHeight()); + const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartX / fWidth)) + 1); - if(!basegfx::fTools::equalZero(fHeight)) + nPosX -= nDiff; + fStartX -= nDiff * fWidth; + } + + if(basegfx::fTools::less(fStartX + fWidth, 0.0)) + { + const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartX / fWidth))); + + nPosX += nDiff; + fStartX += nDiff * fWidth; + } + + if(basegfx::fTools::more(fStartY, 0.0)) + { + const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartY / fHeight)) + 1); + + nPosY -= nDiff; + fStartY -= nDiff * fHeight; + } + + if(basegfx::fTools::less(fStartY + fHeight, 0.0)) + { + const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartY / fHeight))); + + nPosY += nDiff; + fStartY += nDiff * fHeight; + } + + if(!basegfx::fTools::equalZero(mfOffsetY)) + { + for(double fPosX(fStartX); basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth, nPosX++) + { + for(double fPosY((nPosX % 2) ? fStartY - fHeight + (mfOffsetY * fHeight) : fStartY); + basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight) + aFunc(fPosX, fPosY); + } + } + else + { + for(double fPosY(fStartY); basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight, nPosY++) { - double fStartX(maRange.getMinX()); - double fStartY(maRange.getMinY()); - sal_Int32 nPosX(0); - sal_Int32 nPosY(0); - - if(basegfx::fTools::more(fStartX, 0.0)) - { - const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartX / fWidth)) + 1); - - nPosX -= nDiff; - fStartX -= nDiff * fWidth; - } - - if(basegfx::fTools::less(fStartX + fWidth, 0.0)) - { - const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartX / fWidth))); - - nPosX += nDiff; - fStartX += nDiff * fWidth; - } - - if(basegfx::fTools::more(fStartY, 0.0)) - { - const sal_Int32 nDiff(static_cast<sal_Int32>(floor(fStartY / fHeight)) + 1); - - nPosY -= nDiff; - fStartY -= nDiff * fHeight; - } - - if(basegfx::fTools::less(fStartY + fHeight, 0.0)) - { - const sal_Int32 nDiff(static_cast<sal_Int32>(floor(-fStartY / fHeight))); - - nPosY += nDiff; - fStartY += nDiff * fHeight; - } - - if(!basegfx::fTools::equalZero(mfOffsetY)) - { - for(double fPosX(fStartX); basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth, nPosX++) - { - for(double fPosY((nPosX % 2) ? fStartY - fHeight + (mfOffsetY * fHeight) : fStartY); - basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight) - aFunc(fPosX, fPosY); - } - } - else - { - for(double fPosY(fStartY); basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight, nPosY++) - { - for(double fPosX((nPosY % 2) ? fStartX - fWidth + (mfOffsetX * fWidth) : fStartX); - basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth) - aFunc(fPosX, fPosY); - } - } + for(double fPosX((nPosY % 2) ? fStartX - fWidth + (mfOffsetX * fWidth) : fStartX); + basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth) + aFunc(fPosX, fPosY); } } diff --git a/drawinglayer/source/tools/emfpfont.cxx b/drawinglayer/source/tools/emfpfont.cxx index b1dcaa12359f..a9ee61511234 100644 --- a/drawinglayer/source/tools/emfpfont.cxx +++ b/drawinglayer/source/tools/emfpfont.cxx @@ -56,19 +56,19 @@ namespace emfplushelper SAL_INFO("drawinglayer", "EMF+\tReserved: 0x" << reserved << std::dec); SAL_INFO("drawinglayer", "EMF+\tLength: " << length); - if (length > 0 && length < 0x4000) - { - rtl_uString *pStr = rtl_uString_alloc(length); - sal_Unicode *chars = pStr->buffer; + if (!(length > 0 && length < 0x4000)) + return; - for (sal_uInt32 i = 0; i < length; ++i) - { - s.ReadUtf16(chars[i]); - } + rtl_uString *pStr = rtl_uString_alloc(length); + sal_Unicode *chars = pStr->buffer; - family = OUString(pStr, SAL_NO_ACQUIRE); - SAL_INFO("drawinglayer", "EMF+\tFamily: " << family); + for (sal_uInt32 i = 0; i < length; ++i) + { + s.ReadUtf16(chars[i]); } + + family = OUString(pStr, SAL_NO_ACQUIRE); + SAL_INFO("drawinglayer", "EMF+\tFamily: " << family); } } diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx index bc04cd3e8df3..fb28995ecfc0 100644 --- a/drawinglayer/source/tools/emfphelperdata.cxx +++ b/drawinglayer/source/tools/emfphelperdata.cxx @@ -514,213 +514,213 @@ namespace emfplushelper const EMFPPen* pen = dynamic_cast<EMFPPen*>(maEMFPObjects[penIndex & 0xff].get()); SAL_WARN_IF(!pen, "drawinglayer", "emf+ missing pen"); - if (pen && polygon.count()) + if (!(pen && polygon.count())) + return; + + // we need a line join attribute + basegfx::B2DLineJoin lineJoin = basegfx::B2DLineJoin::Round; + if (pen->penDataFlags & EmfPlusPenDataJoin) // additional line join information { - // we need a line join attribute - basegfx::B2DLineJoin lineJoin = basegfx::B2DLineJoin::Round; - if (pen->penDataFlags & EmfPlusPenDataJoin) // additional line join information - { - lineJoin = static_cast<basegfx::B2DLineJoin>(EMFPPen::lcl_convertLineJoinType(pen->lineJoin)); - } + lineJoin = static_cast<basegfx::B2DLineJoin>(EMFPPen::lcl_convertLineJoinType(pen->lineJoin)); + } - // we need a line cap attribute - css::drawing::LineCap lineCap = css::drawing::LineCap_BUTT; - if (pen->penDataFlags & EmfPlusPenDataStartCap) // additional line cap information - { - lineCap = static_cast<css::drawing::LineCap>(EMFPPen::lcl_convertStrokeCap(pen->startCap)); - SAL_WARN_IF(pen->startCap != pen->endCap, "drawinglayer", "emf+ pen uses different start and end cap"); - } + // we need a line cap attribute + css::drawing::LineCap lineCap = css::drawing::LineCap_BUTT; + if (pen->penDataFlags & EmfPlusPenDataStartCap) // additional line cap information + { + lineCap = static_cast<css::drawing::LineCap>(EMFPPen::lcl_convertStrokeCap(pen->startCap)); + SAL_WARN_IF(pen->startCap != pen->endCap, "drawinglayer", "emf+ pen uses different start and end cap"); + } - const double transformedPenWidth = maMapTransform.get(0, 0) * pen->penWidth; - drawinglayer::attribute::LineAttribute lineAttribute(pen->GetColor().getBColor(), - transformedPenWidth, - lineJoin, - lineCap); + const double transformedPenWidth = maMapTransform.get(0, 0) * pen->penWidth; + drawinglayer::attribute::LineAttribute lineAttribute(pen->GetColor().getBColor(), + transformedPenWidth, + lineJoin, + lineCap); - drawinglayer::attribute::StrokeAttribute aStrokeAttribute; - if (pen->penDataFlags & EmfPlusPenDataLineStyle && pen->dashStyle != EmfPlusLineStyleCustom) // pen has a predefined line style + drawinglayer::attribute::StrokeAttribute aStrokeAttribute; + if (pen->penDataFlags & EmfPlusPenDataLineStyle && pen->dashStyle != EmfPlusLineStyleCustom) // pen has a predefined line style + { + // short writing + const double pw = maMapTransform.get(1, 1) * pen->penWidth; + // taken from the old cppcanvas implementation and multiplied with pen width + const std::vector<double> dash = { 3*pw, 3*pw }; + const std::vector<double> dot = { pw, 3*pw }; + const std::vector<double> dashdot = { 3*pw, 3*pw, pw, 3*pw }; + const std::vector<double> dashdotdot = { 3*pw, 3*pw, pw, 3*pw, pw, 3*pw }; + + switch (pen->dashStyle) { - // short writing - const double pw = maMapTransform.get(1, 1) * pen->penWidth; - // taken from the old cppcanvas implementation and multiplied with pen width - const std::vector<double> dash = { 3*pw, 3*pw }; - const std::vector<double> dot = { pw, 3*pw }; - const std::vector<double> dashdot = { 3*pw, 3*pw, pw, 3*pw }; - const std::vector<double> dashdotdot = { 3*pw, 3*pw, pw, 3*pw, pw, 3*pw }; - - switch (pen->dashStyle) - { - case EmfPlusLineStyleSolid: // do nothing special, use default stroke attribute - break; - case EmfPlusLineStyleDash: - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dash); - break; - case EmfPlusLineStyleDot: - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dot); - break; - case EmfPlusLineStyleDashDot: - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dashdot); - break; - case EmfPlusLineStyleDashDotDot: - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dashdotdot); - break; - } + case EmfPlusLineStyleSolid: // do nothing special, use default stroke attribute + break; + case EmfPlusLineStyleDash: + aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dash); + break; + case EmfPlusLineStyleDot: + aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dot); + break; + case EmfPlusLineStyleDashDot: + aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dashdot); + break; + case EmfPlusLineStyleDashDotDot: + aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(dashdotdot); + break; } - else if (pen->penDataFlags & EmfPlusPenDataDashedLine) // pen has a custom dash line + } + else if (pen->penDataFlags & EmfPlusPenDataDashedLine) // pen has a custom dash line + { + // StrokeAttribute needs a double vector while the pen provides a float vector + std::vector<double> aPattern(pen->dashPattern.size()); + for (size_t i=0; i<aPattern.size(); i++) { - // StrokeAttribute needs a double vector while the pen provides a float vector - std::vector<double> aPattern(pen->dashPattern.size()); - for (size_t i=0; i<aPattern.size(); i++) - { - // convert from float to double and multiply with the adjusted pen width - aPattern[i] = maMapTransform.get(1, 1) * pen->penWidth * pen->dashPattern[i]; - } - aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(aPattern); + // convert from float to double and multiply with the adjusted pen width + aPattern[i] = maMapTransform.get(1, 1) * pen->penWidth * pen->dashPattern[i]; } + aStrokeAttribute = drawinglayer::attribute::StrokeAttribute(aPattern); + } - if (pen->GetColor().GetTransparency() == 0) - { - mrTargetHolders.Current().append( - std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>( - polygon, - lineAttribute, - aStrokeAttribute)); - } - else - { - const drawinglayer::primitive2d::Primitive2DReference aPrimitive( - new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( - polygon, - lineAttribute, - aStrokeAttribute)); + if (pen->GetColor().GetTransparency() == 0) + { + mrTargetHolders.Current().append( + std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>( + polygon, + lineAttribute, + aStrokeAttribute)); + } + else + { + const drawinglayer::primitive2d::Primitive2DReference aPrimitive( + new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( + polygon, + lineAttribute, + aStrokeAttribute)); - mrTargetHolders.Current().append( - std::make_unique<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>( - drawinglayer::primitive2d::Primitive2DContainer { aPrimitive }, - pen->GetColor().GetTransparency() / 255.0)); - } + mrTargetHolders.Current().append( + std::make_unique<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>( + drawinglayer::primitive2d::Primitive2DContainer { aPrimitive }, + pen->GetColor().GetTransparency() / 255.0)); + } - if ((pen->penDataFlags & EmfPlusPenDataCustomStartCap) && (pen->customStartCap->polygon.begin()->count() > 1)) - { - SAL_WARN("drawinglayer", "EMF+\tCustom Start Line Cap"); - ::basegfx::B2DPolyPolygon startCapPolygon(pen->customStartCap->polygon); + if ((pen->penDataFlags & EmfPlusPenDataCustomStartCap) && (pen->customStartCap->polygon.begin()->count() > 1)) + { + SAL_WARN("drawinglayer", "EMF+\tCustom Start Line Cap"); + ::basegfx::B2DPolyPolygon startCapPolygon(pen->customStartCap->polygon); - // get the gradient of the first line in the polypolygon - double x1 = polygon.begin()->getB2DPoint(0).getX(); - double y1 = polygon.begin()->getB2DPoint(0).getY(); - double x2 = polygon.begin()->getB2DPoint(1).getX(); - double y2 = polygon.begin()->getB2DPoint(1).getY(); + // get the gradient of the first line in the polypolygon + double x1 = polygon.begin()->getB2DPoint(0).getX(); + double y1 = polygon.begin()->getB2DPoint(0).getY(); + double x2 = polygon.begin()->getB2DPoint(1).getX(); + double y2 = polygon.begin()->getB2DPoint(1).getY(); - if ((x2 - x1) != 0) - { - double gradient = (y2 - y1) / (x2 - x1); + if ((x2 - x1) != 0) + { + double gradient = (y2 - y1) / (x2 - x1); - // now we get the angle that we need to rotate the arrow by - double angle = (M_PI / 2) - atan(gradient); + // now we get the angle that we need to rotate the arrow by + double angle = (M_PI / 2) - atan(gradient); - // rotate the arrow - startCapPolygon.transform(basegfx::utils::createRotateB2DHomMatrix(angle)); - } + // rotate the arrow + startCapPolygon.transform(basegfx::utils::createRotateB2DHomMatrix(angle)); + } - startCapPolygon.transform(maMapTransform); + startCapPolygon.transform(maMapTransform); - basegfx::B2DHomMatrix tran(pen->penWidth, 0.0, polygon.begin()->getB2DPoint(0).getX(), - 0.0, pen->penWidth, polygon.begin()->getB2DPoint(0).getY()); - startCapPolygon.transform(tran); + basegfx::B2DHomMatrix tran(pen->penWidth, 0.0, polygon.begin()->getB2DPoint(0).getX(), + 0.0, pen->penWidth, polygon.begin()->getB2DPoint(0).getY()); + startCapPolygon.transform(tran); - if (pen->customStartCap->mbIsFilled) - { - mrTargetHolders.Current().append( - std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>( - startCapPolygon, - pen->GetColor().getBColor())); - } - else - { - mrTargetHolders.Current().append( - std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>( - startCapPolygon, - lineAttribute, - aStrokeAttribute)); - } + if (pen->customStartCap->mbIsFilled) + { + mrTargetHolders.Current().append( + std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>( + startCapPolygon, + pen->GetColor().getBColor())); } - - if ((pen->penDataFlags & EmfPlusPenDataCustomEndCap) && (pen->customEndCap->polygon.begin()->count() > 1)) + else { - SAL_WARN("drawinglayer", "EMF+\tCustom End Line Cap"); - - ::basegfx::B2DPolyPolygon endCapPolygon(pen->customEndCap->polygon); + mrTargetHolders.Current().append( + std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>( + startCapPolygon, + lineAttribute, + aStrokeAttribute)); + } + } - // get the gradient of the first line in the polypolygon - double x1 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getX(); - double y1 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getY(); - double x2 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 2).getX(); - double y2 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 2).getY(); + if ((pen->penDataFlags & EmfPlusPenDataCustomEndCap) && (pen->customEndCap->polygon.begin()->count() > 1)) + { + SAL_WARN("drawinglayer", "EMF+\tCustom End Line Cap"); - if ((x2 - x1) != 0) - { - double gradient = (y2 - y1) / (x2 - x1); + ::basegfx::B2DPolyPolygon endCapPolygon(pen->customEndCap->polygon); - // now we get the angle that we need to rotate the arrow by - double angle = (M_PI / 2) - atan(gradient); + // get the gradient of the first line in the polypolygon + double x1 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getX(); + double y1 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getY(); + double x2 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 2).getX(); + double y2 = polygon.begin()->getB2DPoint(polygon.begin()->count() - 2).getY(); - // rotate the arrow - endCapPolygon.transform(basegfx::utils::createRotateB2DHomMatrix(angle)); - } + if ((x2 - x1) != 0) + { + double gradient = (y2 - y1) / (x2 - x1); - endCapPolygon.transform(maMapTransform); - basegfx::B2DHomMatrix tran(pen->penWidth, 0.0, polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getX(), - 0.0, pen->penWidth, polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getY()); - endCapPolygon.transform(tran); + // now we get the angle that we need to rotate the arrow by + double angle = (M_PI / 2) - atan(gradient); - if (pen->customEndCap->mbIsFilled) - { - mrTargetHolders.Current().append( - std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>( - endCapPolygon, - pen->GetColor().getBColor())); - } - else - { - mrTargetHolders.Current().append( - std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>( - endCapPolygon, - lineAttribute, - aStrokeAttribute)); - } + // rotate the arrow + endCapPolygon.transform(basegfx::utils::createRotateB2DHomMatrix(angle)); } - mrPropertyHolders.Current().setLineColor(pen->GetColor().getBColor()); - mrPropertyHolders.Current().setLineColorActive(true); - mrPropertyHolders.Current().setFillColorActive(false); - } - } + endCapPolygon.transform(maMapTransform); + basegfx::B2DHomMatrix tran(pen->penWidth, 0.0, polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getX(), + 0.0, pen->penWidth, polygon.begin()->getB2DPoint(polygon.begin()->count() - 1).getY()); + endCapPolygon.transform(tran); - void EmfPlusHelperData::EMFPPlusFillPolygonSolidColor(const ::basegfx::B2DPolyPolygon& polygon, Color const& color) - { - if (color.GetTransparency() < 255) - { - if (color.GetTransparency() == 0) + if (pen->customEndCap->mbIsFilled) { - // not transparent mrTargetHolders.Current().append( std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>( - polygon, - color.getBColor())); + endCapPolygon, + pen->GetColor().getBColor())); } else { - const drawinglayer::primitive2d::Primitive2DReference aPrimitive( - new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( - polygon, - color.getBColor())); - mrTargetHolders.Current().append( - std::make_unique<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>( - drawinglayer::primitive2d::Primitive2DContainer { aPrimitive }, - color.GetTransparency() / 255.0)); + std::make_unique<drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D>( + endCapPolygon, + lineAttribute, + aStrokeAttribute)); } } + + mrPropertyHolders.Current().setLineColor(pen->GetColor().getBColor()); + mrPropertyHolders.Current().setLineColorActive(true); + mrPropertyHolders.Current().setFillColorActive(false); + } + + void EmfPlusHelperData::EMFPPlusFillPolygonSolidColor(const ::basegfx::B2DPolyPolygon& polygon, Color const& color) + { + if (color.GetTransparency() >= 255) + return; + + if (color.GetTransparency() == 0) + { + // not transparent + mrTargetHolders.Current().append( + std::make_unique<drawinglayer::primitive2d::PolyPolygonColorPrimitive2D>( + polygon, + color.getBColor())); + } + else + { + const drawinglayer::primitive2d::Primitive2DReference aPrimitive( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + polygon, + color.getBColor())); + + mrTargetHolders.Current().append( + std::make_unique<drawinglayer::primitive2d::UnifiedTransparencePrimitive2D>( + drawinglayer::primitive2d::Primitive2DContainer { aPrimitive }, + color.GetTransparency() / 255.0)); + } } void EmfPlusHelperData::EMFPPlusFillPolygon(const ::basegfx::B2DPolyPolygon& polygon, const bool isColor, const sal_uInt32 brushIndexOrColor) diff --git a/drawinglayer/source/tools/wmfemfhelper.cxx b/drawinglayer/source/tools/wmfemfhelper.cxx index bef598449ce9..eb3236a0e0b3 100644 --- a/drawinglayer/source/tools/wmfemfhelper.cxx +++ b/drawinglayer/source/tools/wmfemfhelper.cxx @@ -181,97 +181,97 @@ namespace wmfemfhelper OSL_ENSURE(maPropertyHolders.size(), "PropertyHolders: POP with no property holders (!)"); const sal_uInt32 nSize(maPropertyHolders.size()); - if (nSize) - { - const PropertyHolder* pTip = maPropertyHolders.back(); - const PushFlags nPushFlags(pTip->getPushFlags()); + if (!nSize) + return; + + const PropertyHolder* pTip = maPropertyHolders.back(); + const PushFlags nPushFlags(pTip->getPushFlags()); - if (nPushFlags != PushFlags::NONE) + if (nPushFlags != PushFlags::NONE) + { + if (nSize > 1) { - if (nSize > 1) - { - // copy back content for all non-set flags - PropertyHolder* pLast = maPropertyHolders[nSize - 2]; + // copy back content for all non-set flags + PropertyHolder* pLast = maPropertyHolders[nSize - 2]; - if (PushFlags::ALL != nPushFlags) + if (PushFlags::ALL != nPushFlags) + { + if (!(nPushFlags & PushFlags::LINECOLOR)) { - if (!(nPushFlags & PushFlags::LINECOLOR)) - { - pLast->setLineColor(pTip->getLineColor()); - pLast->setLineColorActive(pTip->getLineColorActive()); - } - if (!(nPushFlags & PushFlags::FILLCOLOR)) - { - pLast->setFillColor(pTip->getFillColor()); - pLast->setFillColorActive(pTip->getFillColorActive()); - } - if (!(nPushFlags & PushFlags::FONT)) - { - pLast->setFont(pTip->getFont()); - } - if (!(nPushFlags & PushFlags::TEXTCOLOR)) - { - pLast->setTextColor(pTip->getTextColor()); - pLast->setTextColorActive(pTip->getTextColorActive()); - } - if (!(nPushFlags & PushFlags::MAPMODE)) - { - pLast->setTransformation(pTip->getTransformation()); - pLast->setMapUnit(pTip->getMapUnit()); - } - if (!(nPushFlags & PushFlags::CLIPREGION)) - { - pLast->setClipPolyPolygon(pTip->getClipPolyPolygon()); - pLast->setClipPolyPolygonActive(pTip->getClipPolyPolygonActive()); - } - if (!(nPushFlags & PushFlags::RASTEROP)) - { - pLast->setRasterOp(pTip->getRasterOp()); - } - if (!(nPushFlags & PushFlags::TEXTFILLCOLOR)) - { - pLast->setTextFillColor(pTip->getTextFillColor()); - pLast->setTextFillColorActive(pTip->getTextFillColorActive()); - } - if (!(nPushFlags & PushFlags::TEXTALIGN)) - { - if (pLast->getFont().GetAlignment() != pTip->getFont().GetAlignment()) - { - vcl::Font aFont(pLast->getFont()); - aFont.SetAlignment(pTip->getFont().GetAlignment()); - pLast->setFont(aFont); - } - } - if (!(nPushFlags & PushFlags::REFPOINT)) - { - // not supported - } - if (!(nPushFlags & PushFlags::TEXTLINECOLOR)) - { - pLast->setTextLineColor(pTip->getTextLineColor()); - pLast->setTextLineColorActive(pTip->getTextLineColorActive()); - } - if (!(nPushFlags & PushFlags::TEXTLAYOUTMODE)) - { - pLast->setLayoutMode(pTip->getLayoutMode()); - } - if (!(nPushFlags & PushFlags::TEXTLANGUAGE)) - { - pLast->setLanguageType(pTip->getLanguageType()); - } - if (!(nPushFlags & PushFlags::OVERLINECOLOR)) + pLast->setLineColor(pTip->getLineColor()); + pLast->setLineColorActive(pTip->getLineColorActive()); + } + if (!(nPushFlags & PushFlags::FILLCOLOR)) + { + pLast->setFillColor(pTip->getFillColor()); + pLast->setFillColorActive(pTip->getFillColorActive()); + } + if (!(nPushFlags & PushFlags::FONT)) + { + pLast->setFont(pTip->getFont()); + } + if (!(nPushFlags & PushFlags::TEXTCOLOR)) + { + pLast->setTextColor(pTip->getTextColor()); + pLast->setTextColorActive(pTip->getTextColorActive()); + } + if (!(nPushFlags & PushFlags::MAPMODE)) + { + pLast->setTransformation(pTip->getTransformation()); + pLast->setMapUnit(pTip->getMapUnit()); + } + if (!(nPushFlags & PushFlags::CLIPREGION)) + { + pLast->setClipPolyPolygon(pTip->getClipPolyPolygon()); + pLast->setClipPolyPolygonActive(pTip->getClipPolyPolygonActive()); + } + if (!(nPushFlags & PushFlags::RASTEROP)) + { + pLast->setRasterOp(pTip->getRasterOp()); + } + if (!(nPushFlags & PushFlags::TEXTFILLCOLOR)) + { + pLast->setTextFillColor(pTip->getTextFillColor()); + pLast->setTextFillColorActive(pTip->getTextFillColorActive()); + } + if (!(nPushFlags & PushFlags::TEXTALIGN)) + { + if (pLast->getFont().GetAlignment() != pTip->getFont().GetAlignment()) { - pLast->setOverlineColor(pTip->getOverlineColor()); - pLast->setOverlineColorActive(pTip->getOverlineColorActive()); + vcl::Font aFont(pLast->getFont()); + aFont.SetAlignment(pTip->getFont().GetAlignment()); + pLast->setFont(aFont); } } + if (!(nPushFlags & PushFlags::REFPOINT)) + { + // not supported + } + if (!(nPushFlags & PushFlags::TEXTLINECOLOR)) + { + pLast->setTextLineColor(pTip->getTextLineColor()); + pLast->setTextLineColorActive(pTip->getTextLineColorActive()); + } + if (!(nPushFlags & PushFlags::TEXTLAYOUTMODE)) + { + pLast->setLayoutMode(pTip->getLayoutMode()); + } + if (!(nPushFlags & PushFlags::TEXTLANGUAGE)) + { + pLast->setLanguageType(pTip->getLanguageType()); + } + if (!(nPushFlags & PushFlags::OVERLINECOLOR)) + { + pLast->setOverlineColor(pTip->getOverlineColor()); + pLast->setOverlineColorActive(pTip->getOverlineColorActive()); + } } } - - // execute the pop - delete maPropertyHolders.back(); - maPropertyHolders.pop_back(); } + + // execute the pop + delete maPropertyHolders.back(); + maPropertyHolders.pop_back(); } PropertyHolder& PropertyHolders::Current() @@ -453,29 +453,29 @@ namespace wmfemfhelper PropertyHolder const & rProperties, const basegfx::BColor& rBColor) { - if(!rPositions.empty()) + if(rPositions.empty()) + return; + + if(rProperties.getTransformation().isIdentity()) + { + rTarget.append( + std::make_unique<drawinglayer::primitive2d::PointArrayPrimitive2D>( + rPositions, + rBColor)); + } + else { - if(rProperties.getTransformation().isIdentity()) + std::vector< basegfx::B2DPoint > aPositions(rPositions); + + for(basegfx::B2DPoint & aPosition : aPositions) { - rTarget.append( - std::make_unique<drawinglayer::primitive2d::PointArrayPrimitive2D>( - rPositions, - rBColor)); + aPosition = rProperties.getTransformation() * aPosition; } - else - { - std::vector< basegfx::B2DPoint > aPositions(rPositions); - - for(basegfx::B2DPoint & aPosition : aPositions) - { - aPosition = rProperties.getTransformation() * aPosition; - } - rTarget.append( - std::make_unique<drawinglayer::primitive2d::PointArrayPrimitive2D>( - aPositions, - rBColor)); - } + rTarget.append( + std::make_unique<drawinglayer::primitive2d::PointArrayPrimitive2D>( + aPositions, + rBColor)); } } @@ -520,64 +520,64 @@ namespace wmfemfhelper TargetHolder& rTarget, PropertyHolder const & rProperties) { - if(rLinePolygon.count()) - { - const bool bDashDotUsed(LineStyle::Dash == rLineInfo.GetStyle()); - const bool bWidthUsed(rLineInfo.GetWidth() > 1); + if(!rLinePolygon.count()) + return; - if(bDashDotUsed || bWidthUsed) - { - basegfx::B2DPolygon aLinePolygon(rLinePolygon); - aLinePolygon.transform(rProperties.getTransformation()); - const drawinglayer::attribute::LineAttribute aLineAttribute( - rProperties.getLineColor(), - bWidthUsed ? rLineInfo.GetWidth() : 0.0, - rLineInfo.GetLineJoin(), - rLineInfo.GetLineCap()); - - if(bDashDotUsed) - { - std::vector< double > fDotDashArray; - const double fDashLen(rLineInfo.GetDashLen()); - const double fDotLen(rLineInfo.GetDotLen()); - const double fDistance(rLineInfo.GetDistance()); + const bool bDashDotUsed(LineStyle::Dash == rLineInfo.GetStyle()); + const bool bWidthUsed(rLineInfo.GetWidth() > 1); - for(sal_uInt16 a(0); a < rLineInfo.GetDashCount(); a++) - { - fDotDashArray.push_back(fDashLen); - fDotDashArray.push_back(fDistance); - } - - for(sal_uInt16 b(0); b < rLineInfo.GetDotCount(); b++) - { - fDotDashArray.push_back(fDotLen); - fDotDashArray.push_back(fDistance); - } + if(bDashDotUsed || bWidthUsed) + { + basegfx::B2DPolygon aLinePolygon(rLinePolygon); + aLinePolygon.transform(rProperties.getTransformation()); + const drawinglayer::attribute::LineAttribute aLineAttribute( + rProperties.getLineColor(), + bWidthUsed ? rLineInfo.GetWidth() : 0.0, + rLineInfo.GetLineJoin(), + rLineInfo.GetLineCap()); - const double fAccumulated(std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0)); - const drawinglayer::attribute::StrokeAttribute aStrokeAttribute( - fDotDashArray, - fAccumulated); + if(bDashDotUsed) + { + std::vector< double > fDotDashArray; + const double fDashLen(rLineInfo.GetDashLen()); + const double fDotLen(rLineInfo.GetDotLen()); + const double fDistance(rLineInfo.GetDistance()); - rTarget.append( - std::make_unique<drawinglayer::primitive2d::PolygonStrokePrimitive2D>( - aLinePolygon, - aLineAttribute, - aStrokeAttribute)); + for(sal_uInt16 a(0); a < rLineInfo.GetDashCount(); a++) + { + fDotDashArray.push_back(fDashLen); + fDotDashArray.push_back(fDistance); } - else + + for(sal_uInt16 b(0); b < rLineInfo.GetDotCount(); b++) { - rTarget.append( - std::make_unique<drawinglayer::primitive2d::PolygonStrokePrimitive2D>( - aLinePolygon, - aLineAttribute)); + fDotDashArray.push_back(fDotLen); + fDotDashArray.push_back(fDistance); } + + const double fAccumulated(std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0)); + const drawinglayer::attribute::StrokeAttribute aStrokeAttribute( + fDotDashArray, + fAccumulated); + + rTarget.append( + std::make_unique<drawinglayer::primitive2d::PolygonStrokePrimitive2D>( + aLinePolygon, + aLineAttribute, + aStrokeAttribute)); } else { - createHairlinePrimitive(rLinePolygon, rTarget, rProperties); + rTarget.append( + std::make_unique<drawinglayer::primitive2d::PolygonStrokePrimitive2D>( + aLinePolygon, + aLineAttribute)); } } + else + { + createHairlinePrimitive(rLinePolygon, rTarget, rProperties); + } } /** helper to create needed line and fill primitives based on current context */ @@ -649,22 +649,22 @@ namespace wmfemfhelper TargetHolder& rTarget, PropertyHolder const & rProperties) { - if(!rBitmapEx.IsEmpty()) - { - basegfx::B2DHomMatrix aObjectTransform; + if(rBitmapEx.IsEmpty()) + return; - aObjectTransform.set(0, 0, rSize.Width()); - aObjectTransform.set(1, 1, rSize.Height()); - aObjectTransform.set(0, 2, rPoint.X()); - aObjectTransform.set(1, 2, rPoint.Y()); + basegfx::B2DHomMatrix aObjectTransform; - aObjectTransform = rProperties.getTransformation() * aObjectTransform; + aObjectTransform.set(0, 0, rSize.Width()); + aObjectTransform.set(1, 1, rSize.Height()); + aObjectTransform.set(0, 2, rPoint.X()); + aObjectTransform.set(1, 2, rPoint.Y()); - rTarget.append( - std::make_unique<drawinglayer::primitive2d::BitmapPrimitive2D>( - VCLUnoHelper::CreateVCLXBitmap(rBitmapEx), - aObjectTransform)); - } + aObjectTransform = rProperties.getTransformation() * aObjectTransform; + + rTarget.append( + std::make_unique<drawinglayer::primitive2d::BitmapPrimitive2D>( + VCLUnoHelper::CreateVCLXBitmap(rBitmapEx), + aObjectTransform)); } /** helper to create a regular BotmapEx from a MaskAction (definitions @@ -1288,23 +1288,23 @@ namespace wmfemfhelper } } - if(pResult) + if(!pResult) + return; + + // add created text primitive to target + if(rProperty.getTransformation().isIdentity()) { - // add created text primitive to target - if(rProperty.getTransformation().isIdentity()) - { - rTarget.append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D>(pResult)); - } - else - { - // when a transformation is set, embed to it - const drawinglayer::primitive2d::Primitive2DReference aReference(pResult); + rTarget.append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D>(pResult)); + } + else + { + // when a transformation is set, embed to it + const drawinglayer::primitive2d::Primitive2DReference aReference(pResult); - rTarget.append( - std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>( - rProperty.getTransformation(), - drawinglayer::primitive2d::Primitive2DContainer { aReference })); - } + rTarget.append( + std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>( + rProperty.getTransformation(), + drawinglayer::primitive2d::Primitive2DContainer { aReference })); } } @@ -1316,126 +1316,126 @@ namespace wmfemfhelper { const double fLineWidth(fabs(static_cast<double>(rAction.GetWidth()))); - if(fLineWidth > 0.0) - { - const drawinglayer::primitive2d::TextLine aOverlineMode(drawinglayer::primitive2d::mapFontLineStyleToTextLine(rAction.GetOverline())); - const drawinglayer::primitive2d::TextLine aUnderlineMode(drawinglayer::primitive2d::mapFontLineStyleToTextLine(rAction.GetUnderline())); - const drawinglayer::primitive2d::TextStrikeout aTextStrikeout(drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rAction.GetStrikeout())); + if(fLineWidth <= 0.0) + return; - const bool bOverlineUsed(drawinglayer::primitive2d::TEXT_LINE_NONE != aOverlineMode); - const bool bUnderlineUsed(drawinglayer::primitive2d::TEXT_LINE_NONE != aUnderlineMode); - const bool bStrikeoutUsed(drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE != aTextStrikeout); + const drawinglayer::primitive2d::TextLine aOverlineMode(drawinglayer::primitive2d::mapFontLineStyleToTextLine(rAction.GetOverline())); + const drawinglayer::primitive2d::TextLine aUnderlineMode(drawinglayer::primitive2d::mapFontLineStyleToTextLine(rAction.GetUnderline())); + const drawinglayer::primitive2d::TextStrikeout aTextStrikeout(drawinglayer::primitive2d::mapFontStrikeoutToTextStrikeout(rAction.GetStrikeout())); - if(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed) - { - std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aTargetVector; - basegfx::B2DVector aAlignmentOffset(0.0, 0.0); - drawinglayer::attribute::FontAttribute aFontAttribute; - basegfx::B2DHomMatrix aTextTransform; + const bool bOverlineUsed(drawinglayer::primitive2d::TEXT_LINE_NONE != aOverlineMode); + const bool bUnderlineUsed(drawinglayer::primitive2d::TEXT_LINE_NONE != aUnderlineMode); + const bool bStrikeoutUsed(drawinglayer::primitive2d::TEXT_STRIKEOUT_NONE != aTextStrikeout); - // fill parameters derived from current font - createFontAttributeTransformAndAlignment( - aFontAttribute, - aTextTransform, - aAlignmentOffset, - rProperty); + if(!(bUnderlineUsed || bStrikeoutUsed || bOverlineUsed)) + return; - // add TextStartPosition - aTextTransform.translate(rAction.GetStartPoint().X(), rAction.GetStartPoint().Y()); + std::vector< drawinglayer::primitive2d::BasePrimitive2D* > aTargetVector; + basegfx::B2DVector aAlignmentOffset(0.0, 0.0); + drawinglayer::attribute::FontAttribute aFontAttribute; + basegfx::B2DHomMatrix aTextTransform; - // prepare TextLayouter (used in most cases) - drawinglayer::primitive2d::TextLayouterDevice aTextLayouter; - aTextLayouter.setFont(rProperty.getFont()); + // fill parameters derived from current font + createFontAttributeTransformAndAlignment( + aFontAttribute, + aTextTransform, + aAlignmentOffset, + rProperty); - if(bOverlineUsed) - { - // create primitive geometry for overline - aTargetVector.push_back( - new drawinglayer::primitive2d::TextLinePrimitive2D( - aTextTransform, - fLineWidth, - aTextLayouter.getOverlineOffset(), - aTextLayouter.getOverlineHeight(), - aOverlineMode, - rProperty.getOverlineColor())); - } + // add TextStartPosition + aTextTransform.translate(rAction.GetStartPoint().X(), rAction.GetStartPoint().Y()); - if(bUnderlineUsed) - { - // create primitive geometry for underline - aTargetVector.push_back( - new drawinglayer::primitive2d::TextLinePrimitive2D( - aTextTransform, - fLineWidth, - aTextLayouter.getUnderlineOffset(), - aTextLayouter.getUnderlineHeight(), - aUnderlineMode, - rProperty.getTextLineColor())); - } + // prepare TextLayouter (used in most cases) + drawinglayer::primitive2d::TextLayouterDevice aTextLayouter; + aTextLayouter.setFont(rProperty.getFont()); - if(bStrikeoutUsed) - { - // create primitive geometry for strikeout - if(drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout - || drawinglayer::primitive2d::TEXT_STRIKEOUT_X == aTextStrikeout) - { - // strikeout with character - const sal_Unicode aStrikeoutChar( - drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout ? '/' : 'X'); - const css::lang::Locale aLocale(LanguageTag( - rProperty.getLanguageType()).getLocale()); - - aTargetVector.push_back( - new drawinglayer::primitive2d::TextCharacterStrikeoutPrimitive2D( - aTextTransform, - fLineWidth, - rProperty.getTextColor(), - aStrikeoutChar, - aFontAttribute, - aLocale)); - } - else - { - // strikeout with geometry - aTargetVector.push_back( - new drawinglayer::primitive2d::TextGeometryStrikeoutPrimitive2D( - aTextTransform, - fLineWidth, - rProperty.getTextColor(), - aTextLayouter.getUnderlineHeight(), - aTextLayouter.getStrikeoutOffset(), - aTextStrikeout)); - } - } + if(bOverlineUsed) + { + // create primitive geometry for overline + aTargetVector.push_back( + new drawinglayer::primitive2d::TextLinePrimitive2D( + aTextTransform, + fLineWidth, + aTextLayouter.getOverlineOffset(), + aTextLayouter.getOverlineHeight(), + aOverlineMode, + rProperty.getOverlineColor())); + } - if(!aTargetVector.empty()) - { - // add created text primitive to target - if(rProperty.getTransformation().isIdentity()) - { - for(drawinglayer::primitive2d::BasePrimitive2D* a : aTargetVector) - { - rTarget.append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D>(a)); - } - } - else - { - // when a transformation is set, embed to it - drawinglayer::primitive2d::Primitive2DContainer xTargets(aTargetVector.size()); + if(bUnderlineUsed) + { + // create primitive geometry for underline + aTargetVector.push_back( + new drawinglayer::primitive2d::TextLinePrimitive2D( + aTextTransform, + fLineWidth, + aTextLayouter.getUnderlineOffset(), + aTextLayouter.getUnderlineHeight(), + aUnderlineMode, + rProperty.getTextLineColor())); + } - for(size_t a(0); a < aTargetVector.size(); a++) - { - xTargets[a] = drawinglayer::primitive2d::Primitive2DReference(aTargetVector[a]); - } + if(bStrikeoutUsed) + { + // create primitive geometry for strikeout + if(drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout + || drawinglayer::primitive2d::TEXT_STRIKEOUT_X == aTextStrikeout) + { + // strikeout with character + const sal_Unicode aStrikeoutChar( + drawinglayer::primitive2d::TEXT_STRIKEOUT_SLASH == aTextStrikeout ? '/' : 'X'); + const css::lang::Locale aLocale(LanguageTag( + rProperty.getLanguageType()).getLocale()); + + aTargetVector.push_back( + new drawinglayer::primitive2d::TextCharacterStrikeoutPrimitive2D( + aTextTransform, + fLineWidth, + rProperty.getTextColor(), + aStrikeoutChar, + aFontAttribute, + aLocale)); + } + else + { + // strikeout with geometry + aTargetVector.push_back( + new drawinglayer::primitive2d::TextGeometryStrikeoutPrimitive2D( + aTextTransform, + fLineWidth, + rProperty.getTextColor(), + aTextLayouter.getUnderlineHeight(), + aTextLayouter.getStrikeoutOffset(), + aTextStrikeout)); + } + } - rTarget.append( - std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>( - rProperty.getTransformation(), - xTargets)); - } - } + if(aTargetVector.empty()) + return; + + // add created text primitive to target + if(rProperty.getTransformation().isIdentity()) + { + for(drawinglayer::primitive2d::BasePrimitive2D* a : aTargetVector) + { + rTarget.append(std::unique_ptr<drawinglayer::primitive2d::BasePrimitive2D>(a)); } } + else + { + // when a transformation is set, embed to it + drawinglayer::primitive2d::Primitive2DContainer xTargets(aTargetVector.size()); + + for(size_t a(0); a < aTargetVector.size(); a++) + { + xTargets[a] = drawinglayer::primitive2d::Primitive2DReference(aTargetVector[a]); + } + + rTarget.append( + std::make_unique<drawinglayer::primitive2d::TransformPrimitive2D>( + rProperty.getTransformation(), + xTargets)); + } } /** This is the main interpreter method. It is designed to handle the given Metafile |