diff options
author | Armin Le Grand <Armin.Le.Grand@Sun.COM> | 2009-11-12 11:26:43 +0100 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@Sun.COM> | 2009-11-12 11:26:43 +0100 |
commit | 15dcfdd7c813c4158a18c52c7ba22c14c7dac996 (patch) | |
tree | 6d144b4da1dacfce5271bdeb76312e01841d5f10 /drawinglayer/source/primitive2d/graphicprimitive2d.cxx | |
parent | 95ccca996e41c0ff9fa70fb5007f06796a98bc1c (diff) |
aw078 #i106541# commited in-between stable version with already advanced metafile decomposition for security reasons
Diffstat (limited to 'drawinglayer/source/primitive2d/graphicprimitive2d.cxx')
-rw-r--r-- | drawinglayer/source/primitive2d/graphicprimitive2d.cxx | 504 |
1 files changed, 470 insertions, 34 deletions
diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx index d5282116d46f..eca68858cbb5 100644 --- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx @@ -207,23 +207,54 @@ namespace ////////////////////////////////////////////////////////////////////////////// +#include <vcl/gradient.hxx> +#include <vcl/pngread.hxx> +#include <vcl/lineinfo.hxx> + namespace drawinglayer { namespace primitive2d { - Primitive2DSequence GraphicPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const + Primitive2DSequence GraphicPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const { Primitive2DSequence aRetval; if(255L != getGraphicAttr().GetTransparency()) { - // get transformed graphic. Suppress rotation and cropping, only filtering is needed - // here (and may be replaced later on). Cropping is handled below as mask primitive (if set) + Primitive2DReference xPrimitive; + + // do not apply mirroring from GraphicAttr to the Metafile by calling + // GetTransformedGraphic, this will try to mirror the Metafile using Scale() + // at the Metafile. This again calls Scale at the single MetaFile actions, + // but this implementation never worked. I reworked that implementations, + // but for security reasons i will try not to use it. + basegfx::B2DHomMatrix aTransform(getTransform()); + + if(getGraphicAttr().IsMirrored()) + { + // content needs mirroring + const bool bHMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_HORZ); + const bool bVMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_VERT); + + // mirror by applying negative scale to the unit primitive and + // applying the object transformation on it. + aTransform = basegfx::tools::createScaleB2DHomMatrix( + bHMirr ? -1.0 : 1.0, + bVMirr ? -1.0 : 1.0); + aTransform.translate( + bHMirr ? 1.0 : 0.0, + bVMirr ? 1.0 : 0.0); + aTransform = getTransform() * aTransform; + } + + // Get transformed graphic. Suppress rotation and cropping, only filtering is needed + // here (and may be replaced later on). Cropping is handled below as mask primitive (if set). + // Also need to suppress mirroring, it is part of the transformation now (see above). GraphicAttr aSuppressGraphicAttr(getGraphicAttr()); - aSuppressGraphicAttr.SetCrop(0L, 0L, 0L, 0L); + aSuppressGraphicAttr.SetCrop(0, 0, 0, 0); aSuppressGraphicAttr.SetRotation(0); - Graphic aTransformedGraphic(getGraphicObject().GetTransformedGraphic(&aSuppressGraphicAttr)); - Primitive2DReference xPrimitive; + aSuppressGraphicAttr.SetMirrorFlags(0); + const Graphic aTransformedGraphic(getGraphicObject().GetTransformedGraphic(&aSuppressGraphicAttr)); switch(aTransformedGraphic.GetType()) { @@ -244,7 +275,7 @@ namespace drawinglayer { animation::AnimationEntryFixed aTime((double)aData.stepTime(a), (double)a / (double)aData.count()); aAnimationLoop.append(aTime); - const Primitive2DReference xRef(new BitmapPrimitive2D(aData.stepBitmapEx(a), getTransform())); + const Primitive2DReference xRef(new BitmapPrimitive2D(aData.stepBitmapEx(a), aTransform)); aBitmapPrimitives[a] = xRef; } @@ -258,7 +289,7 @@ namespace drawinglayer } else { - xPrimitive = Primitive2DReference(new BitmapPrimitive2D(aTransformedGraphic.GetBitmapEx(), getTransform())); + xPrimitive = Primitive2DReference(new BitmapPrimitive2D(aTransformedGraphic.GetBitmapEx(), aTransform)); } break; @@ -267,35 +298,440 @@ namespace drawinglayer case GRAPHIC_GDIMETAFILE : { // create MetafilePrimitive2D - const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile(); - - xPrimitive = Primitive2DReference( - new MetafilePrimitive2D( - getTransform(), - rMetafile)); - - // #i100357# find out if clipping is needed for this primitive. Unfortunately, - // there exist Metafiles who's content is bigger than the proposed PrefSize set - // at them. This is an error, but we need to work around this - const Size aMetaFilePrefSize(rMetafile.GetPrefSize()); - const Size aMetaFileRealSize( - const_cast< GDIMetaFile& >(rMetafile).GetBoundRect( - *Application::GetDefaultDevice()).GetSize()); - - if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth() - || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight()) + static bool bDoTest(false); + + if(bDoTest) + { + GDIMetaFile aMtf; + VirtualDevice aOut; + const basegfx::B2DRange aRange(getB2DRange(rViewInformation)); + const Rectangle aRectangle( + basegfx::fround(aRange.getMinX()), basegfx::fround(aRange.getMinY()), + basegfx::fround(aRange.getMaxX()), basegfx::fround(aRange.getMaxY())); + const Point aOrigin(aRectangle.TopLeft()); + const Fraction aScaleX(aRectangle.getWidth()); + const Fraction aScaleY(aRectangle.getHeight()); + MapMode aMapMode(MAP_100TH_MM, aOrigin, aScaleX, aScaleY); + + Size aDummySize(2, 2); + aOut.SetOutputSizePixel(aDummySize); + aOut.EnableOutput(FALSE); + aOut.SetMapMode(aMapMode); + + aMtf.Clear(); + aMtf.Record(&aOut); + + const Fraction aNeutralFraction(1, 1); + const MapMode aRelativeMapMode( + MAP_RELATIVE, + Point(-aRectangle.Left(), -aRectangle.Top()), + aNeutralFraction, aNeutralFraction); + aOut.SetMapMode(aRelativeMapMode); + + if(false) + { + const sal_Int32 nHor(aRectangle.getWidth() / 4); + const sal_Int32 nVer(aRectangle.getHeight() / 4); + const Rectangle aCenteredRectangle( + aRectangle.Left() + nHor, aRectangle.Top() + nVer, + aRectangle.Right() - nHor, aRectangle.Bottom() - nVer); + aOut.SetClipRegion(aCenteredRectangle); + } + + if(false) + { + const Rectangle aRightRectangle(aRectangle.TopCenter(), aRectangle.BottomRight()); + aOut.IntersectClipRegion(aRightRectangle); + } + + if(false) + { + const Rectangle aRightRectangle(aRectangle.TopCenter(), aRectangle.BottomRight()); + const Rectangle aBottomRectangle(aRectangle.LeftCenter(), aRectangle.BottomRight()); + Region aRegion(aRightRectangle); + aRegion.Intersect(aBottomRectangle); + aOut.IntersectClipRegion(aRegion); + } + + if(false) + { + const sal_Int32 nHor(aRectangle.getWidth() / 10); + const sal_Int32 nVer(aRectangle.getHeight() / 10); + aOut.MoveClipRegion(nHor, nVer); + } + + if(false) + { + Wallpaper aWallpaper(Color(COL_BLACK)); + aOut.DrawWallpaper(aRectangle, aWallpaper); + } + + if(false) + { + Wallpaper aWallpaper(Gradient(GRADIENT_LINEAR, Color(COL_RED), Color(COL_GREEN))); + aOut.DrawWallpaper(aRectangle, aWallpaper); + } + + if(false) + { + SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ); + vcl::PNGReader aPNGReader(aRead); + BitmapEx aBitmapEx(aPNGReader.Read()); + Wallpaper aWallpaper(aBitmapEx); + aOut.DrawWallpaper(aRectangle, aWallpaper); + } + + if(false) + { + const double fHor(aRectangle.getWidth()); + const double fVer(aRectangle.getHeight()); + Color aColor(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)); + + for(sal_uInt32 a(0); a < 5000; a++) + { + const Point aPoint( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + + if(!(a % 3)) + { + aColor = Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)); + } + + aOut.DrawPixel(aPoint, aColor); + } + } + + if(false) + { + const double fHor(aRectangle.getWidth()); + const double fVer(aRectangle.getHeight()); + + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(); + + for(sal_uInt32 a(0); a < 5000; a++) + { + const Point aPoint( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + aOut.DrawPixel(aPoint); + } + } + + if(false) + { + const double fHor(aRectangle.getWidth()); + const double fVer(aRectangle.getHeight()); + + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(); + + Point aStart( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + Point aStop( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + + LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fHor / 50.0)); + bool bUseLineInfo(false); + + for(sal_uInt32 a(0); a < 20; a++) + { + if(!(a%6)) + { + bUseLineInfo = !bUseLineInfo; + } + + if(!(a%4)) + { + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + } + + if(a%3) + { + aStart = aStop; + aStop = Point( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + } + else + { + aStart = Point( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + aStop = Point( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + } + + if(bUseLineInfo) + { + aOut.DrawLine(aStart, aStop, aLineInfo); + } + else + { + aOut.DrawLine(aStart, aStop); + } + } + } + + if(false) + { + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.DrawRect(aRectangle); + } + + if(false) + { + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + const sal_uInt32 nHor(aRectangle.getWidth() / 10); + const sal_uInt32 nVer(aRectangle.getHeight() / 10); + aOut.DrawRect(aRectangle, nHor, nVer); + } + + if(false) + { + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.DrawEllipse(aRectangle); + } + + if(false) + { + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.DrawArc(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter()); + } + + if(false) + { + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.DrawPie(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter()); + } + + if(false) + { + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.DrawChord(aRectangle, aRectangle.TopLeft(), aRectangle.BottomCenter()); + } + + if(false) + { + const double fHor(aRectangle.getWidth()); + const double fVer(aRectangle.getHeight()); + + for(sal_uInt32 b(0); b < 5; b++) + { + const sal_uInt32 nCount(basegfx::fround(rand() * (20 / 32767.0))); + const bool bClose(basegfx::fround(rand() / 32767.0)); + Polygon aPolygon(nCount + (bClose ? 1 : 0)); + + for(sal_uInt32 a(0); a < nCount; a++) + { + const Point aPoint( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + aPolygon[a] = aPoint; + } + + if(bClose) + { + aPolygon[aPolygon.GetSize() - 1] = aPolygon[0]; + } + + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + + if(!(b%2)) + { + const LineInfo aLineInfo(LINE_SOLID, basegfx::fround(fHor / 50.0)); + aOut.DrawPolyLine(aPolygon, aLineInfo); + } + else + { + aOut.DrawPolyLine(aPolygon); + } + } + } + + if(false) + { + const double fHor(aRectangle.getWidth()); + const double fVer(aRectangle.getHeight()); + + for(sal_uInt32 b(0); b < 5; b++) + { + const sal_uInt32 nCount(basegfx::fround(rand() * (20 / 32767.0))); + const bool bClose(basegfx::fround(rand() / 32767.0)); + Polygon aPolygon(nCount + (bClose ? 1 : 0)); + + for(sal_uInt32 a(0); a < nCount; a++) + { + const Point aPoint( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + aPolygon[a] = aPoint; + } + + if(bClose) + { + aPolygon[aPolygon.GetSize() - 1] = aPolygon[0]; + } + + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.DrawPolygon(aPolygon); + } + } + + if(false) + { + const double fHor(aRectangle.getWidth()); + const double fVer(aRectangle.getHeight()); + PolyPolygon aPolyPolygon; + + for(sal_uInt32 b(0); b < 3; b++) + { + const sal_uInt32 nCount(basegfx::fround(rand() * (6 / 32767.0))); + const bool bClose(basegfx::fround(rand() / 32767.0)); + Polygon aPolygon(nCount + (bClose ? 1 : 0)); + + for(sal_uInt32 a(0); a < nCount; a++) + { + const Point aPoint( + aRectangle.Left() + basegfx::fround(rand() * (fHor / 32767.0)), + aRectangle.Top() + basegfx::fround(rand() * (fVer / 32767.0))); + aPolygon[a] = aPoint; + } + + if(bClose) + { + aPolygon[aPolygon.GetSize() - 1] = aPolygon[0]; + } + + aPolyPolygon.Insert(aPolygon); + } + + aOut.SetLineColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.SetFillColor(Color(basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0))); + aOut.DrawPolyPolygon(aPolyPolygon); + } + + if(false) + { + SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ); + vcl::PNGReader aPNGReader(aRead); + BitmapEx aBitmapEx(aPNGReader.Read()); + aOut.DrawBitmapEx(aRectangle.TopLeft(), aBitmapEx); + } + + if(false) + { + SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ); + vcl::PNGReader aPNGReader(aRead); + BitmapEx aBitmapEx(aPNGReader.Read()); + aOut.DrawBitmapEx(aRectangle.TopLeft(), aRectangle.GetSize(), aBitmapEx); + } + + if(false) + { + SvFileStream aRead((const String&)String(ByteString( "c:\\test.png" ), RTL_TEXTENCODING_UTF8), STREAM_READ); + vcl::PNGReader aPNGReader(aRead); + BitmapEx aBitmapEx(aPNGReader.Read()); + const Size aSizePixel(aBitmapEx.GetSizePixel()); + aOut.DrawBitmapEx( + aRectangle.TopLeft(), + aRectangle.GetSize(), + Point(0, 0), + Size(aSizePixel.Width() /2, aSizePixel.Height() / 2), + aBitmapEx); + } + + if(false) + { + const double fHor(aRectangle.getWidth()); + const double fVer(aRectangle.getHeight()); + const Point aPointA( + aRectangle.Left() + basegfx::fround(fHor * 0.2), + aRectangle.Top() + basegfx::fround(fVer * 0.3)); + const Point aPointB( + aRectangle.Left() + basegfx::fround(fHor * 0.2), + aRectangle.Top() + basegfx::fround(fVer * 0.5)); + const Point aPointC( + aRectangle.Left() + basegfx::fround(fHor * 0.2), + aRectangle.Top() + basegfx::fround(fVer * 0.7)); + const String aText(ByteString("Hello, World!"), RTL_TEXTENCODING_UTF8); + + const String aFontName(ByteString("Comic Sans MS"), RTL_TEXTENCODING_UTF8); + Font aFont(aFontName, Size(0, 1000)); + aFont.SetAlign(ALIGN_BASELINE); + aFont.SetColor(COL_RED); + //sal_Int32* pDXArray = new sal_Int32[aText.Len()]; + + aFont.SetOutline(true); + aOut.SetFont(aFont); + aOut.DrawText(aPointA, aText, 0, aText.Len()); + + aFont.SetShadow(true); + aOut.SetFont(aFont); + aOut.DrawText(aPointB, aText, 0, aText.Len()); + + aFont.SetRelief(RELIEF_EMBOSSED); + aOut.SetFont(aFont); + aOut.DrawText(aPointC, aText, 0, aText.Len()); + + //delete pDXArray; + } + + aMtf.Stop(); + aMtf.WindStart(); + aMtf.SetPrefMapMode(MapMode(MAP_100TH_MM)); + aMtf.SetPrefSize(Size(aRectangle.getWidth(), aRectangle.getHeight())); + + xPrimitive = Primitive2DReference( + new MetafilePrimitive2D( + aTransform, + aMtf)); + } + else { - // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon - const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1); - basegfx::B2DPolygon aMaskPolygon( - basegfx::tools::createPolygonFromRect( - basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); - aMaskPolygon.transform(getTransform()); + const Graphic aGraphic(getGraphicObject().GetGraphic()); + const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile(); xPrimitive = Primitive2DReference( - new MaskPrimitive2D( - basegfx::B2DPolyPolygon(aMaskPolygon), - aChildContent)); + new MetafilePrimitive2D( + aTransform, + rMetafile)); + + // #i100357# find out if clipping is needed for this primitive. Unfortunately, + // there exist Metafiles who's content is bigger than the proposed PrefSize set + // at them. This is an error, but we need to work around this + const Size aMetaFilePrefSize(rMetafile.GetPrefSize()); + const Size aMetaFileRealSize( + const_cast< GDIMetaFile& >(rMetafile).GetBoundRect( + *Application::GetDefaultDevice()).GetSize()); + + if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth() + || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight()) + { + // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon + const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1); + basegfx::B2DPolygon aMaskPolygon( + basegfx::tools::createPolygonFromRect( + basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aMaskPolygon.transform(aTransform); + + xPrimitive = Primitive2DReference( + new MaskPrimitive2D( + basegfx::B2DPolyPolygon(aMaskPolygon), + aChildContent)); + } } break; |