summaryrefslogtreecommitdiff
path: root/drawinglayer/source/processor2d/vclprocessor2d.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'drawinglayer/source/processor2d/vclprocessor2d.cxx')
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx871
1 files changed, 493 insertions, 378 deletions
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 5a0a85f911ef..4d089830a9db 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -22,31 +22,28 @@
#include "getdigitlanguage.hxx"
#include "vclhelperbufferdevice.hxx"
#include <cmath>
-#include <comphelper/string.hxx>
+#include <comphelper/lok.hxx>
#include <tools/debug.hxx>
+#include <tools/fract.hxx>
+#include <utility>
+#include <vcl/glyphitemcache.hxx>
#include <vcl/graph.hxx>
+#include <vcl/kernarray.hxx>
#include <vcl/outdev.hxx>
-#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
-#include <toolkit/helper/vclunohelper.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygonclipper.hxx>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHairlinePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonMarkerPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonStrokePrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonHatchPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
+#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
#include <drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx>
-#include <drawinglayer/primitive2d/PolyPolygonSelectionPrimitive2D.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
@@ -56,8 +53,6 @@
#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
#include <drawinglayer/primitive2d/textenumsprimitive2d.hxx>
#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
-// for support of Title/Description in all apps when embedding pictures
-#include <drawinglayer/primitive2d/objectinfoprimitive2d.hxx>
// control support
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
@@ -94,6 +89,29 @@ sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA,
}
}
+namespace
+{
+/** helper to convert a MapMode to a transformation */
+basegfx::B2DHomMatrix getTransformFromMapMode(const MapMode& rMapMode)
+{
+ basegfx::B2DHomMatrix aMapping;
+ const Fraction aNoScale(1, 1);
+ const Point& rOrigin(rMapMode.GetOrigin());
+
+ if (0 != rOrigin.X() || 0 != rOrigin.Y())
+ {
+ aMapping.translate(rOrigin.X(), rOrigin.Y());
+ }
+
+ if (rMapMode.GetScaleX() != aNoScale || rMapMode.GetScaleY() != aNoScale)
+ {
+ aMapping.scale(double(rMapMode.GetScaleX()), double(rMapMode.GetScaleY()));
+ }
+
+ return aMapping;
+}
+}
+
namespace drawinglayer::processor2d
{
// rendering support
@@ -111,45 +129,64 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
basegfx::B2DVector aFontScaling, aTranslate;
double fRotate, fShearX;
aLocalTransform.decompose(aFontScaling, aTranslate, fRotate, fShearX);
+
bool bPrimitiveAccepted(false);
// tdf#95581: Assume tiny shears are rounding artefacts or whatever and can be ignored,
// especially if the effect is less than a pixel.
if (std::abs(aFontScaling.getY() * fShearX) < 1)
{
- if (basegfx::fTools::less(aFontScaling.getX(), 0.0)
- && basegfx::fTools::less(aFontScaling.getY(), 0.0))
+ if (aFontScaling.getX() < 0.0 && aFontScaling.getY() < 0.0)
{
// handle special case: If scale is negative in (x,y) (3rd quadrant), it can
// be expressed as rotation by PI. Use this since the Font rendering will not
// apply the negative scales in any form
aFontScaling = basegfx::absolute(aFontScaling);
- fRotate += F_PI;
+ fRotate += M_PI;
}
- if (basegfx::fTools::more(aFontScaling.getX(), 0.0)
- && basegfx::fTools::more(aFontScaling.getY(), 0.0))
+ if (aFontScaling.getX() > 0.0 && aFontScaling.getY() > 0.0)
{
- // Get the VCL font (use FontHeight as FontWidth)
- vcl::Font aFont(primitive2d::getVclFontFromFontAttribute(
- rTextCandidate.getFontAttribute(), aFontScaling.getX(), aFontScaling.getY(),
- fRotate, rTextCandidate.getLocale()));
+ double fIgnoreRotate, fIgnoreShearX;
- // set FillColor Attribute
- const Color aFillColor(rTextCandidate.getTextFillColor());
- if (aFillColor != COL_TRANSPARENT)
+ basegfx::B2DVector aFontSize, aTextTranslate;
+ rTextCandidate.getTextTransform().decompose(aFontSize, aTextTranslate, fIgnoreRotate,
+ fIgnoreShearX);
+
+ // tdf#153092 Ideally we don't have to scale the font and dxarray, but we might have
+ // to nevertheless if dealing with non integer sizes
+ const bool bScaleFont(aFontSize.getY() != std::round(aFontSize.getY())
+ || comphelper::LibreOfficeKit::isActive());
+ vcl::Font aFont;
+
+ // Get the VCL font
+ if (!bScaleFont)
+ {
+ aFont = primitive2d::getVclFontFromFontAttribute(
+ rTextCandidate.getFontAttribute(), aFontSize.getX(), aFontSize.getY(), fRotate,
+ rTextCandidate.getLocale());
+ }
+ else
{
- aFont.SetFillColor(aFillColor);
- aFont.SetTransparent(false);
+ aFont = primitive2d::getVclFontFromFontAttribute(
+ rTextCandidate.getFontAttribute(), aFontScaling.getX(), aFontScaling.getY(),
+ fRotate, rTextCandidate.getLocale());
}
// Don't draw fonts without height
- if (aFont.GetFontHeight() <= 0)
+ Size aResultFontSize = aFont.GetFontSize();
+ if (aResultFontSize.Height() <= 0)
return;
+ // set FillColor Attribute
+ const Color aFillColor(rTextCandidate.getTextFillColor());
+ aFont.SetTransparent(aFillColor.IsTransparent());
+ aFont.SetFillColor(aFillColor);
+
// handle additional font attributes
- const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP
- = dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>(
+ const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP = nullptr;
+ if (rTextCandidate.getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D)
+ pTCPP = static_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>(
&rTextCandidate);
if (pTCPP != nullptr)
@@ -251,83 +288,187 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
aFont.SetShadow(true);
}
- // create transformed integer DXArray in view coordinate system
- std::vector<long> aTransformedDXArray;
+ // create integer DXArray
+ KernArray aDXArray;
if (!rTextCandidate.getDXArray().empty())
{
- aTransformedDXArray.reserve(rTextCandidate.getDXArray().size());
- const basegfx::B2DVector aPixelVector(maCurrentTransformation
- * basegfx::B2DVector(1.0, 0.0));
- const double fPixelVectorFactor(aPixelVector.getLength());
-
- for (auto const& elem : rTextCandidate.getDXArray())
+ double fPixelVectorFactor(1.0);
+ if (bScaleFont)
{
- aTransformedDXArray.push_back(basegfx::fround(elem * fPixelVectorFactor));
+ const basegfx::B2DVector aPixelVector(maCurrentTransformation
+ * basegfx::B2DVector(1.0, 0.0));
+ fPixelVectorFactor = aPixelVector.getLength();
}
+
+ aDXArray.reserve(rTextCandidate.getDXArray().size());
+ for (auto const& elem : rTextCandidate.getDXArray())
+ aDXArray.push_back(elem * fPixelVectorFactor);
}
// set parameters and paint text snippet
const basegfx::BColor aRGBFontColor(
maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
- const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0));
- const Point aStartPoint(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY()));
- const ComplexTextLayoutFlags nOldLayoutMode(mpOutputDevice->GetLayoutMode());
+
+ // Store previous complex text layout state, to be restored after drawing
+ const vcl::text::ComplexTextLayoutFlags nOldLayoutMode(mpOutputDevice->GetLayoutMode());
if (rTextCandidate.getFontAttribute().getRTL())
{
- ComplexTextLayoutFlags nRTLLayoutMode(nOldLayoutMode
- & ~ComplexTextLayoutFlags::BiDiStrong);
- nRTLLayoutMode
- |= ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::TextOriginLeft;
+ vcl::text::ComplexTextLayoutFlags nRTLLayoutMode(
+ nOldLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiStrong);
+ nRTLLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl
+ | vcl::text::ComplexTextLayoutFlags::TextOriginLeft;
mpOutputDevice->SetLayoutMode(nRTLLayoutMode);
}
+ else
+ {
+ // tdf#101686: This is LTR text, but the output device may have RTL state.
+ vcl::text::ComplexTextLayoutFlags nLTRLayoutMode(nOldLayoutMode);
+ nLTRLayoutMode = nLTRLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiRtl;
+ nLTRLayoutMode = nLTRLayoutMode & ~vcl::text::ComplexTextLayoutFlags::BiDiStrong;
+ mpOutputDevice->SetLayoutMode(nLTRLayoutMode);
+ }
- mpOutputDevice->SetFont(aFont);
- mpOutputDevice->SetTextColor(Color(aRGBFontColor));
+ Point aStartPoint;
+ bool bChangeMapMode(false);
+ if (!bScaleFont)
+ {
+ basegfx::B2DHomMatrix aCombinedTransform(
+ getTransformFromMapMode(mpOutputDevice->GetMapMode())
+ * maCurrentTransformation);
+
+ basegfx::B2DVector aCurrentScaling, aCurrentTranslate;
+ double fCurrentRotate;
+ aCombinedTransform.decompose(aCurrentScaling, aCurrentTranslate, fCurrentRotate,
+ fIgnoreShearX);
+
+ const Point aOrigin(
+ basegfx::fround<tools::Long>(aCurrentTranslate.getX() / aCurrentScaling.getX()),
+ basegfx::fround<tools::Long>(aCurrentTranslate.getY()
+ / aCurrentScaling.getY()));
+
+ Fraction aScaleX(aCurrentScaling.getX());
+ if (!aScaleX.IsValid())
+ {
+ SAL_WARN("drawinglayer", "invalid X Scale");
+ return;
+ }
- OUString aText(rTextCandidate.getText());
- sal_Int32 nPos = rTextCandidate.getTextPosition();
- sal_Int32 nLen = rTextCandidate.getTextLength();
+ Fraction aScaleY(aCurrentScaling.getY());
+ if (!aScaleY.IsValid())
+ {
+ SAL_WARN("drawinglayer", "invalid Y Scale");
+ return;
+ }
+
+ MapMode aMapMode(mpOutputDevice->GetMapMode().GetMapUnit(), aOrigin, aScaleX,
+ aScaleY);
- long* pDXArray = !aTransformedDXArray.empty() ? aTransformedDXArray.data() : nullptr;
+ if (fCurrentRotate)
+ aTextTranslate *= basegfx::utils::createRotateB2DHomMatrix(fCurrentRotate);
+ aStartPoint = Point(basegfx::fround<tools::Long>(aTextTranslate.getX()),
+ basegfx::fround<tools::Long>(aTextTranslate.getY()));
- if (rTextCandidate.isFilled())
+ bChangeMapMode = aMapMode != mpOutputDevice->GetMapMode();
+ if (bChangeMapMode)
+ {
+ mpOutputDevice->Push(vcl::PushFlags::MAPMODE);
+ mpOutputDevice->SetRelativeMapMode(aMapMode);
+ }
+ }
+ else
{
- basegfx::B2DVector aOldFontScaling, aOldTranslate;
- double fOldRotate, fOldShearX;
- rTextCandidate.getTextTransform().decompose(aOldFontScaling, aOldTranslate,
- fOldRotate, fOldShearX);
-
- long nWidthToFill = static_cast<long>(
- rTextCandidate.getWidthToFill() * aFontScaling.getX() / aOldFontScaling.getX());
-
- long nWidth
- = mpOutputDevice->GetTextArray(rTextCandidate.getText(), pDXArray, 0, 1);
- long nChars = 2;
- if (nWidth)
- nChars = nWidthToFill / nWidth;
-
- OUStringBuffer aFilled;
- comphelper::string::padToLength(aFilled, nChars, aText[0]);
- aText = aFilled.makeStringAndClear();
- nPos = 0;
- nLen = nChars;
+ const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0));
+ double aPointX = aPoint.getX(), aPointY = aPoint.getY();
+
+ if (!comphelper::LibreOfficeKit::isActive())
+ {
+ // aFont has an integer size; we must scale a bit for precision
+ double nFontScalingFixY = aFontScaling.getY() / aResultFontSize.Height();
+ double nFontScalingFixX
+ = aFontScaling.getX()
+ / (aResultFontSize.Width() ? aResultFontSize.Width()
+ : aResultFontSize.Height());
+
+#ifdef _WIN32
+ if (aResultFontSize.Width()
+ && aResultFontSize.Width() != aResultFontSize.Height())
+ {
+ // See getVclFontFromFontAttribute in drawinglayer/source/primitive2d/textlayoutdevice.cxx
+ vcl::Font aUnscaledTest(aFont);
+ aUnscaledTest.SetFontSize({ 0, aResultFontSize.Height() });
+ const FontMetric aUnscaledFontMetric(
+ Application::GetDefaultDevice()->GetFontMetric(aUnscaledTest));
+ if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
+ {
+ double nExistingXScale = static_cast<double>(aResultFontSize.Width())
+ / aUnscaledFontMetric.GetAverageFontWidth();
+ nFontScalingFixX
+ = aFontScaling.getX() / aFontScaling.getY() / nExistingXScale;
+ }
+ }
+#endif
+
+ if (!rtl_math_approxEqual(nFontScalingFixY, 1.0)
+ || !rtl_math_approxEqual(nFontScalingFixX, 1.0))
+ {
+ MapMode aMapMode = mpOutputDevice->GetMapMode();
+ aMapMode.SetScaleX(aMapMode.GetScaleX() * nFontScalingFixX);
+ aMapMode.SetScaleY(aMapMode.GetScaleY() * nFontScalingFixY);
+
+ const bool bValidScaling
+ = aMapMode.GetScaleX().IsValid() && aMapMode.GetScaleY().IsValid();
+ if (!bValidScaling)
+ SAL_WARN("drawinglayer", "skipping invalid scaling");
+ else
+ {
+ assert(nFontScalingFixX != 0 && nFontScalingFixY != 0
+ && "or bValidScaling would be false");
+
+ Point origin = aMapMode.GetOrigin();
+
+ mpOutputDevice->Push(vcl::PushFlags::MAPMODE);
+ mpOutputDevice->SetRelativeMapMode(aMapMode);
+ bChangeMapMode = true;
+
+ aPointX = (aPointX + origin.X()) / nFontScalingFixX - origin.X();
+ aPointY = (aPointY + origin.Y()) / nFontScalingFixY - origin.Y();
+ }
+ }
+ }
+
+ aStartPoint = Point(basegfx::fround<tools::Long>(aPointX),
+ basegfx::fround<tools::Long>(aPointY));
}
- if (!aTransformedDXArray.empty())
+ // tdf#152990 set the font after the MapMode is (potentially) set so canvas uses the desired
+ // font size
+ mpOutputDevice->SetFont(aFont);
+ mpOutputDevice->SetTextColor(Color(aRGBFontColor));
+
+ if (!aDXArray.empty())
{
- mpOutputDevice->DrawTextArray(aStartPoint, aText, pDXArray, nPos, nLen);
+ const SalLayoutGlyphs* pGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
+ mpOutputDevice, rTextCandidate.getText(), rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength());
+ mpOutputDevice->DrawTextArray(
+ aStartPoint, rTextCandidate.getText(), aDXArray,
+ rTextCandidate.getKashidaArray(), rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength(), SalLayoutFlags::NONE, pGlyphs);
}
else
{
- mpOutputDevice->DrawText(aStartPoint, aText, nPos, nLen);
+ mpOutputDevice->DrawText(aStartPoint, rTextCandidate.getText(),
+ rTextCandidate.getTextPosition(),
+ rTextCandidate.getTextLength());
}
- if (rTextCandidate.getFontAttribute().getRTL())
- {
- mpOutputDevice->SetLayoutMode(nOldLayoutMode);
- }
+ // Restore previous layout mode
+ mpOutputDevice->SetLayoutMode(nOldLayoutMode);
+
+ if (bChangeMapMode)
+ mpOutputDevice->Pop();
bPrimitiveAccepted = true;
}
@@ -352,8 +493,7 @@ void VclProcessor2D::RenderPolygonHairlinePrimitive2D(
basegfx::B2DPolygon aLocalPolygon(rPolygonCandidate.getB2DPolygon());
aLocalPolygon.transform(maCurrentTransformation);
- if (bPixelBased && getOptionsDrawinglayer().IsAntiAliasing()
- && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete())
+ if (bPixelBased && getViewInformation2D().getPixelSnapHairline())
{
// #i98289#
// when a Hairline is painted and AntiAliasing is on the option SnapHorVerLinesToDiscrete
@@ -366,18 +506,18 @@ void VclProcessor2D::RenderPolygonHairlinePrimitive2D(
mpOutputDevice->DrawPolyLine(aLocalPolygon, 0.0);
}
-// direct draw of transformed BitmapEx primitive
+// direct draw of transformed Bitmap primitive
void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
{
- BitmapEx aBitmapEx(VCLUnoHelper::GetBitmap(rBitmapCandidate.getXBitmap()));
+ Bitmap aBitmap(rBitmapCandidate.getBitmap());
const basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation
* rBitmapCandidate.getTransform());
if (maBColorModifierStack.count())
{
- aBitmapEx = aBitmapEx.ModifyBitmapEx(maBColorModifierStack);
+ aBitmap = aBitmap.Modify(maBColorModifierStack);
- if (aBitmapEx.IsEmpty())
+ if (aBitmap.IsEmpty())
{
// color gets completely replaced, get it
const basegfx::BColor aModifiedColor(
@@ -397,249 +537,248 @@ void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2
// the own transformer is used (see OutputDevice::DrawTransformedBitmapEx).
// draw using OutputDevice'sDrawTransformedBitmapEx
- mpOutputDevice->DrawTransformedBitmapEx(aLocalTransform, aBitmapEx);
+ mpOutputDevice->DrawTransformedBitmapEx(aLocalTransform, aBitmap);
}
void VclProcessor2D::RenderFillGraphicPrimitive2D(
const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate)
{
+ if (rFillBitmapCandidate.getTransparency() < 0.0
+ || rFillBitmapCandidate.getTransparency() > 1.0)
+ {
+ // invalid transparence, done
+ return;
+ }
+
+ bool bPrimitiveAccepted = RenderFillGraphicPrimitive2DImpl(rFillBitmapCandidate);
+
+ if (!bPrimitiveAccepted)
+ {
+ // do not accept, use decomposition
+ process(rFillBitmapCandidate);
+ }
+}
+
+bool VclProcessor2D::RenderFillGraphicPrimitive2DImpl(
+ const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate)
+{
const attribute::FillGraphicAttribute& rFillGraphicAttribute(
rFillBitmapCandidate.getFillGraphic());
- bool bPrimitiveAccepted(false);
// #121194# when tiling is used and content is bitmap-based, do direct tiling in the
// renderer on pixel base to ensure tight fitting. Do not do this when
// the fill is rotated or sheared.
- if (rFillGraphicAttribute.getTiling())
- {
- // content is bitmap(ex)
- //
- // for Vector Graphic Data (SVG, EMF+) support, force decomposition when present. This will lead to use
- // the primitive representation of the vector data directly.
- //
- // when graphic is animated, force decomposition to use the correct graphic, else
- // fill style will not be animated
- if (GraphicType::Bitmap == rFillGraphicAttribute.getGraphic().GetType()
- && !rFillGraphicAttribute.getGraphic().getVectorGraphicData()
- && !rFillGraphicAttribute.getGraphic().IsAnimated())
- {
- // decompose matrix to check for shear, rotate and mirroring
- basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation
- * rFillBitmapCandidate.getTransformation());
- basegfx::B2DVector aScale, aTranslate;
- double fRotate, fShearX;
- aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
-
- // when nopt rotated/sheared
- if (basegfx::fTools::equalZero(fRotate) && basegfx::fTools::equalZero(fShearX))
- {
- // no shear or rotate, draw direct in pixel coordinates
- bPrimitiveAccepted = true;
+ if (!rFillGraphicAttribute.getTiling())
+ return false;
+
+ // content is bitmap(ex)
+ //
+ // for Vector Graphic Data (SVG, EMF+) support, force decomposition when present. This will lead to use
+ // the primitive representation of the vector data directly.
+ //
+ // when graphic is animated, force decomposition to use the correct graphic, else
+ // fill style will not be animated
+ if (GraphicType::Bitmap != rFillGraphicAttribute.getGraphic().GetType()
+ || rFillGraphicAttribute.getGraphic().getVectorGraphicData()
+ || rFillGraphicAttribute.getGraphic().IsAnimated())
+ return false;
+
+ // decompose matrix to check for shear, rotate and mirroring
+ basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation
+ * rFillBitmapCandidate.getTransformation());
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+ aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
- // transform object range to device coordinates (pixels). Use
- // the device transformation for better accuracy
- basegfx::B2DRange aObjectRange(aTranslate, aTranslate + aScale);
- aObjectRange.transform(mpOutputDevice->GetViewTransformation());
+ // when nopt rotated/sheared
+ if (!basegfx::fTools::equalZero(fRotate) || !basegfx::fTools::equalZero(fShearX))
+ return false;
- // extract discrete size of object
- const sal_Int32 nOWidth(basegfx::fround(aObjectRange.getWidth()));
- const sal_Int32 nOHeight(basegfx::fround(aObjectRange.getHeight()));
+ // no shear or rotate, draw direct in pixel coordinates
- // only do something when object has a size in discrete units
- if (nOWidth > 0 && nOHeight > 0)
- {
- // transform graphic range to device coordinates (pixels). Use
- // the device transformation for better accuracy
- basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange());
- aGraphicRange.transform(mpOutputDevice->GetViewTransformation()
- * aLocalTransform);
-
- // extract discrete size of graphic
- // caution: when getting to zero, nothing would be painted; thus, do not allow this
- const sal_Int32 nBWidth(
- std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getWidth())));
- const sal_Int32 nBHeight(
- std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getHeight())));
-
- // only do something when bitmap fill has a size in discrete units
- if (nBWidth > 0 && nBHeight > 0)
- {
- // nBWidth, nBHeight is the pixel size of the needed bitmap. To not need to scale it
- // in vcl many times, create a size-optimized version
- const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
- BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx());
- const bool bPreScaled(nBWidth * nBHeight < (250 * 250));
-
- // ... but only up to a maximum size, else it gets too expensive
- if (bPreScaled)
- {
- // if color depth is below 24bit, expand before scaling for better quality.
- // This is even needed for low colors, else the scale will produce
- // a bitmap in gray or Black/White (!)
- if (aBitmapEx.GetBitCount() < 24)
- {
- aBitmapEx.Convert(BmpConversion::N24Bit);
- }
+ // transform object range to device coordinates (pixels). Use
+ // the device transformation for better accuracy
+ basegfx::B2DRange aObjectRange(aTranslate, aTranslate + aScale);
+ aObjectRange.transform(mpOutputDevice->GetViewTransformation());
- aBitmapEx.Scale(aNeededBitmapSizePixel, BmpScaleFlag::Interpolate);
- }
+ // extract discrete size of object
+ const sal_Int32 nOWidth(basegfx::fround(aObjectRange.getWidth()));
+ const sal_Int32 nOHeight(basegfx::fround(aObjectRange.getHeight()));
- bool bPainted(false);
+ // only do something when object has a size in discrete units
+ if (nOWidth <= 0 || nOHeight <= 0)
+ return true;
- if (maBColorModifierStack.count())
- {
- // when color modifier, apply to bitmap
- aBitmapEx = aBitmapEx.ModifyBitmapEx(maBColorModifierStack);
+ // transform graphic range to device coordinates (pixels). Use
+ // the device transformation for better accuracy
+ basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange());
+ aGraphicRange.transform(mpOutputDevice->GetViewTransformation() * aLocalTransform);
- // impModifyBitmapEx uses empty bitmap as sign to return that
- // the content will be completely replaced to mono color, use shortcut
- if (aBitmapEx.IsEmpty())
- {
- // color gets completely replaced, get it
- const basegfx::BColor aModifiedColor(
- maBColorModifierStack.getModifiedColor(basegfx::BColor()));
- basegfx::B2DPolygon aPolygon(basegfx::utils::createUnitPolygon());
- aPolygon.transform(aLocalTransform);
+ // extract discrete size of graphic
+ // caution: when getting to zero, nothing would be painted; thus, do not allow this
+ const sal_Int32 nBWidth(std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getWidth())));
+ const sal_Int32 nBHeight(std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getHeight())));
- mpOutputDevice->SetFillColor(Color(aModifiedColor));
- mpOutputDevice->SetLineColor();
- mpOutputDevice->DrawPolygon(aPolygon);
+ // nBWidth, nBHeight is the pixel size of the needed bitmap. To not need to scale it
+ // in vcl many times, create a size-optimized version
+ const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
+ Bitmap aBitmap(rFillGraphicAttribute.getGraphic().GetBitmap());
+ const bool bPreScaled(nBWidth * nBHeight < (250 * 250));
- bPainted = true;
- }
- }
+ // ... but only up to a maximum size, else it gets too expensive
+ if (bPreScaled)
+ {
+ // if color depth is below 24bit, expand before scaling for better quality.
+ // This is even needed for low colors, else the scale will produce
+ // a bitmap in gray or Black/White (!)
+ if (isPalettePixelFormat(aBitmap.getPixelFormat()))
+ {
+ aBitmap.Convert(BmpConversion::N24Bit);
+ }
- if (!bPainted)
- {
- sal_Int32 nBLeft(basegfx::fround(aGraphicRange.getMinX()));
- sal_Int32 nBTop(basegfx::fround(aGraphicRange.getMinY()));
- const sal_Int32 nOLeft(basegfx::fround(aObjectRange.getMinX()));
- const sal_Int32 nOTop(basegfx::fround(aObjectRange.getMinY()));
- sal_Int32 nPosX(0);
- sal_Int32 nPosY(0);
-
- if (nBLeft > nOLeft)
- {
- const sal_Int32 nDiff((nBLeft / nBWidth) + 1);
+ aBitmap.Scale(aNeededBitmapSizePixel, BmpScaleFlag::Interpolate);
+ }
- nPosX -= nDiff;
- nBLeft -= nDiff * nBWidth;
- }
+ if (rFillBitmapCandidate.hasTransparency())
+ aBitmap.BlendAlpha(
+ static_cast<sal_uInt8>(255 - (rFillBitmapCandidate.getTransparency() * 255)));
- if (nBLeft + nBWidth <= nOLeft)
- {
- const sal_Int32 nDiff(-nBLeft / nBWidth);
+ if (maBColorModifierStack.count())
+ {
+ // when color modifier, apply to bitmap
+ aBitmap = aBitmap.Modify(maBColorModifierStack);
- nPosX += nDiff;
- nBLeft += nDiff * nBWidth;
- }
+ // ModifyBitmapEx uses empty bitmap as sign to return that
+ // the content will be completely replaced to mono color, use shortcut
+ if (aBitmap.IsEmpty())
+ {
+ // color gets completely replaced, get it
+ const basegfx::BColor aModifiedColor(
+ maBColorModifierStack.getModifiedColor(basegfx::BColor()));
+ basegfx::B2DPolygon aPolygon(basegfx::utils::createUnitPolygon());
+ aPolygon.transform(aLocalTransform);
- if (nBTop > nOTop)
- {
- const sal_Int32 nDiff((nBTop / nBHeight) + 1);
+ mpOutputDevice->SetFillColor(Color(aModifiedColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolygon(aPolygon);
- nPosY -= nDiff;
- nBTop -= nDiff * nBHeight;
- }
+ return true;
+ }
+ }
- if (nBTop + nBHeight <= nOTop)
- {
- const sal_Int32 nDiff(-nBTop / nBHeight);
+ sal_Int32 nBLeft(basegfx::fround(aGraphicRange.getMinX()));
+ sal_Int32 nBTop(basegfx::fround(aGraphicRange.getMinY()));
+ const sal_Int32 nOLeft(basegfx::fround(aObjectRange.getMinX()));
+ const sal_Int32 nOTop(basegfx::fround(aObjectRange.getMinY()));
+ sal_Int32 nPosX(0);
+ sal_Int32 nPosY(0);
- nPosY += nDiff;
- nBTop += nDiff * nBHeight;
- }
+ if (nBLeft > nOLeft)
+ {
+ const sal_Int32 nDiff((nBLeft / nBWidth) + 1);
- // prepare OutDev
- const Point aEmptyPoint(0, 0);
- const ::tools::Rectangle aVisiblePixel(
- aEmptyPoint, mpOutputDevice->GetOutputSizePixel());
- const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
- mpOutputDevice->EnableMapMode(false);
+ nPosX -= nDiff;
+ nBLeft -= nDiff * nBWidth;
+ }
- // check if offset is used
- const sal_Int32 nOffsetX(
- basegfx::fround(rFillGraphicAttribute.getOffsetX() * nBWidth));
+ if (nBLeft + nBWidth <= nOLeft)
+ {
+ const sal_Int32 nDiff(-nBLeft / nBWidth);
- if (nOffsetX)
- {
- // offset in X, so iterate over Y first and draw lines
- for (sal_Int32 nYPos(nBTop); nYPos < nOTop + nOHeight;
- nYPos += nBHeight, nPosY++)
- {
- for (sal_Int32 nXPos((nPosY % 2) ? nBLeft - nBWidth + nOffsetX
- : nBLeft);
- nXPos < nOLeft + nOWidth; nXPos += nBWidth)
- {
- const ::tools::Rectangle aOutRectPixel(
- Point(nXPos, nYPos), aNeededBitmapSizePixel);
-
- if (aOutRectPixel.IsOver(aVisiblePixel))
- {
- if (bPreScaled)
- {
- mpOutputDevice->DrawBitmapEx(
- aOutRectPixel.TopLeft(), aBitmapEx);
- }
- else
- {
- mpOutputDevice->DrawBitmapEx(
- aOutRectPixel.TopLeft(), aNeededBitmapSizePixel,
- aBitmapEx);
- }
- }
- }
- }
- }
- else
- {
- // check if offset is used
- const sal_Int32 nOffsetY(
- basegfx::fround(rFillGraphicAttribute.getOffsetY() * nBHeight));
+ nPosX += nDiff;
+ nBLeft += nDiff * nBWidth;
+ }
- // possible offset in Y, so iterate over X first and draw columns
- for (sal_Int32 nXPos(nBLeft); nXPos < nOLeft + nOWidth;
- nXPos += nBWidth, nPosX++)
- {
- for (sal_Int32 nYPos((nPosX % 2) ? nBTop - nBHeight + nOffsetY
- : nBTop);
- nYPos < nOTop + nOHeight; nYPos += nBHeight)
- {
- const ::tools::Rectangle aOutRectPixel(
- Point(nXPos, nYPos), aNeededBitmapSizePixel);
-
- if (aOutRectPixel.IsOver(aVisiblePixel))
- {
- if (bPreScaled)
- {
- mpOutputDevice->DrawBitmapEx(
- aOutRectPixel.TopLeft(), aBitmapEx);
- }
- else
- {
- mpOutputDevice->DrawBitmapEx(
- aOutRectPixel.TopLeft(), aNeededBitmapSizePixel,
- aBitmapEx);
- }
- }
- }
- }
- }
+ if (nBTop > nOTop)
+ {
+ const sal_Int32 nDiff((nBTop / nBHeight) + 1);
- // restore OutDev
- mpOutputDevice->EnableMapMode(bWasEnabled);
- }
+ nPosY -= nDiff;
+ nBTop -= nDiff * nBHeight;
+ }
+
+ if (nBTop + nBHeight <= nOTop)
+ {
+ const sal_Int32 nDiff(-nBTop / nBHeight);
+
+ nPosY += nDiff;
+ nBTop += nDiff * nBHeight;
+ }
+
+ // prepare OutDev
+ const Point aEmptyPoint(0, 0);
+ // the visible rect, in pixels
+ const ::tools::Rectangle aVisiblePixel(aEmptyPoint, mpOutputDevice->GetOutputSizePixel());
+ const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
+ mpOutputDevice->EnableMapMode(false);
+
+ // check if offset is used
+ const sal_Int32 nOffsetX(basegfx::fround(rFillGraphicAttribute.getOffsetX() * nBWidth));
+ const sal_Int32 nOffsetY(basegfx::fround(rFillGraphicAttribute.getOffsetY() * nBHeight));
+
+ // if the tile is a single pixel big, just flood fill with that pixel color
+ if (nOffsetX == 0 && nOffsetY == 0 && aNeededBitmapSizePixel.getWidth() == 1
+ && aNeededBitmapSizePixel.getHeight() == 1)
+ {
+ Color col = aBitmap.GetPixelColor(0, 0);
+ mpOutputDevice->SetLineColor(col);
+ mpOutputDevice->SetFillColor(col);
+ mpOutputDevice->DrawRect(aVisiblePixel);
+ }
+ else if (nOffsetX)
+ {
+ // offset in X, so iterate over Y first and draw lines
+ for (sal_Int32 nYPos(nBTop); nYPos < nOTop + nOHeight; nYPos += nBHeight, nPosY++)
+ {
+ for (sal_Int32 nXPos((nPosY % 2) ? nBLeft - nBWidth + nOffsetX : nBLeft);
+ nXPos < nOLeft + nOWidth; nXPos += nBWidth)
+ {
+ const ::tools::Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
+
+ if (aOutRectPixel.Overlaps(aVisiblePixel))
+ {
+ if (bPreScaled)
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmap);
+ }
+ else
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(),
+ aNeededBitmapSizePixel, aBitmap);
}
}
}
}
}
-
- if (!bPrimitiveAccepted)
+ else // nOffsetY is used
{
- // do not accept, use decomposition
- process(rFillBitmapCandidate);
+ // possible offset in Y, so iterate over X first and draw columns
+ for (sal_Int32 nXPos(nBLeft); nXPos < nOLeft + nOWidth; nXPos += nBWidth, nPosX++)
+ {
+ for (sal_Int32 nYPos((nPosX % 2) ? nBTop - nBHeight + nOffsetY : nBTop);
+ nYPos < nOTop + nOHeight; nYPos += nBHeight)
+ {
+ const ::tools::Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
+
+ if (aOutRectPixel.Overlaps(aVisiblePixel))
+ {
+ if (bPreScaled)
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmap);
+ }
+ else
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(),
+ aNeededBitmapSizePixel, aBitmap);
+ }
+ }
+ }
+ }
}
+
+ // restore OutDev
+ mpOutputDevice->EnableMapMode(bWasEnabled);
+ return true;
}
// direct draw of Graphic
@@ -672,7 +811,8 @@ void VclProcessor2D::RenderPolyPolygonGraphicPrimitive2D(
case GraphicType::Bitmap:
{
if (!rFillGraphicAttribute.getGraphic().IsTransparent()
- && !rFillGraphicAttribute.getGraphic().IsAlpha())
+ && !rFillGraphicAttribute.getGraphic().IsAlpha()
+ && !rPolygonCandidate.hasTransparency())
{
// bitmap is not transparent and has no alpha
const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count());
@@ -757,7 +897,7 @@ void VclProcessor2D::RenderPolyPolygonGraphicPrimitive2D(
}
}
-// mask group. Force output to VDev and create mask from given mask
+// mask group
void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate)
{
if (rMaskCandidate.getChildren().empty())
@@ -769,6 +909,16 @@ void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive
return;
aMask.transform(maCurrentTransformation);
+
+ // Unless smooth edges are needed, simply use clipping.
+ if (basegfx::utils::isRectangle(aMask) || !getViewInformation2D().getUseAntiAliasing())
+ {
+ auto popIt = mpOutputDevice->ScopedPush(vcl::PushFlags::CLIPREGION);
+ mpOutputDevice->IntersectClipRegion(vcl::Region(aMask));
+ process(rMaskCandidate.getChildren());
+ return;
+ }
+
const basegfx::B2DRange aRange(basegfx::utils::getRange(aMask));
impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
@@ -785,28 +935,11 @@ void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive
// 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);
- }
- }
+ // draw mask
+ VirtualDevice& rMask = aBufferDevice.getTransparence();
+ rMask.SetLineColor();
+ rMask.SetFillColor(COL_BLACK);
+ rMask.DrawPolyPolygon(aMask);
// dump buffer to outdev
aBufferDevice.paint();
@@ -841,14 +974,13 @@ void VclProcessor2D::RenderUnifiedTransparencePrimitive2D(
// transparence is in visible range
basegfx::B2DRange aRange(rTransCandidate.getChildren().getB2DRange(getViewInformation2D()));
aRange.transform(maCurrentTransformation);
- impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
+ impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
if (aBufferDevice.isVisible())
{
// remember last OutDev and set to content
OutputDevice* pLastOutputDevice = mpOutputDevice;
mpOutputDevice = &aBufferDevice.getContent();
- mpOutputDevice->Erase();
// paint content to it
process(rTransCandidate.getChildren());
@@ -871,7 +1003,7 @@ void VclProcessor2D::RenderTransparencePrimitive2D(
basegfx::B2DRange aRange(rTransCandidate.getChildren().getB2DRange(getViewInformation2D()));
aRange.transform(maCurrentTransformation);
- impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
+ impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
if (!aBufferDevice.isVisible())
return;
@@ -879,7 +1011,6 @@ void VclProcessor2D::RenderTransparencePrimitive2D(
// remember last OutDev and set to content
OutputDevice* pLastOutputDevice = mpOutputDevice;
mpOutputDevice = &aBufferDevice.getContent();
- mpOutputDevice->Erase();
// paint content to it
process(rTransCandidate.getChildren());
@@ -891,13 +1022,11 @@ void VclProcessor2D::RenderTransparencePrimitive2D(
basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
maBColorModifierStack = basegfx::BColorModifierStack();
- mpOutputDevice->Erase();
-
// paint mask to it (always with transparence intensities, evtl. with AA)
process(rTransCandidate.getTransparence());
// back to old color stack
- maBColorModifierStack = aLastBColorModifierStack;
+ maBColorModifierStack = std::move(aLastBColorModifierStack);
// back to old OutDev
mpOutputDevice = pLastOutputDevice;
@@ -917,19 +1046,17 @@ void VclProcessor2D::RenderTransformPrimitive2D(
// create new transformations for CurrentTransformation
// and for local ViewInformation2D
maCurrentTransformation = maCurrentTransformation * rTransformCandidate.getTransformation();
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
- getViewInformation2D().getViewTransformation(), getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(), getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setObjectTransformation(getViewInformation2D().getObjectTransformation()
+ * rTransformCandidate.getTransformation());
+ setViewInformation2D(aViewInformation2D);
// process content
process(rTransformCandidate.getChildren());
// restore transformations
maCurrentTransformation = aLastCurrentTransformation;
- updateViewInformation(aLastViewInformation2D);
+ setViewInformation2D(aLastViewInformation2D);
}
// new XDrawPage for ViewInformation2D
@@ -940,18 +1067,15 @@ void VclProcessor2D::RenderPagePreviewPrimitive2D(
const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
// create new local ViewInformation2D
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation(),
- getViewInformation2D().getViewTransformation(), getViewInformation2D().getViewport(),
- rPagePreviewCandidate.getXDrawPage(), getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
+ geometry::ViewInformation2D aViewInformation2D(getViewInformation2D());
+ aViewInformation2D.setVisualizedPage(rPagePreviewCandidate.getXDrawPage());
+ setViewInformation2D(aViewInformation2D);
// process decomposed content
process(rPagePreviewCandidate);
// restore transformations
- updateViewInformation(aLastViewInformation2D);
+ setViewInformation2D(aLastViewInformation2D);
}
// marker
@@ -962,11 +1086,11 @@ void VclProcessor2D::RenderMarkerArrayPrimitive2D(
const std::vector<basegfx::B2DPoint>& rPositions = rMarkArrayCandidate.getPositions();
const sal_uInt32 nCount(rPositions.size());
- if (!(nCount && !rMarkArrayCandidate.getMarker().IsEmpty()))
+ if (!nCount || rMarkArrayCandidate.getMarker().IsEmpty())
return;
// get pixel size
- const BitmapEx& rMarker(rMarkArrayCandidate.getMarker());
+ const Bitmap& rMarker(rMarkArrayCandidate.getMarker());
const Size aBitmapSize(rMarker.GetSizePixel());
if (!(aBitmapSize.Width() && aBitmapSize.Height()))
@@ -990,8 +1114,8 @@ void VclProcessor2D::RenderMarkerArrayPrimitive2D(
{
const basegfx::B2DPoint aDiscreteTopLeft((maCurrentTransformation * pos)
- aDiscreteHalfSize);
- const Point aDiscretePoint(basegfx::fround(aDiscreteTopLeft.getX()),
- basegfx::fround(aDiscreteTopLeft.getY()));
+ const Point aDiscretePoint(basegfx::fround<tools::Long>(aDiscreteTopLeft.getX()),
+ basegfx::fround<tools::Long>(aDiscreteTopLeft.getY()));
mpOutputDevice->DrawBitmapEx(aDiscretePoint + aOrigin, rMarker);
}
@@ -1011,8 +1135,8 @@ void VclProcessor2D::RenderPointArrayPrimitive2D(
for (auto const& pos : rPositions)
{
const basegfx::B2DPoint aViewPosition(maCurrentTransformation * pos);
- const Point aPos(basegfx::fround(aViewPosition.getX()),
- basegfx::fround(aViewPosition.getY()));
+ const Point aPos(basegfx::fround<tools::Long>(aViewPosition.getX()),
+ basegfx::fround<tools::Long>(aViewPosition.getY()));
mpOutputDevice->DrawPixel(aPos, aVCLColor);
}
@@ -1027,7 +1151,7 @@ void VclProcessor2D::RenderPolygonStrokePrimitive2D(
const double fLineWidth(rLineAttribute.getWidth());
bool bDone(false);
- if (basegfx::fTools::more(fLineWidth, 0.0))
+ if (fLineWidth > 0.0)
{
const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation
* basegfx::B2DVector(fLineWidth, 0.0));
@@ -1058,7 +1182,7 @@ void VclProcessor2D::RenderPolygonStrokePrimitive2D(
if (nCount)
{
- const bool bAntiAliased(getOptionsDrawinglayer().IsAntiAliasing());
+ const bool bAntiAliased(getViewInformation2D().getUseAntiAliasing());
aHairlinePolyPolygon.transform(maCurrentTransformation);
if (bAntiAliased)
@@ -1271,26 +1395,12 @@ void VclProcessor2D::RenderEpsPrimitive2D(const primitive2d::EpsPrimitive2D& rEp
}
}
-void VclProcessor2D::RenderObjectInfoPrimitive2D(
- const primitive2d::ObjectInfoPrimitive2D& rObjectInfoPrimitive2D)
-{
- // remember current ObjectInfoPrimitive2D and set new current one (build a stack - push)
- const primitive2d::ObjectInfoPrimitive2D* pLast(getObjectInfoPrimitive2D());
- mpObjectInfoPrimitive2D = &rObjectInfoPrimitive2D;
-
- // process content
- process(rObjectInfoPrimitive2D.getChildren());
-
- // restore current ObjectInfoPrimitive2D (pop)
- mpObjectInfoPrimitive2D = pLast;
-}
-
void VclProcessor2D::RenderSvgLinearAtomPrimitive2D(
const primitive2d::SvgLinearAtomPrimitive2D& rCandidate)
{
const double fDelta(rCandidate.getOffsetB() - rCandidate.getOffsetA());
- if (!basegfx::fTools::more(fDelta, 0.0))
+ if (fDelta <= 0.0)
return;
const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA()));
@@ -1300,7 +1410,7 @@ void VclProcessor2D::RenderSvgLinearAtomPrimitive2D(
const basegfx::B2DVector aDiscreteVector(
getViewInformation2D().getInverseObjectToViewTransformation()
* basegfx::B2DVector(1.0, 1.0));
- const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373));
+ const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / M_SQRT2));
// use color distance and discrete lengths to calculate step count
const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDelta, fDiscreteUnit));
@@ -1334,7 +1444,7 @@ void VclProcessor2D::RenderSvgRadialAtomPrimitive2D(
{
const double fDeltaScale(rCandidate.getScaleB() - rCandidate.getScaleA());
- if (!basegfx::fTools::more(fDeltaScale, 0.0))
+ if (fDeltaScale <= 0.0)
return;
const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA()));
@@ -1344,7 +1454,7 @@ void VclProcessor2D::RenderSvgRadialAtomPrimitive2D(
const basegfx::B2DVector aDiscreteVector(
getViewInformation2D().getInverseObjectToViewTransformation()
* basegfx::B2DVector(1.0, 1.0));
- const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373));
+ const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / M_SQRT2));
// use color distance and discrete lengths to calculate step count
const sal_uInt32 nSteps(
@@ -1437,8 +1547,7 @@ void VclProcessor2D::adaptTextToFillDrawMode() const
{
const DrawModeFlags nOriginalDrawMode(mpOutputDevice->GetDrawMode());
if (!(nOriginalDrawMode
- & (DrawModeFlags::BlackText | DrawModeFlags::GrayText | DrawModeFlags::WhiteText
- | DrawModeFlags::SettingsText)))
+ & (DrawModeFlags::BlackText | DrawModeFlags::GrayText | DrawModeFlags::SettingsText)))
return;
DrawModeFlags nAdaptedDrawMode(nOriginalDrawMode);
@@ -1461,15 +1570,6 @@ void VclProcessor2D::adaptTextToFillDrawMode() const
nAdaptedDrawMode &= ~DrawModeFlags::GrayFill;
}
- if (nOriginalDrawMode & DrawModeFlags::WhiteText)
- {
- nAdaptedDrawMode |= DrawModeFlags::WhiteFill;
- }
- else
- {
- nAdaptedDrawMode &= ~DrawModeFlags::WhiteFill;
- }
-
if (nOriginalDrawMode & DrawModeFlags::SettingsText)
{
nAdaptedDrawMode |= DrawModeFlags::SettingsFill;
@@ -1482,25 +1582,40 @@ void VclProcessor2D::adaptTextToFillDrawMode() const
mpOutputDevice->SetDrawMode(nAdaptedDrawMode);
}
-// process support
+void VclProcessor2D::onViewInformation2DChanged()
+{
+ // apply AntiAlias information to target device
+ if (getViewInformation2D().getUseAntiAliasing())
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing()
+ | AntialiasingFlags::Enable);
+ else
+ mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing()
+ & ~AntialiasingFlags::Enable);
+
+ // apply DrawModeFlags to target device
+ if (getViewInformation2D().getDrawModeFlags() != mpOutputDevice->GetDrawMode())
+ mpOutputDevice->SetDrawMode(getViewInformation2D().getDrawModeFlags());
+}
+// process support
VclProcessor2D::VclProcessor2D(const geometry::ViewInformation2D& rViewInformation,
- OutputDevice& rOutDev,
- const basegfx::BColorModifierStack& rInitStack)
+ OutputDevice& rOutDev)
: BaseProcessor2D(rViewInformation)
, mpOutputDevice(&rOutDev)
- , maBColorModifierStack(rInitStack)
- , maCurrentTransformation()
- , maDrawinglayerOpt()
+ , maBColorModifierStack()
, mnPolygonStrokePrimitive2D(0)
- , mpObjectInfoPrimitive2D(nullptr)
+ , mnOriginalAA(rOutDev.GetAntialiasing())
{
// set digit language, derived from SvtCTLOptions to have the correct
// number display for arabic/hindi numerals
rOutDev.SetDigitLanguage(drawinglayer::detail::getDigitLanguage());
+
+ // NOTE: to save/restore original AntiAliasing mode we need
+ // to use mnOriginalAA here - OutputDevice::Push/Pop does not
+ // offer that
}
-VclProcessor2D::~VclProcessor2D() {}
+VclProcessor2D::~VclProcessor2D() { mpOutputDevice->SetAntialiasing(mnOriginalAA); }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */