| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_drawinglayer.hxx" |
| |
| #include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx> |
| #include <drawinglayer/animation/animationtiming.hxx> |
| #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/animatedprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/metafileprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/transformprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/maskprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> |
| #include <basegfx/polygon/b2dpolygon.hxx> |
| #include <basegfx/polygon/b2dpolygontools.hxx> |
| #include <basegfx/numeric/ftools.hxx> |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // helper class for animated graphics |
| |
| #include <vcl/animate.hxx> |
| #include <vcl/graph.hxx> |
| #include <vcl/virdev.hxx> |
| #include <vcl/svapp.hxx> |
| #include <vcl/metaact.hxx> |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // includes for testing MetafilePrimitive2D::create2DDecomposition |
| |
| // this switch defines if the test code is included or not |
| #undef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE |
| |
| #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE |
| #include <vcl/gradient.hxx> |
| #include <vcl/pngread.hxx> |
| #include <vcl/lineinfo.hxx> |
| #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| namespace |
| { |
| struct animationStep |
| { |
| BitmapEx maBitmapEx; |
| sal_uInt32 mnTime; |
| }; |
| |
| class animatedBitmapExPreparator |
| { |
| ::Animation maAnimation; |
| ::std::vector< animationStep > maSteps; |
| |
| sal_uInt32 generateStepTime(sal_uInt32 nIndex) const; |
| |
| public: |
| animatedBitmapExPreparator(const Graphic& rGraphic); |
| |
| sal_uInt32 count() const { return maSteps.size(); } |
| sal_uInt32 loopCount() const { return (sal_uInt32)maAnimation.GetLoopCount(); } |
| sal_uInt32 stepTime(sal_uInt32 a) const { return maSteps[a].mnTime; } |
| const BitmapEx& stepBitmapEx(sal_uInt32 a) const { return maSteps[a].maBitmapEx; } |
| }; |
| |
| sal_uInt32 animatedBitmapExPreparator::generateStepTime(sal_uInt32 nIndex) const |
| { |
| const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(nIndex)); |
| sal_uInt32 nWaitTime(rAnimBitmap.nWait * 10); |
| |
| // #115934# |
| // Take care of special value for MultiPage TIFFs. ATM these shall just |
| // show their first page. Later we will offer some switching when object |
| // is selected. |
| if(ANIMATION_TIMEOUT_ON_CLICK == rAnimBitmap.nWait) |
| { |
| // ATM the huge value would block the timer, so |
| // use a long time to show first page (whole day) |
| nWaitTime = 100 * 60 * 60 * 24; |
| } |
| |
| // Bad trap: There are animated gifs with no set WaitTime (!). |
| // In that case use a default value. |
| if(0L == nWaitTime) |
| { |
| nWaitTime = 100L; |
| } |
| |
| return nWaitTime; |
| } |
| |
| animatedBitmapExPreparator::animatedBitmapExPreparator(const Graphic& rGraphic) |
| : maAnimation(rGraphic.GetAnimation()) |
| { |
| OSL_ENSURE(GRAPHIC_BITMAP == rGraphic.GetType() && rGraphic.IsAnimated(), "animatedBitmapExPreparator: graphic is not animated (!)"); |
| |
| // #128539# secure access to Animation, looks like there exist animated GIFs out there |
| // with a step count of zero |
| if(maAnimation.Count()) |
| { |
| VirtualDevice aVirtualDevice(*Application::GetDefaultDevice()); |
| VirtualDevice aVirtualDeviceMask(*Application::GetDefaultDevice(), 1L); |
| |
| // Prepare VirtualDevices and their states |
| aVirtualDevice.EnableMapMode(sal_False); |
| aVirtualDeviceMask.EnableMapMode(sal_False); |
| aVirtualDevice.SetOutputSizePixel(maAnimation.GetDisplaySizePixel()); |
| aVirtualDeviceMask.SetOutputSizePixel(maAnimation.GetDisplaySizePixel()); |
| aVirtualDevice.Erase(); |
| aVirtualDeviceMask.Erase(); |
| |
| for(sal_uInt16 a(0L); a < maAnimation.Count(); a++) |
| { |
| animationStep aNextStep; |
| aNextStep.mnTime = generateStepTime(a); |
| |
| // prepare step |
| const AnimationBitmap& rAnimBitmap = maAnimation.Get(sal_uInt16(a)); |
| |
| switch(rAnimBitmap.eDisposal) |
| { |
| case DISPOSE_NOT: |
| { |
| aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); |
| Bitmap aMask = rAnimBitmap.aBmpEx.GetMask(); |
| |
| if(aMask.IsEmpty()) |
| { |
| const Point aEmpty; |
| const Rectangle aRect(aEmpty, aVirtualDeviceMask.GetOutputSizePixel()); |
| const Wallpaper aWallpaper(COL_BLACK); |
| aVirtualDeviceMask.DrawWallpaper(aRect, aWallpaper); |
| } |
| else |
| { |
| BitmapEx aExpandVisibilityMask = BitmapEx(aMask, aMask); |
| aVirtualDeviceMask.DrawBitmapEx(rAnimBitmap.aPosPix, aExpandVisibilityMask); |
| } |
| |
| break; |
| } |
| case DISPOSE_BACK: |
| { |
| // #i70772# react on no mask, for primitives, too. |
| const Bitmap aMask(rAnimBitmap.aBmpEx.GetMask()); |
| const Bitmap aContent(rAnimBitmap.aBmpEx.GetBitmap()); |
| |
| aVirtualDeviceMask.Erase(); |
| aVirtualDevice.DrawBitmap(rAnimBitmap.aPosPix, aContent); |
| |
| if(aMask.IsEmpty()) |
| { |
| const Rectangle aRect(rAnimBitmap.aPosPix, aContent.GetSizePixel()); |
| aVirtualDeviceMask.SetFillColor(COL_BLACK); |
| aVirtualDeviceMask.SetLineColor(); |
| aVirtualDeviceMask.DrawRect(aRect); |
| } |
| else |
| { |
| aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, aMask); |
| } |
| |
| break; |
| } |
| case DISPOSE_FULL: |
| { |
| aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); |
| break; |
| } |
| case DISPOSE_PREVIOUS : |
| { |
| aVirtualDevice.DrawBitmapEx(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx); |
| aVirtualDeviceMask.DrawBitmap(rAnimBitmap.aPosPix, rAnimBitmap.aBmpEx.GetMask()); |
| break; |
| } |
| } |
| |
| // create BitmapEx |
| Bitmap aMainBitmap = aVirtualDevice.GetBitmap(Point(), aVirtualDevice.GetOutputSizePixel()); |
| #if defined(MACOSX) |
| AlphaMask aMaskBitmap( aVirtualDeviceMask.GetBitmap( Point(), aVirtualDeviceMask.GetOutputSizePixel())); |
| #else |
| Bitmap aMaskBitmap = aVirtualDeviceMask.GetBitmap( Point(), aVirtualDeviceMask.GetOutputSizePixel()); |
| #endif |
| aNextStep.maBitmapEx = BitmapEx(aMainBitmap, aMaskBitmap); |
| |
| // add to vector |
| maSteps.push_back(aNextStep); |
| } |
| } |
| } |
| } // end of anonymous namespace |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| namespace drawinglayer |
| { |
| namespace primitive2d |
| { |
| Primitive2DSequence create2DDecompositionOfGraphic( |
| const Graphic& rGraphic, |
| const basegfx::B2DHomMatrix& rTransform) |
| { |
| Primitive2DSequence aRetval; |
| |
| switch(rGraphic.GetType()) |
| { |
| case GRAPHIC_BITMAP : |
| { |
| if(rGraphic.IsAnimated()) |
| { |
| // prepare animation data |
| animatedBitmapExPreparator aData(rGraphic); |
| |
| if(aData.count()) |
| { |
| // create sub-primitives for animated bitmap and the needed animation loop |
| animation::AnimationEntryLoop aAnimationLoop(aData.loopCount() ? aData.loopCount() : 0xffff); |
| Primitive2DSequence aBitmapPrimitives(aData.count()); |
| |
| for(sal_uInt32 a(0); a < aData.count(); a++) |
| { |
| animation::AnimationEntryFixed aTime((double)aData.stepTime(a), (double)a / (double)aData.count()); |
| aAnimationLoop.append(aTime); |
| aBitmapPrimitives[a] = new BitmapPrimitive2D( |
| aData.stepBitmapEx(a), |
| rTransform); |
| } |
| |
| // prepare animation list |
| animation::AnimationEntryList aAnimationList; |
| aAnimationList.append(aAnimationLoop); |
| |
| // create and add animated switch primitive |
| aRetval.realloc(1); |
| aRetval[0] = new AnimatedSwitchPrimitive2D( |
| aAnimationList, |
| aBitmapPrimitives, |
| false); |
| } |
| } |
| else if(rGraphic.getSvgData().get()) |
| { |
| // embedded Svg fill, create embed transform |
| const basegfx::B2DRange& rSvgRange(rGraphic.getSvgData()->getRange()); |
| |
| if(basegfx::fTools::more(rSvgRange.getWidth(), 0.0) && basegfx::fTools::more(rSvgRange.getHeight(), 0.0)) |
| { |
| // translate back to origin, scale to unit coordinates |
| basegfx::B2DHomMatrix aEmbedSvg( |
| basegfx::tools::createTranslateB2DHomMatrix( |
| -rSvgRange.getMinX(), |
| -rSvgRange.getMinY())); |
| |
| aEmbedSvg.scale( |
| 1.0 / rSvgRange.getWidth(), |
| 1.0 / rSvgRange.getHeight()); |
| |
| // apply created object transformation |
| aEmbedSvg = rTransform * aEmbedSvg; |
| |
| // add Svg primitives embedded |
| aRetval.realloc(1); |
| aRetval[0] = new TransformPrimitive2D( |
| aEmbedSvg, |
| rGraphic.getSvgData()->getPrimitive2DSequence()); |
| } |
| } |
| else |
| { |
| aRetval.realloc(1); |
| aRetval[0] = new BitmapPrimitive2D( |
| rGraphic.GetBitmapEx(), |
| rTransform); |
| } |
| |
| break; |
| } |
| |
| case GRAPHIC_GDIMETAFILE : |
| { |
| #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE |
| static bool bDoTest(false); |
| |
| if(bDoTest) |
| { |
| // All this is/was test code for testing MetafilePrimitive2D::create2DDecomposition |
| // extensively. It may be needed again when diverse actions need debugging, so i leave |
| // it in here, but take it out using USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE. |
| // Use it by compiling with the code, insert any DrawObject, convert to Metafile. The |
| // debugger will then stop here (when breakpoint set, of course). You may enter single |
| // parts of actions and/or change to true what You want to check. |
| 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; |
| } |
| |
| 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); |
| |
| aOut.SetFont(aFont); |
| const sal_Int32 nWidth(aOut.GetTextWidth(aText, 0, aText.Len())); |
| aOut.DrawText(aPointA, aText, 0, aText.Len()); |
| aOut.DrawTextLine(aPointA, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE); |
| aOut.DrawTextLine(aPointB, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE); |
| aOut.DrawTextLine(aPointC, nWidth, STRIKEOUT_SINGLE, UNDERLINE_SINGLE, UNDERLINE_SMALLWAVE); |
| } |
| |
| aMtf.Stop(); |
| aMtf.WindStart(); |
| aMtf.SetPrefMapMode(MapMode(MAP_100TH_MM)); |
| aMtf.SetPrefSize(Size(aRectangle.getWidth(), aRectangle.getHeight())); |
| |
| aRetval.realloc(1); |
| aRetval[0] = new MetafilePrimitive2D( |
| rTransform, |
| aMtf); |
| } |
| else |
| { |
| #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE |
| // create MetafilePrimitive2D |
| const GDIMetaFile& rMetafile = rGraphic.GetGDIMetaFile(); |
| |
| aRetval.realloc(1); |
| aRetval[0] = new MetafilePrimitive2D( |
| rTransform, |
| 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 |
| basegfx::B2DPolygon aMaskPolygon(basegfx::tools::createUnitPolygon()); |
| aMaskPolygon.transform(rTransform); |
| |
| // #124073# the clde below was compiler-dependent. Normally, |
| // a compiler will |
| // - alloc mem |
| // - ececute the constructor |
| // - do the assignment |
| // but the mac compiler does alloc-assign-constructor, thus |
| // modifying aRetval[0] befure aRetval gets used in the |
| // constructor. This creates an endless loop in the primitive |
| // stack. Thus do it the safe way. |
| // |
| // aRetval[0] = new MaskPrimitive2D( |
| // basegfx::B2DPolyPolygon(aMaskPolygon), |
| // aRetval); |
| MaskPrimitive2D* pMaskPrimitive2D = new MaskPrimitive2D( |
| basegfx::B2DPolyPolygon(aMaskPolygon), |
| aRetval); |
| aRetval[0] = pMaskPrimitive2D; |
| } |
| #ifdef USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE |
| } |
| #endif // USE_DEBUG_CODE_TO_TEST_METAFILE_DECOMPOSE |
| |
| break; |
| } |
| |
| default: |
| { |
| // nothing to create |
| break; |
| } |
| } |
| |
| return aRetval; |
| } |
| } // end of namespace primitive2d |
| } // end of namespace drawinglayer |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| namespace drawinglayer |
| { |
| namespace primitive2d |
| { |
| Primitive2DSequence create2DColorModifierEmbeddingsAsNeeded( |
| const Primitive2DSequence& rChildren, |
| GraphicDrawMode aGraphicDrawMode, |
| double fLuminance, |
| double fContrast, |
| double fRed, |
| double fGreen, |
| double fBlue, |
| double fGamma, |
| bool bInvert) |
| { |
| Primitive2DSequence aRetval; |
| |
| if(!rChildren.getLength()) |
| { |
| // no child content, done |
| return aRetval; |
| } |
| |
| // set child content as retval; that is what will be used as child content in all |
| // embeddings from here |
| aRetval = rChildren; |
| |
| if(GRAPHICDRAWMODE_WATERMARK == aGraphicDrawMode) |
| { |
| // this is solved by applying fixed values additionally to luminance |
| // and contrast, do it here and reset DrawMode to GRAPHICDRAWMODE_STANDARD |
| // original in svtools uses: |
| // #define WATERMARK_LUM_OFFSET 50
|
| // #define WATERMARK_CON_OFFSET -70
|
| fLuminance = basegfx::clamp(fLuminance + 0.5, -1.0, 1.0);
|
| fContrast = basegfx::clamp(fContrast - 0.7, -1.0, 1.0);
|
| aGraphicDrawMode = GRAPHICDRAWMODE_STANDARD;
|
| } |
| |
| // DrawMode (GRAPHICDRAWMODE_WATERMARK already handled) |
| switch(aGraphicDrawMode) |
| { |
| case GRAPHICDRAWMODE_GREYS: |
| { |
| // convert to grey |
| const Primitive2DReference aPrimitiveGrey( |
| new ModifiedColorPrimitive2D( |
| aRetval, |
| basegfx::BColorModifierSharedPtr( |
| new basegfx::BColorModifier_gray()))); |
| |
| aRetval = Primitive2DSequence(&aPrimitiveGrey, 1); |
| break; |
| } |
| case GRAPHICDRAWMODE_MONO: |
| { |
| // convert to mono (black/white with threshold 0.5) |
| const Primitive2DReference aPrimitiveBlackAndWhite( |
| new ModifiedColorPrimitive2D( |
| aRetval, |
| basegfx::BColorModifierSharedPtr( |
| new basegfx::BColorModifier_black_and_white(0.5)))); |
| |
| aRetval = Primitive2DSequence(&aPrimitiveBlackAndWhite, 1); |
| break; |
| } |
| case GRAPHICDRAWMODE_WATERMARK: |
| { |
| OSL_ENSURE(false, "OOps, GRAPHICDRAWMODE_WATERMARK should already be handled (see above)"); |
| // fallthrough intended |
| } |
| default: // case GRAPHICDRAWMODE_STANDARD: |
| { |
| // nothing to do |
| break; |
| } |
| } |
| |
| // mnContPercent, mnLumPercent, mnRPercent, mnGPercent, mnBPercent |
| // handled in a single call |
| if(!basegfx::fTools::equalZero(fLuminance) |
| || !basegfx::fTools::equalZero(fContrast) |
| || !basegfx::fTools::equalZero(fRed) |
| || !basegfx::fTools::equalZero(fGreen) |
| || !basegfx::fTools::equalZero(fBlue)) |
| { |
| const Primitive2DReference aPrimitiveRGBLuminannceContrast( |
| new ModifiedColorPrimitive2D( |
| aRetval, |
| basegfx::BColorModifierSharedPtr( |
| new basegfx::BColorModifier_RGBLuminanceContrast( |
| fRed, |
| fGreen, |
| fBlue, |
| fLuminance, |
| fContrast)))); |
| |
| aRetval = Primitive2DSequence(&aPrimitiveRGBLuminannceContrast, 1); |
| } |
| |
| // gamma (boolean) |
| if(!basegfx::fTools::equal(fGamma, 1.0)) |
| { |
| const Primitive2DReference aPrimitiveGamma( |
| new ModifiedColorPrimitive2D( |
| aRetval, |
| basegfx::BColorModifierSharedPtr( |
| new basegfx::BColorModifier_gamma( |
| fGamma)))); |
| |
| aRetval = Primitive2DSequence(&aPrimitiveGamma, 1); |
| } |
| |
| // invert (boolean) |
| if(bInvert) |
| { |
| const Primitive2DReference aPrimitiveInvert( |
| new ModifiedColorPrimitive2D( |
| aRetval, |
| basegfx::BColorModifierSharedPtr( |
| new basegfx::BColorModifier_invert()))); |
| |
| aRetval = Primitive2DSequence(&aPrimitiveInvert, 1); |
| } |
| |
| return aRetval; |
| } |
| |
| } // end of namespace primitive2d |
| } // end of namespace drawinglayer |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // eof |