blob: 3b47d8df8634d7cb6dc013387e4b706f03d7c703 [file] [log] [blame]
/**************************************************************
*
* 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