summaryrefslogtreecommitdiff
path: root/drawinglayer/source/processor2d
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2012-10-16 08:44:02 +0000
committerCaolán McNamara <caolanm@redhat.com>2013-06-11 20:00:34 +0100
commit37aa7d81aacaae12dfe0fd2ade2779235bbf72f1 (patch)
treebaf84cf5f8fcf62221dd75869d507d2396ae690b /drawinglayer/source/processor2d
parente72e1c110ad42b779afbe74b47ca35c1849e06b2 (diff)
Resolves: #i121194# Better support for graphic fill styles...
which are not bitmaps (svg, metafiles, ..) (cherry picked from commit 7a652a2b2ab5e0d37e32185c8c5fac3af482bb76) Conflicts: drawinglayer/Library_drawinglayer.mk drawinglayer/Package_inc.mk drawinglayer/inc/drawinglayer/attribute/fillgraphicattribute.hxx drawinglayer/inc/drawinglayer/attribute/sdrfillattribute.hxx drawinglayer/inc/drawinglayer/attribute/sdrfillgraphicattribute.hxx drawinglayer/inc/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx drawinglayer/inc/drawinglayer/primitive2d/fillgraphicprimitive2d.hxx drawinglayer/inc/drawinglayer/primitive2d/polypolygonprimitive2d.hxx drawinglayer/inc/drawinglayer/primitive3d/textureprimitive3d.hxx drawinglayer/inc/drawinglayer/processor2d/vclprocessor2d.hxx drawinglayer/inc/drawinglayer/texture/texture.hxx drawinglayer/inc/drawinglayer/texture/texture3d.hxx drawinglayer/source/attribute/fillbitmapattribute.cxx drawinglayer/source/attribute/sdrfillattribute.cxx drawinglayer/source/attribute/sdrfillgraphicattribute.cxx drawinglayer/source/primitive2d/fillbitmapprimitive2d.cxx drawinglayer/source/primitive2d/graphicprimitive2d.cxx drawinglayer/source/primitive2d/polypolygonprimitive2d.cxx drawinglayer/source/processor2d/canvasprocessor.cxx svx/inc/svx/sdr/primitive2d/sdrattributecreator.hxx svx/source/sdr/contact/objectcontacttools.cxx vcl/inc/vcl/graph.hxx unused file _vclmetafileprocessor2d.cxx deleted, was added by error (cherry picked from commit ed0d53f8283cd3ce579a90b599118884d0db6119) Conflicts: drawinglayer/source/processor2d/_vclmetafileprocessor2d.cxx Corrected canvasProcessor usage (cherry picked from commit 7903c33f31c457eb6ff506958c4233f2a5d39bcf) Conflicts: svx/source/sdr/contact/objectcontacttools.cxx Change-Id: I80008050b98dafc92fde043524843c13a75fe22c d2fa667d7c127b4d735334e56093d1d4553b0a5b e20c60c7d6472da1295a162d9a629be998861f62
Diffstat (limited to 'drawinglayer/source/processor2d')
-rw-r--r--drawinglayer/source/processor2d/canvasprocessor.cxx993
-rw-r--r--drawinglayer/source/processor2d/processorfromoutputdevice.cxx35
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx73
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx10
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx390
5 files changed, 279 insertions, 1222 deletions
diff --git a/drawinglayer/source/processor2d/canvasprocessor.cxx b/drawinglayer/source/processor2d/canvasprocessor.cxx
deleted file mode 100644
index b8d260aa941e..000000000000
--- a/drawinglayer/source/processor2d/canvasprocessor.cxx
+++ /dev/null
@@ -1,993 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include <drawinglayer/processor2d/canvasprocessor.hxx>
-#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
-#include <com/sun/star/rendering/XCanvas.hpp>
-#include <vcl/canvastools.hxx>
-#include <basegfx/tools/canvastools.hxx>
-#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
-#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
-#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
-#include <canvas/canvastools.hxx>
-#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
-#include <basegfx/polygon/b2dpolygonclipper.hxx>
-#include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
-#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
-#include <cppcanvas/basegfxfactory.hxx>
-#include <com/sun/star/rendering/XBitmapCanvas.hpp>
-#include <cppcanvas/vclfactory.hxx>
-#include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
-#include <drawinglayer/primitive2d/textprimitive2d.hxx>
-#include <com/sun/star/rendering/TextDirection.hpp>
-#include <vclhelperbitmaptransform.hxx>
-#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
-#include <basegfx/polygon/b2dpolygontools.hxx>
-#include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
-#include <basegfx/tuple/b2i64tuple.hxx>
-#include <basegfx/range/b2irange.hxx>
-#include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp>
-#include <com/sun/star/rendering/PanoseProportion.hpp>
-#include <com/sun/star/rendering/CompositeOperation.hpp>
-#include <com/sun/star/rendering/StrokeAttributes.hpp>
-#include <com/sun/star/rendering/PathJoinType.hpp>
-#include <com/sun/star/rendering/PathCapType.hpp>
-#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
-#include <com/sun/star/rendering/TexturingMode.hpp>
-#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
-#include <vclhelperbufferdevice.hxx>
-#include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
-#include <helperwrongspellrenderer.hxx>
-#include <basegfx/matrix/b2dhommatrixtools.hxx>
-
-#include "getdigitlanguage.hxx"
-
-//////////////////////////////////////////////////////////////////////////////
-
-using namespace com::sun::star;
-
-//////////////////////////////////////////////////////////////////////////////
-
-namespace drawinglayer
-{
- namespace processor2d
- {
- //////////////////////////////////////////////////////////////////////////////
- // single primitive renderers
-
- void canvasProcessor2D::impRenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
- {
- const primitive2d::Primitive2DSequence& rChildren = rMaskCandidate.getChildren();
- static bool bUseMaskBitmapMethod(true);
-
- if(rChildren.hasElements())
- {
- basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
-
- if(!aMask.count())
- {
- // no mask, no clipping. recursively paint content
- process(rChildren);
- }
- else
- {
- // there are principally two methods for implementing the mask primitive. One
- // is to set a clip polygon at the canvas, the other is to create and use a
- // transparence-using XBitmap for content and draw the mask as transparence. Both have their
- // advantages and disadvantages, so here are both with a bool allowing simple
- // change
- if(bUseMaskBitmapMethod)
- {
- // get logic range of transparent part, clip with ViewRange
- basegfx::B2DRange aLogicRange(aMask.getB2DRange());
-
- if(!getViewInformation2D().getViewport().isEmpty())
- {
- aLogicRange.intersect(getViewInformation2D().getViewport());
- }
-
- if(!aLogicRange.isEmpty())
- {
- // get discrete range of transparent part
- basegfx::B2DRange aDiscreteRange(aLogicRange);
- aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
-
- // expand to next covering discrete values (pixel bounds)
- aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
- aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
-
- // use VCL-based buffer device
- impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
-
- if(aBufferDevice.isVisible())
- {
- // remember current OutDev, Canvas and ViewInformation
- OutputDevice* pLastOutputDevice = mpOutputDevice;
- uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
- const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
-
- // prepare discrete offset for XBitmap, do not forget that the buffer bitmap
- // may be truncated to discrete visible pixels
- const basegfx::B2DHomMatrix aDiscreteOffset(basegfx::tools::createTranslateB2DHomMatrix(
- aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
- aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0));
-
- // create new local ViewInformation2D with new transformation
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation(),
- aDiscreteOffset * getViewInformation2D().getViewTransformation(),
- getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(),
- getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
-
- // set OutDev and Canvas to content target
- mpOutputDevice = &aBufferDevice.getContent();
- mxCanvas = mpOutputDevice->GetCanvas();
- canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
-
- // if ViewState transform is changed, the clipping polygon needs to be adapted, too
- const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
-
- if(maClipPolyPolygon.count())
- {
- maClipPolyPolygon.transform(aDiscreteOffset);
- maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
- }
-
- // paint content
- process(rChildren);
-
- // draw mask
- const basegfx::BColor aBlack(0.0, 0.0, 0.0);
- maRenderState.DeviceColor = aBlack.colorToDoubleSequence(mxCanvas->getDevice());
-
- if(getOptionsDrawinglayer().IsAntiAliasing())
- {
- // with AA, use 8bit AlphaMask to get nice borders
- VirtualDevice& rTransparence = aBufferDevice.getTransparence();
- rTransparence.GetCanvas()->fillPolyPolygon(
- basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
- maViewState, maRenderState);
- }
- else
- {
- // No AA, use 1bit mask
- VirtualDevice& rMask = aBufferDevice.getMask();
- rMask.GetCanvas()->fillPolyPolygon(
- basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), aMask),
- maViewState, maRenderState);
- }
-
- // back to old color stack, OutDev, Canvas and ViewTransform
- mpOutputDevice = pLastOutputDevice;
- mxCanvas = xLastCanvas;
- updateViewInformation(aLastViewInformation2D);
- canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
-
- // restore clipping polygon
- maClipPolyPolygon = aOldClipPolyPolygon;
-
- if(maClipPolyPolygon.count())
- {
- maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
- }
-
- // dump buffer to outdev
- aBufferDevice.paint();
- }
- }
- }
- else
- {
- // transform new mask polygon to view coordinates for processing. All masks
- // are processed in view coordinates and clipped against each other evtl. to
- // create multi-clips
- aMask.transform(getViewInformation2D().getObjectTransformation());
-
- // remember last current clip polygon
- const basegfx::B2DPolyPolygon aLastClipPolyPolygon(maClipPolyPolygon);
-
- if(maClipPolyPolygon.count())
- {
- // there is already a clip polygon set; build clipped union of
- // current mask polygon and new one
- maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false);
- }
- else
- {
- // use mask directly
- maClipPolyPolygon = aMask;
- }
-
- // set at ViewState
- if(maClipPolyPolygon.count())
- {
- // set new as clip polygon
- maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
- }
- else
- {
- // empty, reset
- maViewState.Clip.clear();
- }
-
- // paint content
- process(rChildren);
-
- // restore local current to rescued clip polygon
- maClipPolyPolygon = aLastClipPolyPolygon;
-
- // set at ViewState
- if(maClipPolyPolygon.count())
- {
- // set new as clip polygon
- maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
- }
- else
- {
- // empty, reset
- maViewState.Clip.clear();
- }
- }
- }
- }
- }
-
- void canvasProcessor2D::impRenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate)
- {
- GDIMetaFile aMetaFile;
-
- if(maBColorModifierStack.count())
- {
- const basegfx::BColor aRGBBaseColor(0, 0, 0);
- const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
- aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
- }
- else
- {
- aMetaFile = rMetaCandidate.getMetaFile();
- }
-
- cppcanvas::BitmapCanvasSharedPtr pCanvas(cppcanvas::VCLFactory::getInstance().createCanvas(
- uno::Reference<rendering::XBitmapCanvas>(mxCanvas, uno::UNO_QUERY_THROW)));
- cppcanvas::RendererSharedPtr pMtfRenderer(cppcanvas::VCLFactory::getInstance().createRenderer(
- pCanvas, aMetaFile, cppcanvas::Renderer::Parameters()));
-
- if(pMtfRenderer)
- {
- pCanvas->setTransformation(getViewInformation2D().getObjectToViewTransformation());
- pMtfRenderer->setTransformation(rMetaCandidate.getTransform());
- pMtfRenderer->draw();
- }
- }
-
- void canvasProcessor2D::impRenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
- {
- if(rTextCandidate.getTextLength())
- {
- double fShearX(0.0);
- {
- const basegfx::B2DHomMatrix aLocalTransform(getViewInformation2D().getObjectToViewTransformation() * rTextCandidate.getTextTransform());
- basegfx::B2DVector aScale, aTranslate;
- double fRotate;
- aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
- }
-
- if(!basegfx::fTools::equalZero(fShearX))
- {
- // text is sheared. As long as the canvas renderers do not support this,
- // use the decomposed primitive
- process(rTextCandidate.get2DDecomposition(getViewInformation2D()));
- }
- else
- {
- const attribute::FontAttribute& rFontAttr(rTextCandidate.getFontAttribute());
- rendering::FontRequest aFontRequest;
-
- aFontRequest.FontDescription.FamilyName = rFontAttr.getFamilyName();
- aFontRequest.FontDescription.StyleName = rFontAttr.getStyleName();
- aFontRequest.FontDescription.IsSymbolFont = rFontAttr.getSymbol() ? util::TriState_YES : util::TriState_NO;
- aFontRequest.FontDescription.IsVertical = rFontAttr.getVertical() ? util::TriState_YES : util::TriState_NO;
- // TODO(F2): improve vclenum->panose conversion
- aFontRequest.FontDescription.FontDescription.Weight = static_cast< sal_uInt8 >(rFontAttr.getWeight());
- aFontRequest.FontDescription.FontDescription.Proportion =
- rFontAttr.getMonospaced()
- ? rendering::PanoseProportion::MONO_SPACED
- : rendering::PanoseProportion::ANYTHING;
- aFontRequest.FontDescription.FontDescription.Letterform = rFontAttr.getItalic() ? 9 : 0;
-
- // init CellSize to 1.0, else a default font height will be used
- aFontRequest.CellSize = 1.0;
- aFontRequest.Locale = rTextCandidate.getLocale();
-
- // font matrix should only be used for glyph rotations etc.
- com::sun::star::geometry::Matrix2D aFontMatrix;
- canvas::tools::setIdentityMatrix2D(aFontMatrix);
-
- uno::Reference<rendering::XCanvasFont> xFont(mxCanvas->createFont(
- aFontRequest, uno::Sequence< beans::PropertyValue >(), aFontMatrix));
-
- if(xFont.is())
- {
- // got a font, now try to get a TextLayout
- const rendering::StringContext aStringContext(
- rTextCandidate.getText(), rTextCandidate.getTextPosition(), rTextCandidate.getTextLength());
- uno::Reference<rendering::XTextLayout> xLayout(xFont->createTextLayout(
- aStringContext, com::sun::star::rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0));
-
- if(xLayout.is())
- {
- // got a text layout, apply DXArray if given
- const ::std::vector< double >& rDXArray = rTextCandidate.getDXArray();
- const sal_uInt32 nDXCount(rDXArray.size());
-
- if(nDXCount)
- {
- // DXArray does not need to be adapted to getTextPosition/getTextLength,
- // it is already provided correctly
- const uno::Sequence< double > aDXSequence(&rDXArray[0], nDXCount);
- xLayout->applyLogicalAdvancements(aDXSequence);
- }
-
- // set text color
- const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
- maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
-
- // set text transformation
- canvas::tools::setRenderStateTransform(maRenderState,
- getViewInformation2D().getObjectTransformation() * rTextCandidate.getTextTransform());
-
- // paint
- mxCanvas->drawTextLayout(xLayout, maViewState, maRenderState);
- }
- }
- }
- }
- }
-
- void canvasProcessor2D::impRenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
- {
- // apply possible color modification to BitmapEx
- BitmapEx aModifiedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rBitmapCandidate.getBitmapEx()));
-
- if(aModifiedBitmapEx.IsEmpty())
- {
- // replace with color filled polygon
- const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
- const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
-
- maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
- canvas::tools::setRenderStateTransform(maRenderState,
- getViewInformation2D().getObjectTransformation() * rBitmapCandidate.getTransform());
-
- mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
- mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState);
- }
- else
- {
- // adapt object's transformation to the correct scale
- basegfx::B2DVector aScale, aTranslate;
- const Size aSizePixel(aModifiedBitmapEx.GetSizePixel());
-
- if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
- {
- double fRotate, fShearX;
- rBitmapCandidate.getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
- const basegfx::B2DHomMatrix aNewMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
- aScale.getX() / aSizePixel.Width(), aScale.getY() / aSizePixel.Height(),
- fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
-
- canvas::tools::setRenderStateTransform(maRenderState,
- getViewInformation2D().getObjectTransformation() * aNewMatrix);
-
- mxCanvas->drawBitmap(
- vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aModifiedBitmapEx),
- maViewState, maRenderState);
- }
- }
- }
-
- void canvasProcessor2D::impRenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransparenceCandidate)
- {
- const primitive2d::Primitive2DSequence& rChildren = rTransparenceCandidate.getChildren();
- const primitive2d::Primitive2DSequence& rTransparence = rTransparenceCandidate.getTransparence();
-
- if(rChildren.hasElements() && rTransparence.hasElements())
- {
- // get logic range of transparent part and clip with ViewRange
- basegfx::B2DRange aLogicRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rChildren, getViewInformation2D()));
-
- if(!getViewInformation2D().getViewport().isEmpty())
- {
- aLogicRange.intersect(getViewInformation2D().getViewport());
- }
-
- if(!aLogicRange.isEmpty())
- {
- // get discrete range of transparent part
- basegfx::B2DRange aDiscreteRange(aLogicRange);
- aDiscreteRange.transform(getViewInformation2D().getObjectToViewTransformation());
-
- // expand to next covering discrete values (pixel bounds)
- aDiscreteRange.expand(basegfx::B2DTuple(floor(aDiscreteRange.getMinX()), floor(aDiscreteRange.getMinY())));
- aDiscreteRange.expand(basegfx::B2DTuple(ceil(aDiscreteRange.getMaxX()), ceil(aDiscreteRange.getMaxY())));
-
- // use VCL-based buffer device
- impBufferDevice aBufferDevice(*mpOutputDevice, aDiscreteRange, false);
-
- if(aBufferDevice.isVisible())
- {
- // remember current OutDev, Canvas and ViewInformation
- OutputDevice* pLastOutputDevice = mpOutputDevice;
- uno::Reference< rendering::XCanvas > xLastCanvas(mxCanvas);
- const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
-
- // prepare discrete offset for XBitmap, do not forget that the buffer bitmap
- // may be truncated to discrete visible pixels
- const basegfx::B2DHomMatrix aDiscreteOffset(basegfx::tools::createTranslateB2DHomMatrix(
- aDiscreteRange.getMinX() > 0.0 ? -aDiscreteRange.getMinX() : 0.0,
- aDiscreteRange.getMinY() > 0.0 ? -aDiscreteRange.getMinY() : 0.0));
-
- // create new local ViewInformation2D with new transformation
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation(),
- aDiscreteOffset * getViewInformation2D().getViewTransformation(),
- getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(),
- getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
-
- // set OutDev and Canvas to content target
- mpOutputDevice = &aBufferDevice.getContent();
- mxCanvas = mpOutputDevice->GetCanvas();
- canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
-
- // if ViewState transform is changed, the clipping polygon needs to be adapted, too
- const basegfx::B2DPolyPolygon aOldClipPolyPolygon(maClipPolyPolygon);
-
- if(maClipPolyPolygon.count())
- {
- maClipPolyPolygon.transform(aDiscreteOffset);
- maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
- }
-
- // paint content
- process(rChildren);
-
- // set to mask
- mpOutputDevice = &aBufferDevice.getTransparence();
- mxCanvas = mpOutputDevice->GetCanvas();
- canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
-
- // 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(rTransparence);
-
- // back to old color stack, OutDev, Canvas and ViewTransform
- maBColorModifierStack = aLastBColorModifierStack;
- mpOutputDevice = pLastOutputDevice;
- mxCanvas = xLastCanvas;
- updateViewInformation(aLastViewInformation2D);
- canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
-
- // restore clipping polygon
- maClipPolyPolygon = aOldClipPolyPolygon;
-
- if(maClipPolyPolygon.count())
- {
- maViewState.Clip = basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), maClipPolyPolygon);
- }
-
- // dump buffer to outdev
- aBufferDevice.paint();
- }
- }
- }
- }
-
- void canvasProcessor2D::impRenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive)
- {
- // support direct fat line geometry. This moves the decomposition to the canvas.
- // As long as our canvases are used (which also use basegfx tooling) this makes
- // no difference, but potentially canvases may better support this
- static bool bSupportFatLineDirectly(true);
- bool bOutputDone(false);
-
- if(bSupportFatLineDirectly)
- {
- const attribute::LineAttribute& rLineAttribute = rPolygonStrokePrimitive.getLineAttribute();
- const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokePrimitive.getStrokeAttribute();
-
- if(0.0 < rLineAttribute.getWidth() || 0 != rStrokeAttribute.getDotDashArray().size())
- {
- rendering::StrokeAttributes aStrokeAttribute;
-
- aStrokeAttribute.StrokeWidth = rLineAttribute.getWidth();
- aStrokeAttribute.MiterLimit = 15.0; // degrees; maybe here (15.0 * F_PI180) is needed, not clear in the documentation
- const ::std::vector< double >& rDotDashArray = rStrokeAttribute.getDotDashArray();
-
- if(!rDotDashArray.empty())
- {
- aStrokeAttribute.DashArray = uno::Sequence< double >(&rDotDashArray[0], rDotDashArray.size());
- }
-
- switch(rLineAttribute.getLineJoin())
- {
- default: // B2DLINEJOIN_NONE, B2DLINEJOIN_MIDDLE
- aStrokeAttribute.JoinType = rendering::PathJoinType::NONE;
- break;
- case basegfx::B2DLINEJOIN_BEVEL:
- aStrokeAttribute.JoinType = rendering::PathJoinType::BEVEL;
- break;
- case basegfx::B2DLINEJOIN_MITER:
- aStrokeAttribute.JoinType = rendering::PathJoinType::MITER;
- break;
- case basegfx::B2DLINEJOIN_ROUND:
- aStrokeAttribute.JoinType = rendering::PathJoinType::ROUND;
- break;
- }
-
- switch(rLineAttribute.getLineCap())
- {
- case com::sun::star::drawing::LineCap_ROUND:
- aStrokeAttribute.StartCapType = rendering::PathCapType::ROUND;
- aStrokeAttribute.EndCapType = rendering::PathCapType::ROUND;
- break;
- case com::sun::star::drawing::LineCap_SQUARE:
- aStrokeAttribute.StartCapType = rendering::PathCapType::SQUARE;
- aStrokeAttribute.EndCapType = rendering::PathCapType::SQUARE;
- break;
- default: // com::sun::star::drawing::LineCap_BUTT
- aStrokeAttribute.StartCapType = rendering::PathCapType::BUTT;
- aStrokeAttribute.EndCapType = rendering::PathCapType::BUTT;
- break;
- }
-
- const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor()));
- maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
- canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
-
- mxCanvas->strokePolyPolygon(
- basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonStrokePrimitive.getB2DPolygon()),
- maViewState, maRenderState, aStrokeAttribute);
-
- bOutputDone = true;
- }
- }
-
- if(!bOutputDone)
- {
- // process decomposition
- process(rPolygonStrokePrimitive.get2DDecomposition(getViewInformation2D()));
- }
- }
-
- void canvasProcessor2D::impRenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapPrimitive2D)
- {
- // support tiled fills directly when tiling is on
- static bool bSupportFillBitmapDirectly(true);
- bool bOutputDone(false);
-
- if(bSupportFillBitmapDirectly)
- {
- const attribute::FillBitmapAttribute& rFillBitmapAttribute = rFillBitmapPrimitive2D.getFillBitmap();
-
- if(rFillBitmapAttribute.getTiling())
- {
- // apply possible color modification to Bitmap
- const BitmapEx aChangedBitmapEx(impModifyBitmapEx(maBColorModifierStack, rFillBitmapAttribute.getBitmapEx()));
-
- if(aChangedBitmapEx.IsEmpty())
- {
- // replace with color filled polygon
- const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
- const basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
-
- maRenderState.DeviceColor = aModifiedColor.colorToDoubleSequence(mxCanvas->getDevice());
- canvas::tools::setRenderStateTransform(maRenderState,
- getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
-
- mxCanvas->fillPolyPolygon(basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
- mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aPolygon)), maViewState, maRenderState);
- }
- else
- {
- const Size aSizePixel(aChangedBitmapEx.GetSizePixel());
-
- if(0 != aSizePixel.Width() && 0 != aSizePixel.Height())
- {
- // create texture matrix from texture to object (where object is unit square here),
- // so use values directly
- const basegfx::B2DHomMatrix aTextureMatrix(basegfx::tools::createScaleTranslateB2DHomMatrix(
- rFillBitmapAttribute.getSize().getX(), rFillBitmapAttribute.getSize().getY(),
- rFillBitmapAttribute.getTopLeft().getX(), rFillBitmapAttribute.getTopLeft().getY()));
-
- // create and fill texture
- rendering::Texture aTexture;
-
- basegfx::unotools::affineMatrixFromHomMatrix(aTexture.AffineTransform, aTextureMatrix);
- aTexture.Alpha = 1.0;
- aTexture.Bitmap = vcl::unotools::xBitmapFromBitmapEx(mxCanvas->getDevice(), aChangedBitmapEx);
- aTexture.RepeatModeX = rendering::TexturingMode::REPEAT;
- aTexture.RepeatModeY = rendering::TexturingMode::REPEAT;
-
- // canvas needs a polygon to fill, create unit rectangle polygon
- const basegfx::B2DPolygon aOutlineRectangle(basegfx::tools::createUnitPolygon());
-
- // set primitive's transformation as render state transform
- canvas::tools::setRenderStateTransform(maRenderState,
- getViewInformation2D().getObjectTransformation() * rFillBitmapPrimitive2D.getTransformation());
-
- // put texture into a uno sequence for handover
- uno::Sequence< rendering::Texture > aSeq(1);
- aSeq[0] = aTexture;
-
- // draw textured rectangle
- mxCanvas->fillTexturedPolyPolygon(
- basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), basegfx::B2DPolyPolygon(aOutlineRectangle)),
- maViewState, maRenderState, aSeq);
- }
- }
-
- bOutputDone = true;
- }
- }
-
- if(!bOutputDone)
- {
- // process decomposition
- process(rFillBitmapPrimitive2D.get2DDecomposition(getViewInformation2D()));
- }
- }
-
- void canvasProcessor2D::impRenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rUniTransparenceCandidate)
- {
- if(0.0 == rUniTransparenceCandidate.getTransparence())
- {
- // not transparent at all, directly use content
- process(rUniTransparenceCandidate.getChildren());
- }
- else if(rUniTransparenceCandidate.getTransparence() > 0.0 && rUniTransparenceCandidate.getTransparence() < 1.0)
- {
- const primitive2d::Primitive2DSequence rChildren = rUniTransparenceCandidate.getChildren();
-
- if(rChildren.hasElements())
- {
- bool bOutputDone(false);
-
- // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
- // use the fillPolyPolygon method with correctly set transparence. This is a often used
- // case, so detectiong it is valuable
- if(1 == rChildren.getLength())
- {
- const primitive2d::Primitive2DReference xReference(rChildren[0]);
- const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
-
- if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
- {
- // direct draw of PolyPolygon with color and transparence
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
-
- // add transparence modulation value to DeviceColor
- uno::Sequence< double > aColor(4);
-
- aColor[0] = aPolygonColor.getRed();
- aColor[1] = aPolygonColor.getGreen();
- aColor[2] = aPolygonColor.getBlue();
- aColor[3] = 1.0 - rUniTransparenceCandidate.getTransparence();
- maRenderState.DeviceColor = aColor;
-
- canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
- mxCanvas->fillPolyPolygon(
- basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), pPoPoColor->getB2DPolyPolygon()),
- maViewState, maRenderState);
- bOutputDone = true;
- }
- }
-
- if(!bOutputDone)
- {
- // process decomposition. This will be decomposed to an TransparencePrimitive2D
- // with the same child context and a single polygon for transparent context. This could be
- // directly handled here with known VCL-buffer technology, but would only
- // make a small difference compared to directly rendering the TransparencePrimitive2D
- // using impRenderTransparencePrimitive2D above.
- process(rUniTransparenceCandidate.get2DDecomposition(getViewInformation2D()));
- }
- }
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // internal processing support
-
- void canvasProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate)
- {
- switch(rCandidate.getPrimitive2DID())
- {
- case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D :
- {
- // direct draw of hairline
- const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
- const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
-
- maRenderState.DeviceColor = aHairlineColor.colorToDoubleSequence(mxCanvas->getDevice());
- canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
- mxCanvas->drawPolyPolygon(
- basegfx::unotools::xPolyPolygonFromB2DPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolygon()),
- maViewState, maRenderState);
-
- break;
- }
- case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
- {
- // direct draw of PolyPolygon with color
- const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate = static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate);
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
-
- maRenderState.DeviceColor = aPolygonColor.colorToDoubleSequence(mxCanvas->getDevice());
- canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
- mxCanvas->fillPolyPolygon(
- basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(mxCanvas->getDevice(), rPolygonCandidate.getB2DPolyPolygon()),
- maViewState, maRenderState);
-
- break;
- }
- case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D :
- {
- // modified color group. Force output to unified color.
- const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate = static_cast< const primitive2d::ModifiedColorPrimitive2D& >(rCandidate);
-
- if(rModifiedCandidate.getChildren().hasElements())
- {
- maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
- process(rModifiedCandidate.getChildren());
- maBColorModifierStack.pop();
- }
-
- break;
- }
- case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
- {
- // mask group
- impRenderMaskPrimitive2D(static_cast< const primitive2d::MaskPrimitive2D& >(rCandidate));
-
- break;
- }
- case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D :
- {
- // transform group. Remember current ViewInformation2D
- const primitive2d::TransformPrimitive2D& rTransformCandidate = static_cast< const primitive2d::TransformPrimitive2D& >(rCandidate);
- const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
-
- // create new local ViewInformation2D with new transformation
- const geometry::ViewInformation2D aViewInformation2D(
- getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
- getViewInformation2D().getViewTransformation(),
- getViewInformation2D().getViewport(),
- getViewInformation2D().getVisualizedPage(),
- getViewInformation2D().getViewTime(),
- getViewInformation2D().getExtendedInformationSequence());
- updateViewInformation(aViewInformation2D);
-
- // set at canvas
- canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
-
- // proccess content
- process(rTransformCandidate.getChildren());
-
- // restore transformations
- updateViewInformation(aLastViewInformation2D);
-
- // restore at canvas
- canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
-
- break;
- }
- case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D :
- {
- // new XDrawPage for ViewInformation2D
- const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate = static_cast< const primitive2d::PagePreviewPrimitive2D& >(rCandidate);
-
- // remember current transformation and ViewInformation
- 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);
-
- // proccess decomposed content
- process(rPagePreviewCandidate.get2DDecomposition(getViewInformation2D()));
-
- // restore transformations
- updateViewInformation(aLastViewInformation2D);
- break;
- }
- case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
- {
- // MetaFile primitive
- impRenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate));
-
- break;
- }
- case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D :
- {
- // PointArray primitive
- const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate = static_cast< const primitive2d::PointArrayPrimitive2D& >(rCandidate);
-
- // set point color
- const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor()));
- maRenderState.DeviceColor = aRGBColor.colorToDoubleSequence(mxCanvas->getDevice());
- canvas::tools::setRenderStateTransform(maRenderState, getViewInformation2D().getObjectTransformation());
-
- const std::vector< basegfx::B2DPoint >& rPointVector = rPointArrayCandidate.getPositions();
- const sal_uInt32 nPointCount(rPointVector.size());
-
- for(sal_uInt32 a(0); a < nPointCount; a++)
- {
- const basegfx::B2DPoint& rPoint = rPointVector[a];
- mxCanvas->drawPoint(basegfx::unotools::point2DFromB2DPoint(rPoint), maViewState, maRenderState);
- }
-
- break;
- }
- case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D :
- {
- // TextSimplePortion primitive
- impRenderTextSimplePortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(rCandidate));
-
- break;
- }
- case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
- {
- // Bitmap primitive
- impRenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
-
- break;
- }
- case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D :
- {
- // Transparence primitive
- impRenderTransparencePrimitive2D(static_cast< const primitive2d::TransparencePrimitive2D& >(rCandidate));
-
- break;
- }
- case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D:
- {
- // PolygonStrokePrimitive
- impRenderPolygonStrokePrimitive2D(static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate));
-
- break;
- }
- case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D :
- {
- // FillBitmapPrimitive2D
- impRenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(rCandidate));
-
- break;
- }
- case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D :
- {
- // UnifiedTransparencePrimitive2D
- impRenderUnifiedTransparencePrimitive2D(static_cast< const primitive2d::UnifiedTransparencePrimitive2D& >(rCandidate));
-
- break;
- }
- case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D :
- {
- // wrong spell primitive. Handled directly here using VCL since VCL has a nice and
- // very direct waveline painting which is needed for this. If VCL is to be avoided,
- // this can be removed anytime and the decomposition may be used
- const primitive2d::WrongSpellPrimitive2D& rWrongSpellPrimitive = static_cast< const primitive2d::WrongSpellPrimitive2D& >(rCandidate);
-
- if(!renderWrongSpellPrimitive2D(
- rWrongSpellPrimitive,
- *mpOutputDevice,
- getViewInformation2D().getObjectToViewTransformation(),
- maBColorModifierStack))
- {
- // fallback to decomposition (MetaFile)
- process(rWrongSpellPrimitive.get2DDecomposition(getViewInformation2D()));
- }
-
- break;
- }
-
- // nice to have:
- //
- // case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D :
- // - support FormControls more direct eventually, not sure if this is needed
- // with the canvas renderer. The decomposition provides a bitmap representation
- // of the control which will work
- //
-
- default :
- {
- // process recursively
- process(rCandidate.get2DDecomposition(getViewInformation2D()));
-
- break;
- }
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // process support
-
- canvasProcessor2D::canvasProcessor2D(
- const geometry::ViewInformation2D& rViewInformation,
- OutputDevice& rOutDev)
- : BaseProcessor2D(rViewInformation),
- mpOutputDevice(&rOutDev),
- mxCanvas(rOutDev.GetCanvas()),
- maViewState(),
- maRenderState(),
- maBColorModifierStack(),
- maDrawinglayerOpt(),
- maClipPolyPolygon(),
- meLang(drawinglayer::detail::getDigitLanguage())
- {
- canvas::tools::initViewState(maViewState);
- canvas::tools::initRenderState(maRenderState);
- canvas::tools::setViewStateTransform(maViewState, getViewInformation2D().getViewTransformation());
-
- // set digit language, derived from SvtCTLOptions to have the correct
- // number display for arabic/hindi numerals
- rOutDev.SetDigitLanguage(meLang);
-
- // prepare output directly to pixels
- mpOutputDevice->Push(PUSH_MAPMODE);
- mpOutputDevice->SetMapMode();
-
- // react on AntiAliasing settings
- if(getOptionsDrawinglayer().IsAntiAliasing())
- {
- mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
- }
- else
- {
- mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
- }
- }
-
- canvasProcessor2D::~canvasProcessor2D()
- {
- // restore MapMode
- mpOutputDevice->Pop();
-
- // restore AntiAliasing
- mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW);
- }
- } // end of namespace processor2d
-} // end of namespace drawinglayer
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/processorfromoutputdevice.cxx b/drawinglayer/source/processor2d/processorfromoutputdevice.cxx
index 9875e79a7aae..ac7848829ec0 100644
--- a/drawinglayer/source/processor2d/processorfromoutputdevice.cxx
+++ b/drawinglayer/source/processor2d/processorfromoutputdevice.cxx
@@ -26,7 +26,6 @@
#include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
#include <drawinglayer/processor2d/vclmetafileprocessor2d.hxx>
#include <drawinglayer/processor2d/vclpixelprocessor2d.hxx>
-#include <drawinglayer/processor2d/canvasprocessor.hxx>
#include <vcl/window.hxx>
//////////////////////////////////////////////////////////////////////////////
@@ -53,38 +52,8 @@ namespace drawinglayer
}
else
{
-#ifdef WIN32
- // for a first AA incarnation VCL-PixelRenderer will be okay since
- // simple (and fast) GDIPlus support over VCL will be used.
- // Leaving the code below as a hint for what to do when we will
- // use canvas renderers in the future
-
- //static SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
-
- //if(false && aSvtOptionsDrawinglayer.IsAntiAliasing())
- //{
- // // for WIN32 AA, create cairo canvas processor
- // return new drawinglayer::processor2d::canvasProcessor2D(rViewInformation2D, rTargetOutDev);
- //}
- //else
- //{
- // create Pixel Vcl-Processor
- return new drawinglayer::processor2d::VclPixelProcessor2D(rViewInformation2D, rTargetOutDev);
- //}
-#else
- static bool bTryTestCanvas(false);
-
- if(bTryTestCanvas)
- {
- // create test-cancas-Processor
- return new drawinglayer::processor2d::canvasProcessor2D(rViewInformation2D, rTargetOutDev);
- }
- else
- {
- // create Pixel Vcl-Processor
- return new drawinglayer::processor2d::VclPixelProcessor2D(rViewInformation2D, rTargetOutDev);
- }
-#endif
+ // create Pixel Vcl-Processor
+ return new drawinglayer::processor2d::VclPixelProcessor2D(rViewInformation2D, rTargetOutDev);
}
}
} // end of namespace processor2d
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index ec5ad2d48d71..cf3c79b92638 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -615,7 +615,7 @@ namespace drawinglayer
Even for XFillTransparenceItem it is used, thus it may need to be supported in
UnifiedTransparencePrimitive2D, too, when interpreted as normally filled PolyPolygon.
Implemented for:
- PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D,
+ PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D,
PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D,
PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D,
PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D,
@@ -1345,19 +1345,19 @@ namespace drawinglayer
RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
break;
}
- case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D :
+ case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
{
- // need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
- const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate);
+ // need to handle PolyPolygonGraphicPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
+ const primitive2d::PolyPolygonGraphicPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate);
basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
{
// #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
// per polygon. If there are more use the splitted polygon and call recursively
- const primitive2d::PolyPolygonBitmapPrimitive2D aSplitted(
+ const primitive2d::PolyPolygonGraphicPrimitive2D aSplitted(
aLocalPolyPolygon,
- rBitmapCandidate.getFillBitmap());
+ rBitmapCandidate.getFillGraphic());
processBasePrimitive2D(aSplitted);
}
@@ -1367,46 +1367,41 @@ namespace drawinglayer
if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
{
- aLocalPolyPolygon.transform(maCurrentTransformation);
- // calculate transformation. Get real object size, all values in FillBitmapAttribute
- // are relative to the unified object
- const attribute::FillBitmapAttribute& rFillBitmapAttribute = rBitmapCandidate .getFillBitmap();
- const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(aLocalPolyPolygon));
- const basegfx::B2DVector aOutlineSize(aOutlineRange.getRange());
+ // #121194# Changed implementation and checked usages fo convert to metafile,
+ // presentation start (uses SvtGraphicFill) and printing.
- // get absolute values
- const basegfx::B2DVector aFillBitmapSize(rFillBitmapAttribute.getSize() * aOutlineSize);
- const basegfx::B2DPoint aFillBitmapTopLeft(rFillBitmapAttribute.getTopLeft() * aOutlineSize);
+ // calculate transformation. Get real object size, all values in FillGraphicAttribute
+ // are relative to the unified object
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+ const basegfx::B2DVector aOutlineSize(aLocalPolyPolygon.getB2DRange().getRange());
// the scaling needs scale from pixel to logic coordinate system
- const BitmapEx& rBitmapEx = rFillBitmapAttribute.getBitmapEx();
- Size aBmpSizePixel(rBitmapEx.GetSizePixel());
-
- if(!aBmpSizePixel.Width())
- {
- aBmpSizePixel.Width() = 1;
- }
-
- if(!aBmpSizePixel.Height())
- {
- aBmpSizePixel.Height() = 1;
- }
+ const attribute::FillGraphicAttribute& rFillGraphicAttribute = rBitmapCandidate.getFillGraphic();
+ const Size aBmpSizePixel(rFillGraphicAttribute.getGraphic().GetSizePixel());
+
+ // setup transformation like in impgrfll. Multiply with aOutlineSize
+ // to get from unit coordinates in rFillGraphicAttribute.getGraphicRange()
+ // to object coordinates with object's top left being at (0,0). Divide
+ // by pixel size so that scale from pixel to logic will work in SvtGraphicFill.
+ const basegfx::B2DVector aTransformScale(
+ rFillGraphicAttribute.getGraphicRange().getRange() /
+ basegfx::B2DVector(
+ std::max(1.0, double(aBmpSizePixel.Width())),
+ std::max(1.0, double(aBmpSizePixel.Height()))) *
+ aOutlineSize);
+ const basegfx::B2DPoint aTransformPosition(
+ rFillGraphicAttribute.getGraphicRange().getMinimum() * aOutlineSize);
// setup transformation like in impgrfll
SvtGraphicFill::Transform aTransform;
// scale values are divided by bitmap pixel sizes
- aTransform.matrix[0] = aFillBitmapSize.getX() / aBmpSizePixel.Width();
- aTransform.matrix[4] = aFillBitmapSize.getY() / aBmpSizePixel.Height();
+ aTransform.matrix[0] = aTransformScale.getX();
+ aTransform.matrix[4] = aTransformScale.getY();
// translates are absolute
- aTransform.matrix[2] = aFillBitmapTopLeft.getX();
- aTransform.matrix[5] = aFillBitmapTopLeft.getY();
-
- // setup fill graphic like in impgrfll
- Graphic aFillGraphic = Graphic(rBitmapEx);
- aFillGraphic.SetPrefMapMode(MapMode(MAP_PIXEL));
- aFillGraphic.SetPrefSize(aBmpSizePixel);
+ aTransform.matrix[2] = aTransformPosition.getX();
+ aTransform.matrix[5] = aTransformPosition.getY();
pSvtGraphicFill = new SvtGraphicFill(
getFillPolyPolygon(aLocalPolyPolygon),
@@ -1415,14 +1410,14 @@ namespace drawinglayer
SvtGraphicFill::fillEvenOdd,
SvtGraphicFill::fillTexture,
aTransform,
- rFillBitmapAttribute.getTiling(),
+ rFillGraphicAttribute.getTiling(),
SvtGraphicFill::hatchSingle,
Color(),
SvtGraphicFill::gradientLinear,
Color(),
Color(),
0,
- aFillGraphic);
+ rFillGraphicAttribute.getGraphic());
}
// Do use decomposition; encapsulate with SvtGraphicFill
@@ -1806,7 +1801,7 @@ namespace drawinglayer
}
// PolyPolygonGradientPrimitive2D, PolyPolygonHatchPrimitive2D and
- // PolyPolygonBitmapPrimitive2D are derived from PolyPolygonColorPrimitive2D.
+ // PolyPolygonGraphicPrimitive2D are derived from PolyPolygonColorPrimitive2D.
// Check also for correct ID to exclude derived implementations
if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
{
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index dde9bb5724dc..1f2d518e3c9d 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -24,7 +24,7 @@
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
-#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
@@ -179,10 +179,10 @@ namespace drawinglayer
RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(rCandidate));
break;
}
- case PRIMITIVE2D_ID_FILLBITMAPPRIMITIVE2D :
+ case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D :
{
// direct draw of fillBitmapPrimitive
- RenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(rCandidate));
+ RenderFillGraphicPrimitive2D(static_cast< const primitive2d::FillGraphicPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
@@ -191,10 +191,10 @@ namespace drawinglayer
RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate));
break;
}
- case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D :
+ case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D :
{
// direct draw of bitmap
- RenderPolyPolygonBitmapPrimitive2D(static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate));
+ RenderPolyPolygonGraphicPrimitive2D(static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D& >(rCandidate));
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index cced61242c17..d129251dbfc1 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -28,8 +28,8 @@
#include <vclhelperbitmaptransform.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <vclhelperbitmaprender.hxx>
-#include <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
-#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
+#include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
+#include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <vclhelpergradient.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
@@ -52,6 +52,7 @@
#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
#include <basegfx/color/bcolor.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <vcl/graph.hxx>
#include "getdigitlanguage.hxx"
@@ -474,122 +475,192 @@ namespace drawinglayer
}
}
- void VclProcessor2D::RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapCandidate)
+ void VclProcessor2D::RenderFillGraphicPrimitive2D(const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate)
{
- const attribute::FillBitmapAttribute& rFillBitmapAttribute(rFillBitmapCandidate.getFillBitmap());
+ const attribute::FillGraphicAttribute& rFillGraphicAttribute(rFillBitmapCandidate.getFillGraphic());
bool bPrimitiveAccepted(false);
+ static bool bTryTilingDirect = true;
- if(rFillBitmapAttribute.getTiling())
- {
- // 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);
+ // #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(basegfx::fTools::equalZero(fRotate) && basegfx::fTools::equalZero(fShearX))
+ // ovveride static bool (for debug) and tiling is active
+ if(bTryTilingDirect && rFillGraphicAttribute.getTiling())
+ {
+ // content is bitmap(ex)
+ //
+ // for SVG support, force decomposition when SVG is present. This will lead to use
+ // the primitive representation of the svg directly.
+ //
+ // when graphic is animated, force decomposition to use the correct graphic, else
+ // fill style will not be animated
+ if(GRAPHIC_BITMAP == rFillGraphicAttribute.getGraphic().GetType()
+ && !rFillGraphicAttribute.getGraphic().getSvgData().get()
+ && !rFillGraphicAttribute.getGraphic().IsAnimated())
{
- // no shear or rotate, draw direct in pixel coordinates
- bPrimitiveAccepted = true;
- BitmapEx aBitmapEx(rFillBitmapAttribute.getBitmapEx());
- bool bPainted(false);
-
- if(maBColorModifierStack.count())
+ // 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))
{
- aBitmapEx = impModifyBitmapEx(maBColorModifierStack, aBitmapEx);
-
- if(aBitmapEx.IsEmpty())
- {
- // color gets completely replaced, get it
- const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
- basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
- aPolygon.transform(aLocalTransform);
+ // no shear or rotate, draw direct in pixel coordinates
+ bPrimitiveAccepted = true;
- mpOutputDevice->SetFillColor(Color(aModifiedColor));
- mpOutputDevice->SetLineColor();
- mpOutputDevice->DrawPolygon(aPolygon);
+ // transform object range to device coordinates (pixels). Use
+ // the device transformation for better accuracy
+ basegfx::B2DRange aObjectRange(aTranslate, aTranslate + aScale);
+ aObjectRange.transform(mpOutputDevice->GetViewTransformation());
- bPainted = true;
- }
- }
-
- if(!bPainted)
- {
- const basegfx::B2DPoint aObjTopLeft(aTranslate.getX(), aTranslate.getY());
- const basegfx::B2DPoint aObjBottomRight(aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
- const Point aObjTL(mpOutputDevice->LogicToPixel(Point((sal_Int32)aObjTopLeft.getX(), (sal_Int32)aObjTopLeft.getY())));
- const Point aObjBR(mpOutputDevice->LogicToPixel(Point((sal_Int32)aObjBottomRight.getX(), (sal_Int32)aObjBottomRight.getY())));
-
- const basegfx::B2DPoint aBmpTopLeft(aLocalTransform * rFillBitmapAttribute.getTopLeft());
- const basegfx::B2DPoint aBmpBottomRight(aLocalTransform * basegfx::B2DPoint(rFillBitmapAttribute.getTopLeft() + rFillBitmapAttribute.getSize()));
- const Point aBmpTL(mpOutputDevice->LogicToPixel(Point((sal_Int32)aBmpTopLeft.getX(), (sal_Int32)aBmpTopLeft.getY())));
- const Point aBmpBR(mpOutputDevice->LogicToPixel(Point((sal_Int32)aBmpBottomRight.getX(), (sal_Int32)aBmpBottomRight.getY())));
-
- sal_Int32 nOWidth(aObjBR.X() - aObjTL.X());
- sal_Int32 nOHeight(aObjBR.Y() - aObjTL.Y());
+ // extract discrete size of object
+ const sal_Int32 nOWidth(basegfx::fround(aObjectRange.getWidth()));
+ const sal_Int32 nOHeight(basegfx::fround(aObjectRange.getHeight()));
// only do something when object has a size in discrete units
if(nOWidth > 0 && nOHeight > 0)
{
- sal_Int32 nBWidth(aBmpBR.X() - aBmpTL.X());
- sal_Int32 nBHeight(aBmpBR.Y() - aBmpTL.Y());
+ // 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
+ const sal_Int32 nBWidth(basegfx::fround(aGraphicRange.getWidth()));
+ const sal_Int32 nBHeight(basegfx::fround(aGraphicRange.getHeight()));
// only do something when bitmap fill has a size in discrete units
if(nBWidth > 0 && nBHeight > 0)
{
- sal_Int32 nBLeft(aBmpTL.X());
- sal_Int32 nBTop(aBmpTL.Y());
-
- if(nBLeft > aObjTL.X())
+ // nBWidth, nBHeight is the pixel size of the neede 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(
+ GraphicConversionParameters(
+ aNeededBitmapSizePixel, // get the correct size immediately
+ false, // no unlimited size
+ false, // Use AntiAliasing
+ false, //SnapHorVerLines
+ true // ScaleHighQuality
+ )));
+ bool bPainted(false);
+
+ if(maBColorModifierStack.count())
{
- nBLeft -= ((nBLeft / nBWidth) + 1L) * nBWidth;
- }
+ // when color modifier, apply to bitmap
+ aBitmapEx = impModifyBitmapEx(maBColorModifierStack, aBitmapEx);
- if(nBLeft + nBWidth <= aObjTL.X())
- {
- nBLeft -= (nBLeft / nBWidth) * nBWidth;
- }
+ // 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::tools::createUnitPolygon());
+ aPolygon.transform(aLocalTransform);
- if(nBTop > aObjTL.Y())
- {
- nBTop -= ((nBTop / nBHeight) + 1L) * nBHeight;
+ mpOutputDevice->SetFillColor(Color(aModifiedColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolygon(aPolygon);
+
+ bPainted = true;
+ }
}
- if(nBTop + nBHeight <= aObjTL.Y())
+ if(!bPainted)
{
- nBTop -= (nBTop / nBHeight) * 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);
+
+ if(nBLeft > nOLeft)
+ {
+ const sal_Int32 nDiff((nBLeft / nBWidth) + 1);
- // nBWidth, nBHeight is the pixel size of the neede bitmap. To not need to scale it
- // in vcl many times, create a size-optimized version
- const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
+ nPosX -= nDiff;
+ nBLeft -= nDiff * nBWidth;
+ }
- if(aNeededBitmapSizePixel != aBitmapEx.GetSizePixel())
- {
- aBitmapEx.Scale(aNeededBitmapSizePixel);
- }
+ if(nBLeft + nBWidth <= nOLeft)
+ {
+ const sal_Int32 nDiff(-nBLeft / nBWidth);
- // prepare OutDev
- const Point aEmptyPoint(0, 0);
- const Rectangle aVisiblePixel(aEmptyPoint, mpOutputDevice->GetOutputSizePixel());
- const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
- mpOutputDevice->EnableMapMode(false);
+ nPosX += nDiff;
+ nBLeft += nDiff * nBWidth;
+ }
- for(sal_Int32 nXPos(nBLeft); nXPos < aObjTL.X() + nOWidth; nXPos += nBWidth)
- {
- for(sal_Int32 nYPos(nBTop); nYPos < aObjTL.Y() + nOHeight; nYPos += nBHeight)
+ if(nBTop > nOTop)
+ {
+ const sal_Int32 nDiff((nBTop / nBHeight) + 1);
+
+ 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);
+ const 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));
+
+ 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 Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
+
+ if(aOutRectPixel.IsOver(aVisiblePixel))
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
+ }
+ }
+ }
+ }
+ else
{
- const Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
+ // check if offset is used
+ const sal_Int32 nOffsetY(basegfx::fround(rFillGraphicAttribute.getOffsetY() * nBHeight));
- if(aOutRectPixel.IsOver(aVisiblePixel))
+ // possible offset in Y, so iterate over X first and draw columns
+ for(sal_Int32 nXPos(nBLeft); nXPos < nOLeft + nOWidth; nXPos += nBWidth, nPosX++)
{
- mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
+ for(sal_Int32 nYPos(nPosX % 2 ? nBTop - nBHeight + nOffsetY : nBTop);
+ nYPos < nOTop + nOHeight; nYPos += nBHeight)
+ {
+ const Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
+
+ if(aOutRectPixel.IsOver(aVisiblePixel))
+ {
+ mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
+ }
+ }
}
}
- }
- // restore OutDev
- mpOutputDevice->EnableMapMode(bWasEnabled);
+ // restore OutDev
+ mpOutputDevice->EnableMapMode(bWasEnabled);
+ }
}
}
}
@@ -641,90 +712,105 @@ namespace drawinglayer
}
}
- // direct draw of bitmap
- void VclProcessor2D::RenderPolyPolygonBitmapPrimitive2D(const primitive2d::PolyPolygonBitmapPrimitive2D& rPolygonCandidate)
+ // direct draw of Graphic
+ void VclProcessor2D::RenderPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D& rPolygonCandidate)
{
bool bDone(false);
const basegfx::B2DPolyPolygon& rPolyPolygon = rPolygonCandidate.getB2DPolyPolygon();
- if(rPolyPolygon.count())
+ // #121194# Todo: check if this works
+ if(!rPolyPolygon.count())
{
- const attribute::FillBitmapAttribute& rFillBitmapAttribute = rPolygonCandidate.getFillBitmap();
- const BitmapEx& rBitmapEx = rFillBitmapAttribute.getBitmapEx();
+ // empty polyPolygon, done
+ bDone = true;
+ }
+ else
+ {
+ const attribute::FillGraphicAttribute& rFillGraphicAttribute = rPolygonCandidate.getFillGraphic();
- if(rBitmapEx.IsEmpty())
- {
- // empty bitmap, done
- bDone = true;
- }
- else
+ // try to catch cases where the graphic will be color-modified to a single
+ // color (e.g. shadow)
+ switch(rFillGraphicAttribute.getGraphic().GetType())
{
- // try to catch cases where the bitmap will be color-modified to a single
- // color (e.g. shadow). This would NOT be optimizable with an transparence channel
- // at the Bitmap which we do not have here. When this should change, this
- // optimization has to be reworked accordingly.
- const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count());
-
- if(nBColorModifierStackCount)
+ case GRAPHIC_GDIMETAFILE:
{
- const basegfx::BColorModifier& rTopmostModifier = maBColorModifierStack.getBColorModifier(nBColorModifierStackCount - 1);
-
- if(basegfx::BCOLORMODIFYMODE_REPLACE == rTopmostModifier.getMode())
+ // metafiles are potentially transparent, cannot optimize, not done
+ break;
+ }
+ case GRAPHIC_BITMAP:
+ {
+ if(!rFillGraphicAttribute.getGraphic().IsTransparent() && !rFillGraphicAttribute.getGraphic().IsAlpha())
{
- // the bitmap fill is in unified color, so we can replace it with
- // a single polygon fill. The form of the fill depends on tiling
- if(rFillBitmapAttribute.getTiling())
- {
- // with tiling, fill the whole PolyPolygon with the modifier color
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolyPolygon);
+ // bitmap is not transparent and has no alpha
+ const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count());
- aLocalPolyPolygon.transform(maCurrentTransformation);
- mpOutputDevice->SetLineColor();
- mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor()));
- mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
- }
- else
+ if(nBColorModifierStackCount)
{
- // without tiling, only the area common to the bitmap tile and the
- // PolyPolygon is filled. Create the bitmap tile area in object
- // coordinates. For this, the object transformation needs to be created
- // from the already scaled PolyPolygon. The tile area in object
- // coordinates wil always be non-rotated, so it's not necessary to
- // work with a polygon here
- basegfx::B2DRange aTileRange(rFillBitmapAttribute.getTopLeft(),
- rFillBitmapAttribute.getTopLeft() + rFillBitmapAttribute.getSize());
- const basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.getB2DRange());
- basegfx::B2DHomMatrix aNewObjectTransform;
-
- aNewObjectTransform.set(0, 0, aPolyPolygonRange.getWidth());
- aNewObjectTransform.set(1, 1, aPolyPolygonRange.getHeight());
- aNewObjectTransform.set(0, 2, aPolyPolygonRange.getMinX());
- aNewObjectTransform.set(1, 2, aPolyPolygonRange.getMinY());
- aTileRange.transform(aNewObjectTransform);
-
- // now clip the object polyPolygon against the tile range
- // to get the common area (OR)
- basegfx::B2DPolyPolygon aTarget = basegfx::tools::clipPolyPolygonOnRange(rPolyPolygon, aTileRange, true, false);
-
- if(aTarget.count())
+ const basegfx::BColorModifier& rTopmostModifier = maBColorModifierStack.getBColorModifier(nBColorModifierStackCount - 1);
+
+ if(basegfx::BCOLORMODIFYMODE_REPLACE == rTopmostModifier.getMode())
{
- aTarget.transform(maCurrentTransformation);
- mpOutputDevice->SetLineColor();
- mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor()));
- mpOutputDevice->DrawPolyPolygon(aTarget);
+ // the bitmap fill is in unified color, so we can replace it with
+ // a single polygon fill. The form of the fill depends on tiling
+ if(rFillGraphicAttribute.getTiling())
+ {
+ // with tiling, fill the whole PolyPolygon with the modifier color
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolyPolygon);
+
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor()));
+ mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+ }
+ else
+ {
+ // without tiling, only the area common to the bitmap tile and the
+ // PolyPolygon is filled. Create the bitmap tile area in object
+ // coordinates. For this, the object transformation needs to be created
+ // from the already scaled PolyPolygon. The tile area in object
+ // coordinates wil always be non-rotated, so it's not necessary to
+ // work with a polygon here
+ basegfx::B2DRange aTileRange(rFillGraphicAttribute.getGraphicRange());
+ const basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.getB2DRange());
+ const basegfx::B2DHomMatrix aNewObjectTransform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aPolyPolygonRange.getRange(),
+ aPolyPolygonRange.getMinimum()));
+
+ aTileRange.transform(aNewObjectTransform);
+
+ // now clip the object polyPolygon against the tile range
+ // to get the common area
+ basegfx::B2DPolyPolygon aTarget = basegfx::tools::clipPolyPolygonOnRange(
+ rPolyPolygon,
+ aTileRange,
+ true,
+ false);
+
+ if(aTarget.count())
+ {
+ aTarget.transform(maCurrentTransformation);
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor()));
+ mpOutputDevice->DrawPolyPolygon(aTarget);
+ }
+ }
+
+ // simplified output executed, we are done
+ bDone = true;
}
}
-
- bDone = true;
}
+ break;
+ }
+ default: //GRAPHIC_NONE, GRAPHIC_DEFAULT
+ {
+ // empty graphic, we are done
+ bDone = true;
+ break;
}
}
}
- else
- {
- // empty polyPolygon, done
- bDone = true;
- }
if(!bDone)
{