summaryrefslogtreecommitdiff
path: root/drawinglayer
diff options
context:
space:
mode:
Diffstat (limited to 'drawinglayer')
-rw-r--r--drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx45
-rw-r--r--drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx14
-rw-r--r--drawinglayer/source/primitive2d/metafileprimitive2d.cxx243
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx344
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx53
-rw-r--r--drawinglayer/source/processor3d/shadow3dextractor.cxx76
-rw-r--r--drawinglayer/source/processor3d/zbufferprocessor3d.cxx2
7 files changed, 557 insertions, 220 deletions
diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx
index 0f426c6ad2ba..6c67bded2b17 100644
--- a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx
+++ b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx
@@ -62,11 +62,48 @@ namespace drawinglayer
To get better text quality, it is suggested to handle tis primitive directly
in a renderer. In that case, e.g. hintings on the system can be supported.
+
+ @param maTextTransform
+ The text transformation contains the text start position (always baselined)
+ as translation, the FontSize as scale (where width relative to height defines
+ font scaling and width == height means no font scaling) and the font rotation
+ and shear.
+ When shear is used and a renderer does not support it, it may be better to use
+ the decomposition which will do everything correctly. Same is true for mirroring
+ which would be expressed as negative scalings.
+
+ @param rText
+ The text to be used. Only a part may be used, but a bigger part of the string
+ may be necessary for correct layouting (e.g. international)
+
+ @param aTextPosition
+ The index to the first character to use from rText
+
+ @param aTextLength
+ The number of characters to use from rText
+
+ @param rDXArray
+ The distances between the characters. This parameter may be empty, in that case
+ the renderer is responsible to do something useful. If it is given, it has to be of
+ the size aTextLength. Its values are in logical coordinates and describe the
+ distance for each character to use. This is independent from the font width which
+ is given with maTextTransform. The first value is the offset to use from the start
+ point in FontCoordinateSystem X-Direction (given by maTextTransform) to the start
+ point of the second character
+
+ @param rFontAttribute
+ The font definition
+
+ @param rLocale
+ The locale to use
+
+ @param rFontColor
+ The font color to use
*/
class TextSimplePortionPrimitive2D : public BufferedDecompositionPrimitive2D
{
private:
- /// text range transformation from unit range ([0.0 .. 1.0]) to text range
+ /// text transformation (FontCoordinateSystem)
basegfx::B2DHomMatrix maTextTransform;
/// The text, used from maTextPosition up to maTextPosition + maTextLength
@@ -78,10 +115,10 @@ namespace drawinglayer
/// The length for maText usage, starting from maTextPosition
xub_StrLen maTextLength;
- /// The DX array scale-independent in unit coordinates
+ /// The DX array in logic units
::std::vector< double > maDXArray;
- /// The font to use
+ /// The font definition
attribute::FontAttribute maFontAttribute;
/// The Locale for the text
@@ -90,7 +127,7 @@ namespace drawinglayer
/// font color
basegfx::BColor maFontColor;
- /// #i96669# add simple range buffering for this primitive
+ /// #i96669# internal: add simple range buffering for this primitive
basegfx::B2DRange maB2DRange;
protected:
diff --git a/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx b/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx
index 23d8e7edd913..93ebfeab48e7 100644
--- a/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx
+++ b/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx
@@ -54,9 +54,12 @@ namespace drawinglayer
class Shadow3DExtractingProcessor : public BaseProcessor3D
{
private:
+ /// typedef for data handling
+ typedef std::vector< primitive2d::BasePrimitive2D* > BasePrimitive2DVector;
+
/// result holding vector (2D) and target vector for stacking (inited to &maPrimitive2DSequence)
- primitive2d::Primitive2DSequence maPrimitive2DSequence;
- primitive2d::Primitive2DSequence* mpPrimitive2DSequence;
+ BasePrimitive2DVector maPrimitive2DSequence;
+ BasePrimitive2DVector* mpPrimitive2DSequence;
/// object transformation for scene for 2d definition
basegfx::B2DHomMatrix maObjectTransformation;
@@ -93,6 +96,10 @@ namespace drawinglayer
*/
virtual void processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate);
+ /// helper to convert from BasePrimitive2DVector to primitive2d::Primitive2DSequence
+ const primitive2d::Primitive2DSequence getPrimitive2DSequenceFromBasePrimitive2DVector(
+ const BasePrimitive2DVector& rVector) const;
+
public:
Shadow3DExtractingProcessor(
const geometry::ViewInformation3D& rViewInformation,
@@ -100,9 +107,10 @@ namespace drawinglayer
const basegfx::B3DVector& rLightNormal,
double fShadowSlant,
const basegfx::B3DRange& rContained3DRange);
+ virtual ~Shadow3DExtractingProcessor();
/// data read access
- const primitive2d::Primitive2DSequence& getPrimitive2DSequence() const { return maPrimitive2DSequence; }
+ const primitive2d::Primitive2DSequence getPrimitive2DSequence() const;
const basegfx::B2DHomMatrix& getObjectTransformation() const { return maObjectTransformation; }
const basegfx::B3DHomMatrix& getWorldToEye() const { return maWorldToEye; }
const basegfx::B3DHomMatrix& getEyeToView() const { return maEyeToView; }
diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
index 480fa99e07fe..0d57e566ef8a 100644
--- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
@@ -94,8 +94,10 @@ namespace
basegfx::BColor maTextLineColor;
basegfx::BColor maOverlineColor;
- /// clipping, font, etc.
- Region maRegion;
+ /// clipping
+ basegfx::B2DPolyPolygon maClipPolyPoygon;
+
+ /// font, etc.
Font maFont;
RasterOp maRasterOp;
sal_uInt32 mnLayoutMode;
@@ -110,7 +112,7 @@ namespace
bool mbTextFillColor : 1;
bool mbTextLineColor : 1;
bool mbOverlineColor : 1;
- bool mbRegion : 1;
+ bool mbClipPolyPolygonActive : 1;
public:
PropertyHolder()
@@ -122,7 +124,7 @@ namespace
maTextFillColor(),
maTextLineColor(),
maOverlineColor(),
- maRegion(),
+ maClipPolyPoygon(),
maFont(),
maRasterOp(ROP_OVERPAINT),
mnLayoutMode(0),
@@ -134,7 +136,7 @@ namespace
mbTextFillColor(false),
mbTextLineColor(false),
mbOverlineColor(false),
- mbRegion(false)
+ mbClipPolyPolygonActive(false)
{
}
@@ -179,10 +181,10 @@ namespace
bool getOverlineColorActive() const { return mbOverlineColor; }
void setOverlineColorActive(bool bNew) { if(bNew != mbOverlineColor) mbOverlineColor = bNew; }
- const Region& getRegion() const { return maRegion; }
- void setRegion(const Region& rRegion) { if(rRegion != maRegion) maRegion = rRegion; }
- bool getRegionActive() const { return mbRegion; }
- void setRegionActive(bool bNew) { if(bNew != mbRegion) mbRegion = bNew; }
+ const basegfx::B2DPolyPolygon& getClipPolyPolygon() const { return maClipPolyPoygon; }
+ void setClipPolyPolygon(const basegfx::B2DPolyPolygon& rNew) { if(rNew != maClipPolyPoygon) maClipPolyPoygon = rNew; }
+ bool getClipPolyPolygonActive() const { return mbClipPolyPolygonActive; }
+ void setClipPolyPolygonActive(bool bNew) { if(bNew != mbClipPolyPolygonActive) mbClipPolyPolygonActive = bNew; }
const Font& getFont() const { return maFont; }
void setFont(const Font& rFont) { if(rFont != maFont) maFont = rFont; }
@@ -235,6 +237,12 @@ namespace
return maPropertyHolders.size();
}
+ void PushDefault()
+ {
+ PropertyHolder* pNew = new PropertyHolder();
+ maPropertyHolders.push_back(pNew);
+ }
+
void Push(sal_uInt16 nPushFlags)
{
if(nPushFlags)
@@ -291,8 +299,8 @@ namespace
}
if(!(nPushFlags & PUSH_CLIPREGION ))
{
- pLast->setRegion(pTip->getRegion());
- pLast->setRegionActive(pTip->getRegionActive());
+ pLast->setClipPolyPolygon(pTip->getClipPolyPolygon());
+ pLast->setClipPolyPolygonActive(pTip->getClipPolyPolygonActive());
}
if(!(nPushFlags & PUSH_RASTEROP ))
{
@@ -336,11 +344,11 @@ namespace
}
}
}
-
- // execute the pop
- delete maPropertyHolders.back();
- maPropertyHolders.pop_back();
}
+
+ // execute the pop
+ delete maPropertyHolders.back();
+ maPropertyHolders.pop_back();
}
}
@@ -465,25 +473,18 @@ namespace
// the buffer to not delete them in the destructor.
aTargets.clear();
- if(xRetval.hasElements() && rPropertyHolder.getRegionActive())
+ if(xRetval.hasElements() && rPropertyHolder.getClipPolyPolygonActive())
{
- const Region& rRegion = rPropertyHolder.getRegion();
+ const basegfx::B2DPolyPolygon& rClipPolyPolygon = rPropertyHolder.getClipPolyPolygon();
- if(!rRegion.IsEmpty())
+ if(rClipPolyPolygon.count())
{
- basegfx::B2DPolyPolygon aClipPolyPolygon(getB2DPolyPolygonFromRegion(rRegion));
+ const drawinglayer::primitive2d::Primitive2DReference xMask(
+ new drawinglayer::primitive2d::MaskPrimitive2D(
+ rClipPolyPolygon,
+ xRetval));
- if(aClipPolyPolygon.count())
- {
- aClipPolyPolygon.transform(rPropertyHolder.getTransformation());
-
- const drawinglayer::primitive2d::Primitive2DReference xMask(
- new drawinglayer::primitive2d::MaskPrimitive2D(
- aClipPolyPolygon,
- xRetval));
-
- xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1);
- }
+ xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1);
}
}
@@ -943,14 +944,17 @@ namespace
default : // case HATCH_SINGLE :
{
aHatchStyle = drawinglayer::attribute::HATCHSTYLE_SINGLE;
+ break;
}
case HATCH_DOUBLE :
{
aHatchStyle = drawinglayer::attribute::HATCHSTYLE_DOUBLE;
+ break;
}
case HATCH_TRIPLE :
{
aHatchStyle = drawinglayer::attribute::HATCHSTYLE_TRIPLE;
+ break;
}
}
@@ -969,53 +973,56 @@ namespace
a new target for embracing new geometry to the current region
*/
void HandleNewClipRegion(
- const Region* pRegion,
+ const basegfx::B2DPolyPolygon& rClipPolyPolygon,
TargetHolders& rTargetHolders,
PropertyHolders& rPropertyHolders)
{
- const bool bNewActive(pRegion && !pRegion->IsEmpty());
+ const bool bNewActive(rClipPolyPolygon.count());
- // #i108636# The handlig of new ClipRegions was not done as good as possible
- // in the first version of this interpreter; e.g. when a ClipRegion was set
+ // #i108636# The handlig of new ClipPolyPolygons was not done as good as possible
+ // in the first version of this interpreter; e.g. when a ClipPolyPolygon was set
// initially and then using a lot of push/pop actions, the pop always leads
- // to setting a 'new' ClipRegion which indeed is the return to the ClipRegion
+ // to setting a 'new' ClipPolyPolygon which indeed is the return to the ClipPolyPolygon
// of the properties next on the stack.
- // This ClipRegion is identical to the current one, so there is no need to
+ //
+ // This ClipPolyPolygon is identical to the current one, so there is no need to
// create a MaskPrimitive2D containing the up-to-now created primitives, but
// this was done before. While this does not lead to wrong primitive
// representations of the metafile data, it creates unneccesarily expensive
- // representations. Just detecting when no really 'new' ClipRegion gets set
+ // representations. Just detecting when no really 'new' ClipPolyPolygon gets set
// solves the problem.
- if(!rPropertyHolders.Current().getRegionActive() && !bNewActive)
+ if(!rPropertyHolders.Current().getClipPolyPolygonActive() && !bNewActive)
{
- // no active region exchanged by no new one, done
+ // no active ClipPolyPolygon exchanged by no new one, done
return;
}
- if(rPropertyHolders.Current().getRegionActive() && bNewActive)
+ if(rPropertyHolders.Current().getClipPolyPolygonActive() && bNewActive)
{
- // active region and new active region
- if(rPropertyHolders.Current().getRegion() == *pRegion)
+ // active ClipPolyPolygon and new active ClipPolyPolygon
+ if(rPropertyHolders.Current().getClipPolyPolygon() == rClipPolyPolygon)
{
- // new region is the same as the old region, done
+ // new is the same as old, done
return;
}
}
- // Here the old region and the new one are definitively different, maybe
+ // Here the old and the new are definitively different, maybe
// old one and/or new one is not active.
- // Handle deletion of old region.The process evtl. created primitives which
- // belong to this active region. These need to be embedded to a
+ // Handle deletion of old ClipPolyPolygon. The process evtl. created primitives which
+ // belong to this active ClipPolyPolygon. These need to be embedded to a
// MaskPrimitive2D accordingly.
- if(rPropertyHolders.Current().getRegionActive() && rTargetHolders.size() > 1)
+ if(rPropertyHolders.Current().getClipPolyPolygonActive() && rTargetHolders.size() > 1)
{
drawinglayer::primitive2d::Primitive2DSequence aSubContent;
- if(!rPropertyHolders.Current().getRegion().IsEmpty() && rTargetHolders.Current().size())
+ if(rPropertyHolders.Current().getClipPolyPolygon().count()
+ && rTargetHolders.Current().size())
{
- aSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current());
+ aSubContent = rTargetHolders.Current().getPrimitive2DSequence(
+ rPropertyHolders.Current());
}
rTargetHolders.Pop();
@@ -1030,11 +1037,11 @@ namespace
// apply new settings to current properties by setting
// the new region now
- rPropertyHolders.Current().setRegionActive(bNewActive);
+ rPropertyHolders.Current().setClipPolyPolygonActive(bNewActive);
if(bNewActive)
{
- rPropertyHolders.Current().setRegion(*pRegion);
+ rPropertyHolders.Current().setClipPolyPolygon(rClipPolyPolygon);
// prepare new content holder for new active region
rTargetHolders.Push();
@@ -2134,8 +2141,11 @@ namespace
drawinglayer::primitive2d::Primitive2DSequence xSubContent;
{
rTargetHolders.Push();
+ // #i# for sub-Mteafile contents, do start with new, default render state
+ rPropertyHolders.PushDefault();
interpretMetafile(aGDIMetaFile, rTargetHolders, rPropertyHolders, rViewInformation);
xSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current());
+ rPropertyHolders.Pop();
rTargetHolders.Pop();
}
@@ -2424,13 +2434,18 @@ namespace
if(pA->IsClipping())
{
- // new clipping
- HandleNewClipRegion(&pA->GetRegion(), rTargetHolders, rPropertyHolders);
+ // new clipping. Get PolyPolygon and transform with current transformation
+ basegfx::B2DPolyPolygon aNewClipPolyPolygon(getB2DPolyPolygonFromRegion(pA->GetRegion()));
+
+ aNewClipPolyPolygon.transform(rPropertyHolders.Current().getTransformation());
+ HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders);
}
else
{
// end clipping
- HandleNewClipRegion(0, rTargetHolders, rPropertyHolders);
+ const basegfx::B2DPolyPolygon aEmptyPolyPolygon;
+
+ HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders);
}
break;
@@ -2444,49 +2459,60 @@ namespace
if(rRectangle.IsEmpty())
{
// intersect with empty rectangle will always give empty
- // region; start new clipping with empty region
- const Region aNewRegion;
- HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders);
+ // ClipPolyPolygon; start new clipping with empty PolyPolygon
+ const basegfx::B2DPolyPolygon aEmptyPolyPolygon;
+
+ HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders);
}
else
{
- if(rPropertyHolders.Current().getRegionActive())
+ // create transformed ClipRange
+ basegfx::B2DRange aClipRange(
+ rRectangle.Left(), rRectangle.Top(),
+ rRectangle.Right(), rRectangle.Bottom());
+
+ aClipRange.transform(rPropertyHolders.Current().getTransformation());
+
+ if(rPropertyHolders.Current().getClipPolyPolygonActive())
{
- if(rPropertyHolders.Current().getRegion().IsEmpty())
+ if(0 == rPropertyHolders.Current().getClipPolyPolygon().count())
{
- // nothing to do, empty active clip region will stay
+ // nothing to do, empty active clipPolyPolygon will stay
// empty when intersecting
}
else
{
- // AND existing region and new rectangle
+ // AND existing region and new ClipRange
const basegfx::B2DPolyPolygon aOriginalPolyPolygon(
- getB2DPolyPolygonFromRegion(rPropertyHolders.Current().getRegion()));
+ rPropertyHolders.Current().getClipPolyPolygon());
basegfx::B2DPolyPolygon aClippedPolyPolygon;
if(aOriginalPolyPolygon.count())
{
- const basegfx::B2DRange aIntersectRange(
- rRectangle.Left(), rRectangle.Top(),
- rRectangle.Right(), rRectangle.Bottom());
-
aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnRange(
- aOriginalPolyPolygon, aIntersectRange, true, false);
+ aOriginalPolyPolygon,
+ aClipRange,
+ true,
+ false);
}
if(aClippedPolyPolygon != aOriginalPolyPolygon)
{
// start new clipping with intersected region
- const Region aNewRegion(aClippedPolyPolygon);
- HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders);
+ HandleNewClipRegion(
+ aClippedPolyPolygon,
+ rTargetHolders,
+ rPropertyHolders);
}
}
}
else
{
- // start new clipping with rectangle
- const Region aNewRegion(rRectangle);
- HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders);
+ // start new clipping with ClipRange
+ const basegfx::B2DPolyPolygon aNewClipPolyPolygon(
+ basegfx::tools::createPolygonFromRect(aClipRange));
+
+ HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders);
}
}
@@ -2501,50 +2527,48 @@ namespace
if(rNewRegion.IsEmpty())
{
// intersect with empty region will always give empty
- // region; start new clipping with empty region
- const Region aNewRegion;
- HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders);
+ // region; start new clipping with empty PolyPolygon
+ const basegfx::B2DPolyPolygon aEmptyPolyPolygon;
+
+ HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders);
}
else
{
- if(rPropertyHolders.Current().getRegionActive())
+ // get new ClipPolyPolygon, transform it with current transformation
+ basegfx::B2DPolyPolygon aNewClipPolyPolygon(getB2DPolyPolygonFromRegion(rNewRegion));
+ aNewClipPolyPolygon.transform(rPropertyHolders.Current().getTransformation());
+
+ if(rPropertyHolders.Current().getClipPolyPolygonActive())
{
- if(rPropertyHolders.Current().getRegion().IsEmpty())
+ if(0 == rPropertyHolders.Current().getClipPolyPolygon().count())
{
- // nothing to do, empty active clip region will stay empty
+ // nothing to do, empty active clipPolyPolygon will stay empty
// when intersecting with any region
}
else
{
// AND existing and new region
const basegfx::B2DPolyPolygon aOriginalPolyPolygon(
- getB2DPolyPolygonFromRegion(rPropertyHolders.Current().getRegion()));
+ rPropertyHolders.Current().getClipPolyPolygon());
basegfx::B2DPolyPolygon aClippedPolyPolygon;
if(aOriginalPolyPolygon.count())
{
- const basegfx::B2DPolyPolygon aClipPolyPolygon(
- getB2DPolyPolygonFromRegion(rNewRegion));
-
- if(aClipPolyPolygon.count())
- {
- aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
- aOriginalPolyPolygon, aClipPolyPolygon, true, false);
- }
+ aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
+ aOriginalPolyPolygon, aNewClipPolyPolygon, true, false);
}
if(aClippedPolyPolygon != aOriginalPolyPolygon)
{
- // start new clipping with intersected region
- const Region aNewRegion(aClippedPolyPolygon);
- HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders);
+ // start new clipping with intersected ClipPolyPolygon
+ HandleNewClipRegion(aClippedPolyPolygon, rTargetHolders, rPropertyHolders);
}
}
}
else
{
- // start new clipping with new region
- HandleNewClipRegion(&rNewRegion, rTargetHolders, rPropertyHolders);
+ // start new clipping with new ClipPolyPolygon
+ HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders);
}
}
@@ -2555,24 +2579,31 @@ namespace
/** CHECKED, WORKS WELL */
const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*)pAction;
- if(rPropertyHolders.Current().getRegionActive())
+ if(rPropertyHolders.Current().getClipPolyPolygonActive())
{
- if(rPropertyHolders.Current().getRegion().IsEmpty())
+ if(0 == rPropertyHolders.Current().getClipPolyPolygon().count())
{
// nothing to do
}
else
{
- // move using old interface
- Region aRegion(rPropertyHolders.Current().getRegion());
-
const sal_Int32 nHor(pA->GetHorzMove());
const sal_Int32 nVer(pA->GetVertMove());
if(0 != nHor || 0 != nVer)
{
- aRegion.Move(nHor, nVer);
- HandleNewClipRegion(&aRegion, rTargetHolders, rPropertyHolders);
+ // prepare translation, add current transformation
+ basegfx::B2DVector aVector(pA->GetHorzMove(), pA->GetVertMove());
+ aVector *= rPropertyHolders.Current().getTransformation();
+ basegfx::B2DHomMatrix aTransform(
+ basegfx::tools::createTranslateB2DHomMatrix(aVector));
+
+ // transform existing region
+ basegfx::B2DPolyPolygon aClipPolyPolygon(
+ rPropertyHolders.Current().getClipPolyPolygon());
+
+ aClipPolyPolygon.transform(aTransform);
+ HandleNewClipRegion(aClipPolyPolygon, rTargetHolders, rPropertyHolders);
}
}
}
@@ -2777,10 +2808,12 @@ namespace
const bool bRegionMayChange(rPropertyHolders.Current().getPushFlags() & PUSH_CLIPREGION);
const bool bRasterOpMayChange(rPropertyHolders.Current().getPushFlags() & PUSH_RASTEROP);
- if(bRegionMayChange && rPropertyHolders.Current().getRegionActive())
+ if(bRegionMayChange && rPropertyHolders.Current().getClipPolyPolygonActive())
{
// end evtl. clipping
- HandleNewClipRegion(0, rTargetHolders, rPropertyHolders);
+ const basegfx::B2DPolyPolygon aEmptyPolyPolygon;
+
+ HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders);
}
if(bRasterOpMayChange && rPropertyHolders.Current().isRasterOpActive())
@@ -2797,10 +2830,11 @@ namespace
HandleNewRasterOp(rPropertyHolders.Current().getRasterOp(), rTargetHolders, rPropertyHolders);
}
- if(bRegionMayChange && rPropertyHolders.Current().getRegionActive())
+ if(bRegionMayChange && rPropertyHolders.Current().getClipPolyPolygonActive())
{
// start evtl. clipping
- HandleNewClipRegion(&rPropertyHolders.Current().getRegion(), rTargetHolders, rPropertyHolders);
+ HandleNewClipRegion(
+ rPropertyHolders.Current().getClipPolyPolygon(), rTargetHolders, rPropertyHolders);
}
break;
@@ -2948,8 +2982,11 @@ namespace
drawinglayer::primitive2d::Primitive2DSequence xSubContent;
{
rTargetHolders.Push();
+ // #i# for sub-Mteafile contents, do start with new, default render state
+ rPropertyHolders.PushDefault();
interpretMetafile(rContent, rTargetHolders, rPropertyHolders, rViewInformation);
xSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current());
+ rPropertyHolders.Pop();
rTargetHolders.Pop();
}
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index 68ca424cca78..dc954de7bb2a 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -94,6 +94,147 @@
using namespace com::sun::star;
//////////////////////////////////////////////////////////////////////////////
+// #112245# definition for maximum allowed point count due to Metafile target.
+// To be on the safe side with the old tools polygon, use slightly less then
+// the theoretical maximum (bad experiences with tools polygon)
+
+#define MAX_POLYGON_POINT_COUNT_METAFILE (0x0000fff0)
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+ // #112245# helper to split line polygon in half
+ void splitLinePolygon(
+ const basegfx::B2DPolygon& rBasePolygon,
+ basegfx::B2DPolygon& o_aLeft,
+ basegfx::B2DPolygon& o_aRight)
+ {
+ const sal_uInt32 nCount(rBasePolygon.count());
+
+ if(nCount)
+ {
+ const sal_uInt32 nHalfCount((nCount - 1) >> 1);
+
+ o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1);
+ o_aLeft.setClosed(false);
+
+ o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount);
+ o_aRight.setClosed(false);
+
+ if(rBasePolygon.isClosed())
+ {
+ o_aRight.append(rBasePolygon.getB2DPoint(0));
+
+ if(rBasePolygon.areControlPointsUsed())
+ {
+ o_aRight.setControlPoints(
+ o_aRight.count() - 1,
+ rBasePolygon.getPrevControlPoint(0),
+ rBasePolygon.getNextControlPoint(0));
+ }
+ }
+ }
+ else
+ {
+ o_aLeft.clear();
+ o_aRight.clear();
+ }
+ }
+
+ // #112245# helper to evtl. split filled polygons to maximum metafile point count
+ bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon)
+ {
+ bool bRetval(false);
+ const sal_uInt32 nPolyCount(rPolyPolygon.count());
+
+ if(nPolyCount)
+ {
+ basegfx::B2DPolyPolygon aSplitted;
+
+ for(sal_uInt32 a(0); a < nPolyCount; a++)
+ {
+ const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a));
+ const sal_uInt32 nPointCount(aCandidate.count());
+ bool bNeedToSplit(false);
+
+ if(aCandidate.areControlPointsUsed())
+ {
+ // compare with the maximum for bezier curved polygons
+ bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L);
+ }
+ else
+ {
+ // compare with the maximum for simple point polygons
+ bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1);
+ }
+
+ if(bNeedToSplit)
+ {
+ // need to split the partial polygon
+ const basegfx::B2DRange aRange(aCandidate.getB2DRange());
+ const basegfx::B2DPoint aCenter(aRange.getCenter());
+
+ if(aRange.getWidth() > aRange.getHeight())
+ {
+ // clip in left and right
+ const basegfx::B2DPolyPolygon aLeft(
+ basegfx::tools::clipPolygonOnParallelAxis(
+ aCandidate,
+ false,
+ true,
+ aCenter.getX(),
+ false));
+ const basegfx::B2DPolyPolygon aRight(
+ basegfx::tools::clipPolygonOnParallelAxis(
+ aCandidate,
+ false,
+ false,
+ aCenter.getX(),
+ false));
+
+ aSplitted.append(aLeft);
+ aSplitted.append(aRight);
+ }
+ else
+ {
+ // clip in top and bottom
+ const basegfx::B2DPolyPolygon aTop(
+ basegfx::tools::clipPolygonOnParallelAxis(
+ aCandidate,
+ true,
+ true,
+ aCenter.getY(),
+ false));
+ const basegfx::B2DPolyPolygon aBottom(
+ basegfx::tools::clipPolygonOnParallelAxis(
+ aCandidate,
+ true,
+ false,
+ aCenter.getY(),
+ false));
+
+ aSplitted.append(aTop);
+ aSplitted.append(aBottom);
+ }
+ }
+ else
+ {
+ aSplitted.append(aCandidate);
+ }
+ }
+
+ if(aSplitted.count() != nPolyCount)
+ {
+ rPolyPolygon = aSplitted;
+ }
+ }
+
+ return bRetval;
+ }
+} // end of anonymous namespace
+
+//////////////////////////////////////////////////////////////////////////////
namespace drawinglayer
{
@@ -985,14 +1126,12 @@ namespace drawinglayer
const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate);
const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon();
- if(rBasePolygon.count() > (0x0000ffff - 1))
+ if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
{
// #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
// per polygon. If there are more, split the polygon in half and call recursively
- const sal_uInt32 nCount(rBasePolygon.count());
- const sal_uInt32 nHalfCount((nCount - 1) >> 1);
- const basegfx::B2DPolygon aLeft(rBasePolygon, 0, nHalfCount + 1);
- const basegfx::B2DPolygon aRight(rBasePolygon, nHalfCount, nCount - nHalfCount);
+ basegfx::B2DPolygon aLeft, aRight;
+ splitLinePolygon(rBasePolygon, aLeft, aRight);
const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor());
const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor());
@@ -1020,14 +1159,12 @@ namespace drawinglayer
const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate);
const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon();
- if(rBasePolygon.count() > (0x0000ffff - 1))
+ if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
{
// #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
// per polygon. If there are more, split the polygon in half and call recursively
- const sal_uInt32 nCount(rBasePolygon.count());
- const sal_uInt32 nHalfCount((nCount - 1) >> 1);
- const basegfx::B2DPolygon aLeft(rBasePolygon, 0, nHalfCount + 1);
- const basegfx::B2DPolygon aRight(rBasePolygon, nHalfCount, nCount - nHalfCount);
+ basegfx::B2DPolygon aLeft, aRight;
+ splitLinePolygon(rBasePolygon, aLeft, aRight);
const primitive2d::PolygonStrokePrimitive2D aPLeft(
aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute());
const primitive2d::PolygonStrokePrimitive2D aPRight(
@@ -1099,14 +1236,12 @@ namespace drawinglayer
const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate);
const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon();
- if(rBasePolygon.count() > (0x0000ffff - 1))
+ if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1))
{
// #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
// per polygon. If there are more, split the polygon in half and call recursively
- const sal_uInt32 nCount(rBasePolygon.count());
- const sal_uInt32 nHalfCount((nCount - 1) >> 1);
- const basegfx::B2DPolygon aLeft(rBasePolygon, 0, nHalfCount + 1);
- const basegfx::B2DPolygon aRight(rBasePolygon, nHalfCount, nCount - nHalfCount);
+ basegfx::B2DPolygon aLeft, aRight;
+ splitLinePolygon(rBasePolygon, aLeft, aRight);
const attribute::LineStartEndAttribute aEmpty;
const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft(
aLeft,
@@ -1150,16 +1285,26 @@ namespace drawinglayer
case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D :
{
// need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
- SvtGraphicFill* pSvtGraphicFill = 0;
+ const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate);
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
- if(!mnSvtGraphicFillCount)
+ if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
{
- const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate);
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon());
- aLocalPolyPolygon.transform(maCurrentTransformation);
+ // #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(
+ aLocalPolyPolygon,
+ rBitmapCandidate.getFillBitmap());
- if(aLocalPolyPolygon.count())
+ processBasePrimitive2D(aSplitted);
+ }
+ else
+ {
+ SvtGraphicFill* pSvtGraphicFill = 0;
+
+ 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();
@@ -1216,84 +1361,100 @@ namespace drawinglayer
0,
aFillGraphic);
}
- }
- // Do use decomposition; encapsulate with SvtGraphicFill
- impStartSvtGraphicFill(pSvtGraphicFill);
- process(rCandidate.get2DDecomposition(getViewInformation2D()));
- impEndSvtGraphicFill(pSvtGraphicFill);
+ // Do use decomposition; encapsulate with SvtGraphicFill
+ impStartSvtGraphicFill(pSvtGraphicFill);
+ process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ impEndSvtGraphicFill(pSvtGraphicFill);
+ }
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D :
{
// need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END
+ const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
+
+ // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
+ // per polygon. Split polygon until there are less than that
+ while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
+ ;
+
SvtGraphicFill* pSvtGraphicFill = 0;
+ const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
+ aLocalPolyPolygon.transform(maCurrentTransformation);
- if(!mnSvtGraphicFillCount)
+ if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
{
- const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate);
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon());
- aLocalPolyPolygon.transform(maCurrentTransformation);
+ // re-create a VCL hatch as base data
+ SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
- if(aLocalPolyPolygon.count())
+ switch(rFillHatchAttribute.getStyle())
{
- // re-create a VCL hatch as base data
- const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch();
- SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle);
-
- switch(rFillHatchAttribute.getStyle())
+ default: // attribute::HATCHSTYLE_SINGLE :
{
- default: // attribute::HATCHSTYLE_SINGLE :
- {
- eHatch = SvtGraphicFill::hatchSingle;
- break;
- }
- case attribute::HATCHSTYLE_DOUBLE :
- {
- eHatch = SvtGraphicFill::hatchDouble;
- break;
- }
- case attribute::HATCHSTYLE_TRIPLE :
- {
- eHatch = SvtGraphicFill::hatchTriple;
- break;
- }
+ eHatch = SvtGraphicFill::hatchSingle;
+ break;
+ }
+ case attribute::HATCHSTYLE_DOUBLE :
+ {
+ eHatch = SvtGraphicFill::hatchDouble;
+ break;
}
+ case attribute::HATCHSTYLE_TRIPLE :
+ {
+ eHatch = SvtGraphicFill::hatchTriple;
+ break;
+ }
+ }
- SvtGraphicFill::Transform aTransform;
+ SvtGraphicFill::Transform aTransform;
- // scale
- aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
- aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
+ // scale
+ aTransform.matrix[0] *= rFillHatchAttribute.getDistance();
+ aTransform.matrix[4] *= rFillHatchAttribute.getDistance();
- // rotate (was never correct in impgrfll anyways, use correct angle now)
- aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
- aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
- aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
- aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
+ // rotate (was never correct in impgrfll anyways, use correct angle now)
+ aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle());
+ aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle());
+ aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle());
+ aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle());
- pSvtGraphicFill = new SvtGraphicFill(
- PolyPolygon(aLocalPolyPolygon),
- Color(),
- 0.0,
- SvtGraphicFill::fillEvenOdd,
- SvtGraphicFill::fillHatch,
- aTransform,
- false,
- eHatch,
- Color(rFillHatchAttribute.getColor()),
- SvtGraphicFill::gradientLinear,
- Color(),
- Color(),
- 0,
- Graphic());
- }
+ pSvtGraphicFill = new SvtGraphicFill(
+ PolyPolygon(aLocalPolyPolygon),
+ Color(),
+ 0.0,
+ SvtGraphicFill::fillEvenOdd,
+ SvtGraphicFill::fillHatch,
+ aTransform,
+ false,
+ eHatch,
+ Color(rFillHatchAttribute.getColor()),
+ SvtGraphicFill::gradientLinear,
+ Color(),
+ Color(),
+ 0,
+ Graphic());
}
// Do use decomposition; encapsulate with SvtGraphicFill
impStartSvtGraphicFill(pSvtGraphicFill);
- process(rCandidate.get2DDecomposition(getViewInformation2D()));
+
+ // #i111954# do NOT use decomposition, but use direct VCL-command
+ // process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon);
+ const HatchStyle aHatchStyle(
+ attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE :
+ attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE :
+ HATCH_TRIPLE);
+
+ mpOutputDevice->DrawHatch(aToolsPolyPolygon,
+ Hatch(aHatchStyle,
+ Color(rFillHatchAttribute.getColor()),
+ basegfx::fround(rFillHatchAttribute.getDistance()),
+ basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800)));
+
impEndSvtGraphicFill(pSvtGraphicFill);
break;
@@ -1301,13 +1462,18 @@ namespace drawinglayer
case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D :
{
const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate);
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
+
+ // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
+ // per polygon. Split polygon until there are less than that
+ while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
+ ;
// for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END
// it is safest to use the VCL OutputDevice::DrawGradient method which creates those.
// re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon
Gradient aVCLGradient;
impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false);
- basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon());
aLocalPolyPolygon.transform(maCurrentTransformation);
// #i82145# ATM VCL printing of gradients using curved shapes does not work,
@@ -1365,13 +1531,20 @@ namespace drawinglayer
// NO usage of common own gradient randerer, not used ATM for VCL MetaFile, see text above
// RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate));
+
break;
}
case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D :
{
const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate));
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
+
+ // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
+ // per polygon. Split polygon until there are less than that
+ while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
+ ;
+
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
aLocalPolyPolygon.transform(maCurrentTransformation);
// XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
@@ -1433,7 +1606,11 @@ namespace drawinglayer
{
// 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);
+ maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
+ aMask,
+ maClipPolyPolygon,
+ true, // #i106516# we want the inside of aMask, not the outside
+ false);
}
else
{
@@ -1535,6 +1712,13 @@ namespace drawinglayer
// single transparent PolyPolygon identified, use directly
const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
+
+ // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points
+ // per polygon. Split polygon until there are less than that
+ while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon))
+ ;
+
+ // now transform
aLocalPolyPolygon.transform(maCurrentTransformation);
// XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index a1b1393a2fac..6a280fcad95e 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -284,20 +284,37 @@ namespace drawinglayer
if(bAllowUsingDrawTransparent && 1 == rContent.getLength())
{
const primitive2d::Primitive2DReference xReference(rContent[0]);
- const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get());
+ const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get());
- if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID())
+ if(pBasePrimitive)
{
- // single transparent PolyPolygon identified, use directly
- const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
- mpOutputDevice->SetFillColor(Color(aPolygonColor));
- mpOutputDevice->SetLineColor();
-
- basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
- aLocalPolyPolygon.transform(maCurrentTransformation);
-
- mpOutputDevice->DrawTransparent(aLocalPolyPolygon, rUniTransparenceCandidate.getTransparence());
- bDrawTransparentUsed = true;
+ switch(pBasePrimitive->getPrimitive2DID())
+ {
+ case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D:
+ {
+ // single transparent PolyPolygon identified, use directly
+ const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = static_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(pBasePrimitive);
+ OSL_ENSURE(pPoPoColor, "OOps, PrimitiveID and PrimitiveType do not match (!)");
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor()));
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+
+ basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon());
+ aLocalPolyPolygon.transform(maCurrentTransformation);
+
+ mpOutputDevice->DrawTransparent(aLocalPolyPolygon, rUniTransparenceCandidate.getTransparence());
+ bDrawTransparentUsed = true;
+ break;
+ }
+ // #i# need to wait for #i101378# which is in CWS vcl112 to directly paint transparent hairlines
+ //case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D:
+ //{
+ // // single transparent PolygonHairlinePrimitive2D identified, use directly
+ // const primitive2d::PolygonHairlinePrimitive2D* pPoHair = static_cast< const primitive2d::PolygonHairlinePrimitive2D* >(pBasePrimitive);
+ // OSL_ENSURE(pPoHair, "OOps, PrimitiveID and PrimitiveType do not match (!)");
+ // break;
+ //}
+ }
}
}
@@ -469,19 +486,29 @@ namespace drawinglayer
// This is wrong in principle, but looks nicer. This could also be done here directly
// without VCL usage if needed
const primitive2d::FillHatchPrimitive2D& rFillHatchPrimitive = static_cast< const primitive2d::FillHatchPrimitive2D& >(rCandidate);
+ const attribute::FillHatchAttribute& rFillHatchAttributes = rFillHatchPrimitive.getFillHatch();
// create hatch polygon in range size and discrete coordinates
basegfx::B2DRange aHatchRange(rFillHatchPrimitive.getObjectRange());
aHatchRange.transform(maCurrentTransformation);
const basegfx::B2DPolygon aHatchPolygon(basegfx::tools::createPolygonFromRect(aHatchRange));
+ if(rFillHatchAttributes.isFillBackground())
+ {
+ // #i111846# background fill is active; draw fill polygon
+ const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor()));
+
+ mpOutputDevice->SetFillColor(Color(aPolygonColor));
+ mpOutputDevice->SetLineColor();
+ mpOutputDevice->DrawPolygon(aHatchPolygon);
+ }
+
// set hatch line color
const basegfx::BColor aHatchColor(maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor()));
mpOutputDevice->SetFillColor();
mpOutputDevice->SetLineColor(Color(aHatchColor));
// get hatch style
- const attribute::FillHatchAttribute& rFillHatchAttributes = rFillHatchPrimitive.getFillHatch();
HatchStyle eHatchStyle(HATCH_SINGLE);
switch(rFillHatchAttributes.getStyle())
diff --git a/drawinglayer/source/processor3d/shadow3dextractor.cxx b/drawinglayer/source/processor3d/shadow3dextractor.cxx
index 2abbcaa9f83f..9e0c0674ea66 100644
--- a/drawinglayer/source/processor3d/shadow3dextractor.cxx
+++ b/drawinglayer/source/processor3d/shadow3dextractor.cxx
@@ -51,6 +51,25 @@ namespace drawinglayer
{
namespace processor3d
{
+ /// helper to convert from BasePrimitive2DVector to primitive2d::Primitive2DSequence
+ const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequenceFromBasePrimitive2DVector(
+ const BasePrimitive2DVector& rVector) const
+ {
+ const sal_uInt32 nCount(rVector.size());
+ primitive2d::Primitive2DSequence aRetval(nCount);
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ aRetval[a] = rVector[a];
+ }
+
+ // all entries taken over; no need to delete entries, just reset to
+ // mark as empty
+ const_cast< BasePrimitive2DVector& >(rVector).clear();
+
+ return aRetval;
+ }
+
// as tooling, the process() implementation takes over API handling and calls this
// virtual render method when the primitive implementation is BasePrimitive3D-based.
void Shadow3DExtractingProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate)
@@ -64,8 +83,8 @@ namespace drawinglayer
const primitive3d::ShadowPrimitive3D& rPrimitive = static_cast< const primitive3d::ShadowPrimitive3D& >(rCandidate);
// set new target
- primitive2d::Primitive2DSequence aNewSubList;
- primitive2d::Primitive2DSequence* pLastTargetSequence = mpPrimitive2DSequence;
+ BasePrimitive2DVector aNewSubList;
+ BasePrimitive2DVector* pLastTargetSequence = mpPrimitive2DSequence;
mpPrimitive2DSequence = &aNewSubList;
// activate convert
@@ -84,21 +103,26 @@ namespace drawinglayer
mbConvert = bLastConvert;
mpPrimitive2DSequence = pLastTargetSequence;
- // create 2d shadow primitive with result
- const primitive2d::Primitive2DReference xRef(new primitive2d::ShadowPrimitive2D(rPrimitive.getShadowTransform(), rPrimitive.getShadowColor(), aNewSubList));
+ // create 2d shadow primitive with result. This also fetches all entries
+ // from aNewSubList, so there is no need to delete them
+ primitive2d::BasePrimitive2D* pNew = new primitive2d::ShadowPrimitive2D(
+ rPrimitive.getShadowTransform(),
+ rPrimitive.getShadowColor(),
+ getPrimitive2DSequenceFromBasePrimitive2DVector(aNewSubList));
if(basegfx::fTools::more(rPrimitive.getShadowTransparence(), 0.0))
{
// create simpleTransparencePrimitive, add created primitives
- const primitive2d::Primitive2DSequence aNewTransPrimitiveVector(&xRef, 1L);
- const primitive2d::Primitive2DReference xRef2(new primitive2d::UnifiedTransparencePrimitive2D(aNewTransPrimitiveVector, rPrimitive.getShadowTransparence()));
- primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef2);
- }
- else
- {
- // add directly
- primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef);
+ const primitive2d::Primitive2DReference xRef(pNew);
+ const primitive2d::Primitive2DSequence aNewTransPrimitiveVector(&xRef, 1);
+
+ pNew = new primitive2d::UnifiedTransparencePrimitive2D(
+ aNewTransPrimitiveVector,
+ rPrimitive.getShadowTransparence());
}
+
+ mpPrimitive2DSequence->push_back(pNew);
+
break;
}
case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D :
@@ -161,8 +185,10 @@ namespace drawinglayer
if(a2DHairline.count())
{
a2DHairline.transform(getObjectTransformation());
- const primitive2d::Primitive2DReference xRef(new primitive2d::PolygonHairlinePrimitive2D(a2DHairline, maPrimitiveColor));
- primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef);
+ mpPrimitive2DSequence->push_back(
+ new primitive2d::PolygonHairlinePrimitive2D(
+ a2DHairline,
+ maPrimitiveColor));
}
}
break;
@@ -190,8 +216,10 @@ namespace drawinglayer
if(a2DFill.count())
{
a2DFill.transform(getObjectTransformation());
- const primitive2d::Primitive2DReference xRef(new primitive2d::PolyPolygonColorPrimitive2D(a2DFill, maPrimitiveColor));
- primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef);
+ mpPrimitive2DSequence->push_back(
+ new primitive2d::PolyPolygonColorPrimitive2D(
+ a2DFill,
+ maPrimitiveColor));
}
}
break;
@@ -251,6 +279,16 @@ namespace drawinglayer
}
}
+ Shadow3DExtractingProcessor::~Shadow3DExtractingProcessor()
+ {
+ OSL_ENSURE(0 == maPrimitive2DSequence.size(),
+ "OOps, someone used Shadow3DExtractingProcessor, but did not fetch the results (!)");
+ for(sal_uInt32 a(0); a < maPrimitive2DSequence.size(); a++)
+ {
+ delete maPrimitive2DSequence[a];
+ }
+ }
+
basegfx::B2DPolygon Shadow3DExtractingProcessor::impDoShadowProjection(const basegfx::B3DPolygon& rSource)
{
basegfx::B2DPolygon aRetval;
@@ -291,6 +329,12 @@ namespace drawinglayer
return aRetval;
}
+
+ const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequence() const
+ {
+ return getPrimitive2DSequenceFromBasePrimitive2DVector(maPrimitive2DSequence);
+ }
+
} // end of namespace processor3d
} // end of namespace drawinglayer
diff --git a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
index 326b9d392999..b06718d01ccb 100644
--- a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
+++ b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx
@@ -487,7 +487,7 @@ private:
boost::shared_ptr< drawinglayer::texture::GeoTexSvx > mpTransparenceGeoTexSvx;
drawinglayer::attribute::MaterialAttribute3D maMaterial;
basegfx::B3DPolyPolygon maPolyPolygon;
- sal_uInt32 mfCenterZ;
+ double mfCenterZ;
// bitfield
bool mbModulate : 1;