885 lines
32 KiB
C++
885 lines
32 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <cppuhelper/bootstrap.hxx>
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
|
#include <com/sun/star/lang/XInitialization.hpp>
|
|
#include <com/sun/star/registry/XSimpleRegistry.hpp>
|
|
#include <com/sun/star/ucb/UniversalContentBroker.hpp>
|
|
|
|
#include <vcl/vclmain.hxx>
|
|
|
|
#include <tools/urlobj.hxx>
|
|
#include <tools/stream.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/pngread.hxx>
|
|
#include <vcl/wrkwin.hxx>
|
|
#include <vcl/virdev.hxx>
|
|
#include <vcl/graphicfilter.hxx>
|
|
#include <vcl/button.hxx>
|
|
#include <vcl/floatwin.hxx>
|
|
#include <basegfx/numeric/ftools.hxx>
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
|
|
#if 0
|
|
# define FIXME_SELF_INTERSECTING_WORKING
|
|
#endif
|
|
|
|
// debugging hook just for us
|
|
SAL_DLLPUBLIC css::uno::Sequence< OUString > ImageTree_getAllImageNames();
|
|
|
|
using namespace css;
|
|
|
|
class DemoBase :
|
|
public WorkWindow // hide OutputDevice if necessary
|
|
{
|
|
public:
|
|
DemoBase() : WorkWindow(NULL, WB_APP | WB_STDWORK)
|
|
{
|
|
}
|
|
OutputDevice &getOutDev() { return *this; }
|
|
};
|
|
|
|
enum RenderStyle {
|
|
RENDER_THUMB, // small view <n> to a page
|
|
RENDER_EXPANDED, // expanded view of this renderer
|
|
};
|
|
|
|
class DemoWin : public DemoBase
|
|
{
|
|
Bitmap maIntroBW;
|
|
BitmapEx maIntro;
|
|
|
|
int mnSegmentsX;
|
|
int mnSegmentsY;
|
|
|
|
struct RenderContext {
|
|
RenderStyle meStyle;
|
|
bool mbVDev;
|
|
DemoWin *mpDemoWin;
|
|
};
|
|
struct RegionRenderer {
|
|
public:
|
|
virtual ~RegionRenderer() {}
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) = 0;
|
|
};
|
|
|
|
std::vector< RegionRenderer * > maRenderers;
|
|
sal_Int32 mnSelectedRenderer;
|
|
|
|
void InitRenderers();
|
|
|
|
public:
|
|
DemoWin() : DemoBase()
|
|
, mnSegmentsX(4)
|
|
, mnSegmentsY(3)
|
|
, mnSelectedRenderer(-1)
|
|
, mpButton(NULL)
|
|
, mpButtonWin(NULL)
|
|
, mnBounceX(1)
|
|
, mnBounceY(1)
|
|
{
|
|
if (!Application::LoadBrandBitmap("intro", maIntro))
|
|
Application::Abort("Failed to load intro image");
|
|
|
|
maIntroBW = maIntro.GetBitmap();
|
|
maIntroBW.Filter(BMP_FILTER_EMBOSS_GREY);
|
|
|
|
InitRenderers();
|
|
}
|
|
|
|
// Bouncing windows on click ...
|
|
PushButton *mpButton;
|
|
FloatingWindow *mpButtonWin;
|
|
AutoTimer maBounce;
|
|
int mnBounceX, mnBounceY;
|
|
DECL_LINK(BounceTimerCb, void *);
|
|
|
|
virtual void MouseButtonDown(const MouseEvent& rMEvt) SAL_OVERRIDE;
|
|
|
|
virtual void Paint(const Rectangle& rRect) SAL_OVERRIDE
|
|
{
|
|
fprintf(stderr, "DemoWin::Paint(%ld,%ld,%ld,%ld)\n", rRect.getX(), rRect.getY(), rRect.getWidth(), rRect.getHeight());
|
|
drawToDevice(getOutDev(), false);
|
|
}
|
|
|
|
static std::vector<Rectangle> partition(OutputDevice &rDev, int nX, int nY)
|
|
{
|
|
Rectangle r;
|
|
std::vector<Rectangle> aRegions;
|
|
|
|
// Make small cleared area for these guys
|
|
Size aSize(rDev.GetOutputSizePixel());
|
|
long nBorderSize = aSize.Width() / 32;
|
|
long nBoxWidth = (aSize.Width() - nBorderSize*(nX+1)) / nX;
|
|
long nBoxHeight = (aSize.Height() - nBorderSize*(nY+1)) / nY;
|
|
for (int y = 0; y < nY; y++)
|
|
{
|
|
for (int x = 0; x < nX; x++)
|
|
{
|
|
r.SetPos(Point(nBorderSize + (nBorderSize + nBoxWidth) * x,
|
|
nBorderSize + (nBorderSize + nBoxHeight) * y));
|
|
r.SetSize(Size(nBoxWidth, nBoxHeight));
|
|
aRegions.push_back(r);
|
|
}
|
|
}
|
|
|
|
return aRegions;
|
|
}
|
|
|
|
static void clearRects(OutputDevice &rDev, std::vector<Rectangle> &rRects)
|
|
{
|
|
for (size_t i = 0; i < rRects.size(); i++)
|
|
{
|
|
// knock up a nice little border
|
|
rDev.SetLineColor(COL_GRAY);
|
|
rDev.SetFillColor(COL_LIGHTGRAY);
|
|
if (i % 2)
|
|
{
|
|
int nBorderSize = rRects[i].GetWidth() / 5;
|
|
rDev.DrawRect(rRects[i], nBorderSize, nBorderSize);
|
|
}
|
|
else
|
|
rDev.DrawRect(rRects[i]);
|
|
}
|
|
}
|
|
|
|
void drawBackground(OutputDevice &rDev, Rectangle r)
|
|
{
|
|
Gradient aGradient;
|
|
aGradient.SetStartColor(COL_BLUE);
|
|
aGradient.SetEndColor(COL_GREEN);
|
|
aGradient.SetStyle(GradientStyle_LINEAR);
|
|
rDev.DrawGradient(r, aGradient);
|
|
}
|
|
|
|
struct DrawLines : public RegionRenderer
|
|
{
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) SAL_OVERRIDE
|
|
{
|
|
if (rCtx.meStyle == RENDER_EXPANDED)
|
|
{
|
|
sal_uInt16 nOldAA = rDev.GetAntialiasing();
|
|
rDev.SetAntialiasing(ANTIALIASING_ENABLE_B2DDRAW);
|
|
|
|
std::vector<Rectangle> aRegions(DemoWin::partition(rDev, 4, 4));
|
|
DemoWin::clearRects(rDev, aRegions);
|
|
|
|
#if 0 // FIXME: get this through to the backend ...
|
|
double nTransparency[] = {
|
|
1.0, 1.0, 1.0, 1.0,
|
|
0.8, 0.8, 0.8, 0.8,
|
|
0.5, 0.5, 0.5, 0.5,
|
|
0.1, 0.1, 0.1, 0.1
|
|
};
|
|
#endif
|
|
drawing::LineCap eLineCaps[] = {
|
|
drawing::LineCap_BUTT, drawing::LineCap_ROUND, drawing::LineCap_SQUARE, drawing::LineCap_BUTT,
|
|
drawing::LineCap_BUTT, drawing::LineCap_ROUND, drawing::LineCap_SQUARE, drawing::LineCap_BUTT,
|
|
drawing::LineCap_BUTT, drawing::LineCap_ROUND, drawing::LineCap_SQUARE, drawing::LineCap_BUTT,
|
|
drawing::LineCap_BUTT, drawing::LineCap_ROUND, drawing::LineCap_SQUARE, drawing::LineCap_BUTT
|
|
};
|
|
::basegfx::B2DLineJoin eJoins[] = {
|
|
basegfx::B2DLINEJOIN_NONE, basegfx::B2DLINEJOIN_MIDDLE, basegfx::B2DLINEJOIN_BEVEL, basegfx::B2DLINEJOIN_MITER,
|
|
basegfx::B2DLINEJOIN_ROUND, basegfx::B2DLINEJOIN_NONE, basegfx::B2DLINEJOIN_MIDDLE, basegfx::B2DLINEJOIN_BEVEL,
|
|
basegfx::B2DLINEJOIN_MITER, basegfx::B2DLINEJOIN_ROUND, basegfx::B2DLINEJOIN_NONE, basegfx::B2DLINEJOIN_MIDDLE,
|
|
basegfx::B2DLINEJOIN_BEVEL, basegfx::B2DLINEJOIN_MITER, basegfx::B2DLINEJOIN_ROUND, basegfx::B2DLINEJOIN_NONE
|
|
};
|
|
double aLineWidths[] = {
|
|
10.0, 15.0, 20.0, 10.0,
|
|
10.0, 15.0, 20.0, 10.0,
|
|
10.0, 15.0, 20.0, 10.0,
|
|
0.1, 1.0, 10.0, 50.0
|
|
};
|
|
for (size_t i = 0; i < aRegions.size(); i++)
|
|
{
|
|
static const struct {
|
|
double nX, nY;
|
|
} aPoints[] = {
|
|
{ 0.2, 0.2 }, { 0.8, 0.3 }, { 0.7, 0.8 }
|
|
};
|
|
rDev.SetLineColor(Color(COL_BLACK));
|
|
basegfx::B2DPolygon aPoly;
|
|
Rectangle aSub(aRegions[i]);
|
|
for (size_t j = 0; j < SAL_N_ELEMENTS(aPoints); j++)
|
|
{
|
|
aPoly.append(basegfx::B2DPoint(aSub.Left() + aSub.GetWidth() * aPoints[j].nX,
|
|
aSub.Top() + aSub.GetHeight() * aPoints[j].nY));
|
|
}
|
|
rDev.DrawPolyLine(aPoly, aLineWidths[i], eJoins[i], eLineCaps[i]);
|
|
|
|
// Half of them not-anti-aliased ..
|
|
if (i > aRegions.size()/2)
|
|
rDev.SetAntialiasing(nOldAA);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rDev.SetFillColor(Color(COL_LIGHTRED));
|
|
rDev.SetLineColor(Color(COL_BLACK));
|
|
rDev.DrawRect(r);
|
|
|
|
for(int i=0; i<r.GetHeight(); i+=15)
|
|
rDev.DrawLine(Point(r.Left(), r.Top()+i), Point(r.Right(), r.Bottom()-i));
|
|
for(int i=0; i<r.GetWidth(); i+=15)
|
|
rDev.DrawLine(Point(r.Left()+i, r.Bottom()), Point(r.Right()-i, r.Top()));
|
|
|
|
// Should draw a white-line across the middle
|
|
Color aLastPixel(COL_WHITE);
|
|
Point aCenter((r.Left() + r.Right())/2 - 4,
|
|
(r.Top() + r.Bottom())/2 - 4);
|
|
for(int i=0; i<8; i++)
|
|
{
|
|
rDev.DrawPixel(aCenter, aLastPixel);
|
|
aLastPixel = rDev.GetPixel(aCenter);
|
|
aCenter.Move(1,1);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
struct DrawText : public RegionRenderer
|
|
{
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &) SAL_OVERRIDE
|
|
{
|
|
rDev.SetTextColor(Color(COL_BLACK));
|
|
vcl::Font aFont(OUString("Times"), Size(0, 25));
|
|
rDev.SetFont(aFont);
|
|
rDev.DrawText(r, OUString("Click any rect to zoom"));
|
|
}
|
|
};
|
|
|
|
struct DrawCheckered : public RegionRenderer
|
|
{
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) SAL_OVERRIDE
|
|
{
|
|
if (rCtx.meStyle == RENDER_EXPANDED)
|
|
{
|
|
std::vector<Rectangle> aRegions(DemoWin::partition(rDev, 2, 2));
|
|
for (size_t i = 0; i < aRegions.size(); i++)
|
|
{
|
|
vcl::Region aRegion;
|
|
Rectangle aSub(aRegions[i]);
|
|
Rectangle aSmaller(aSub);
|
|
aSmaller.Move(10,10);
|
|
aSmaller.setWidth(aSmaller.getWidth()-20);
|
|
aSmaller.setHeight(aSmaller.getHeight()-24);
|
|
switch (i) {
|
|
case 0:
|
|
aRegion = vcl::Region(aSub);
|
|
break;
|
|
case 1:
|
|
aRegion = vcl::Region(aSmaller);
|
|
aRegion.XOr(aSub);
|
|
break;
|
|
case 2:
|
|
{
|
|
Polygon aPoly(aSub);
|
|
aPoly.Rotate(aSub.Center(), 450);
|
|
aPoly.Clip(aSmaller);
|
|
aRegion = vcl::Region(aPoly);
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
tools::PolyPolygon aPolyPoly;
|
|
sal_Int32 nTW = aSub.GetWidth()/6;
|
|
sal_Int32 nTH = aSub.GetHeight()/6;
|
|
Rectangle aTiny(Point(4, 4), Size(nTW*2, nTH*2));
|
|
aPolyPoly.Insert(Polygon(aTiny));
|
|
aTiny.Move(nTW*3, nTH*3);
|
|
aPolyPoly.Insert(Polygon(aTiny));
|
|
aTiny.Move(nTW, nTH);
|
|
aPolyPoly.Insert(Polygon(aTiny));
|
|
|
|
aRegion = vcl::Region(aPolyPoly);
|
|
break;
|
|
}
|
|
} // switch
|
|
rDev.SetClipRegion(aRegion);
|
|
rDev.DrawCheckered(aSub.TopLeft(), aSub.GetSize());
|
|
rDev.SetClipRegion();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rDev.DrawCheckered(r.TopLeft(), r.GetSize());
|
|
}
|
|
}
|
|
};
|
|
|
|
struct DrawPoly : public RegionRenderer
|
|
{
|
|
DrawCheckered maCheckered;
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) SAL_OVERRIDE
|
|
{
|
|
maCheckered.RenderRegion(rDev, r, rCtx);
|
|
|
|
long nDx = r.GetWidth()/20;
|
|
long nDy = r.GetHeight()/20;
|
|
Rectangle aShrunk(r);
|
|
aShrunk.Move(nDx, nDy);
|
|
aShrunk.SetSize(Size(r.GetWidth()-nDx*2,
|
|
r.GetHeight()-nDy*2));
|
|
Polygon aPoly(aShrunk);
|
|
tools::PolyPolygon aPPoly(aPoly);
|
|
rDev.SetLineColor(Color(COL_RED));
|
|
rDev.SetFillColor(Color(COL_RED));
|
|
// This hits the optional 'drawPolyPolygon' code-path
|
|
rDev.DrawTransparent(aPPoly, 64);
|
|
}
|
|
};
|
|
|
|
struct DrawEllipse : public RegionRenderer
|
|
{
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &) SAL_OVERRIDE
|
|
{
|
|
rDev.SetLineColor(Color(COL_RED));
|
|
rDev.SetFillColor(Color(COL_GREEN));
|
|
rDev.DrawEllipse(r);
|
|
}
|
|
};
|
|
|
|
struct DrawGradient : public RegionRenderer
|
|
{
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) SAL_OVERRIDE
|
|
{
|
|
if (rCtx.meStyle == RENDER_EXPANDED)
|
|
{
|
|
std::vector<Rectangle> aRegions(DemoWin::partition(rDev, 5, 4));
|
|
sal_uInt32 nStartCols[] = {
|
|
COL_RED, COL_RED, COL_RED, COL_GREEN, COL_GREEN,
|
|
COL_BLUE, COL_BLUE, COL_BLUE, COL_CYAN, COL_CYAN,
|
|
COL_BLACK, COL_LIGHTGRAY, COL_WHITE, COL_BLUE, COL_CYAN,
|
|
COL_WHITE, COL_WHITE, COL_WHITE, COL_BLACK, COL_BLACK
|
|
};
|
|
sal_uInt32 nEndCols[] = {
|
|
COL_WHITE, COL_WHITE, COL_WHITE, COL_BLACK, COL_BLACK,
|
|
COL_RED, COL_RED, COL_RED, COL_GREEN, COL_GREEN,
|
|
COL_GRAY, COL_GRAY, COL_LIGHTGRAY, COL_LIGHTBLUE, COL_LIGHTCYAN,
|
|
COL_BLUE, COL_BLUE, COL_BLUE, COL_CYAN, COL_CYAN
|
|
};
|
|
GradientStyle eStyles[] = {
|
|
GradientStyle_LINEAR, GradientStyle_AXIAL, GradientStyle_RADIAL, GradientStyle_ELLIPTICAL, GradientStyle_SQUARE,
|
|
GradientStyle_RECT, GradientStyle_FORCE_EQUAL_SIZE, GradientStyle_LINEAR, GradientStyle_RADIAL, GradientStyle_LINEAR,
|
|
GradientStyle_LINEAR, GradientStyle_AXIAL, GradientStyle_RADIAL, GradientStyle_ELLIPTICAL, GradientStyle_SQUARE,
|
|
GradientStyle_RECT, GradientStyle_FORCE_EQUAL_SIZE, GradientStyle_LINEAR, GradientStyle_RADIAL, GradientStyle_LINEAR
|
|
};
|
|
sal_uInt16 nAngles[] = {
|
|
0, 0, 0, 0, 0,
|
|
15, 30, 45, 60, 75,
|
|
90, 120, 135, 160, 180,
|
|
0, 0, 0, 0, 0
|
|
};
|
|
sal_uInt16 nBorders[] = {
|
|
0, 0, 0, 0, 0,
|
|
1, 10, 100, 10, 1,
|
|
0, 0, 0, 0, 0,
|
|
1, 10, 20, 10, 1,
|
|
0, 0, 0, 0, 0
|
|
};
|
|
DemoWin::clearRects(rDev, aRegions);
|
|
assert(aRegions.size() <= SAL_N_ELEMENTS(nStartCols));
|
|
assert(aRegions.size() <= SAL_N_ELEMENTS(nEndCols));
|
|
assert(aRegions.size() <= SAL_N_ELEMENTS(eStyles));
|
|
assert(aRegions.size() <= SAL_N_ELEMENTS(nAngles));
|
|
assert(aRegions.size() <= SAL_N_ELEMENTS(nBorders));
|
|
for (size_t i = 0; i < aRegions.size(); i++)
|
|
{
|
|
Rectangle aSub = aRegions[i];
|
|
Gradient aGradient;
|
|
aGradient.SetStartColor(Color(nStartCols[i]));
|
|
aGradient.SetEndColor(Color(nEndCols[i]));
|
|
aGradient.SetStyle(eStyles[i]);
|
|
aGradient.SetAngle(nAngles[i]);
|
|
aGradient.SetBorder(nBorders[i]);
|
|
rDev.DrawGradient(aSub, aGradient);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Gradient aGradient;
|
|
aGradient.SetStartColor(COL_YELLOW);
|
|
aGradient.SetEndColor(COL_RED);
|
|
// aGradient.SetAngle(45);
|
|
aGradient.SetStyle(GradientStyle_RECT);
|
|
aGradient.SetBorder(r.GetSize().Width()/20);
|
|
rDev.DrawGradient(r, aGradient);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct DrawBitmap : public RegionRenderer
|
|
{
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) SAL_OVERRIDE
|
|
{
|
|
Bitmap aBitmap(rCtx.mpDemoWin->maIntroBW);
|
|
aBitmap.Scale(r.GetSize(), BMP_SCALE_BESTQUALITY);
|
|
rDev.DrawBitmap(r.TopLeft(), aBitmap);
|
|
}
|
|
};
|
|
|
|
struct DrawBitmapEx : public RegionRenderer
|
|
{
|
|
DrawCheckered maCheckered;
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) SAL_OVERRIDE
|
|
{
|
|
maCheckered.RenderRegion(rDev, r, rCtx);
|
|
|
|
BitmapEx aBitmap(rCtx.mpDemoWin->maIntro);
|
|
aBitmap.Scale(r.GetSize(), BMP_SCALE_BESTQUALITY);
|
|
AlphaMask aSemiTransp(aBitmap.GetSizePixel());
|
|
aSemiTransp.Erase(64);
|
|
rDev.DrawBitmapEx(r.TopLeft(), BitmapEx(aBitmap.GetBitmap(),
|
|
aSemiTransp));
|
|
}
|
|
};
|
|
|
|
struct DrawPolyPolygons : public RegionRenderer
|
|
{
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &) SAL_OVERRIDE
|
|
{
|
|
struct {
|
|
double nX, nY;
|
|
} aPoints[] = { { 0.1, 0.1 }, { 0.9, 0.9 },
|
|
#ifdef FIXME_SELF_INTERSECTING_WORKING
|
|
{ 0.9, 0.1 }, { 0.1, 0.9 },
|
|
{ 0.1, 0.1 }
|
|
#else
|
|
{ 0.1, 0.9 }, { 0.5, 0.5 },
|
|
{ 0.9, 0.1 }, { 0.1, 0.1 }
|
|
#endif
|
|
};
|
|
|
|
tools::PolyPolygon aPolyPoly;
|
|
// Render 4x polygons & aggregate into another PolyPolygon
|
|
for (int x = 0; x < 2; x++)
|
|
{
|
|
for (int y = 0; y < 2; y++)
|
|
{
|
|
Rectangle aSubRect(r);
|
|
aSubRect.Move(x * r.GetWidth()/3, y * r.GetHeight()/3);
|
|
aSubRect.SetSize(Size(r.GetWidth()/2, r.GetHeight()/4));
|
|
Polygon aPoly(SAL_N_ELEMENTS(aPoints));
|
|
for (size_t v = 0; v < SAL_N_ELEMENTS(aPoints); v++)
|
|
{
|
|
aPoly.SetPoint(Point(aSubRect.Left() +
|
|
aSubRect.GetWidth() * aPoints[v].nX,
|
|
aSubRect.Top() +
|
|
aSubRect.GetHeight() * aPoints[v].nY),
|
|
v);
|
|
}
|
|
rDev.SetLineColor(Color(COL_YELLOW));
|
|
rDev.SetFillColor(Color(COL_BLACK));
|
|
rDev.DrawPolygon(aPoly);
|
|
|
|
// now move and add to the polypolygon
|
|
aPoly.Move(0, r.GetHeight()/2);
|
|
aPolyPoly.Insert(aPoly);
|
|
}
|
|
}
|
|
rDev.SetLineColor(Color(COL_LIGHTRED));
|
|
rDev.SetFillColor(Color(COL_GREEN));
|
|
rDev.DrawTransparent(aPolyPoly, 50);
|
|
}
|
|
};
|
|
|
|
struct DrawToVirtualDevice : public RegionRenderer
|
|
{
|
|
enum RenderType {
|
|
RENDER_AS_BITMAP,
|
|
RENDER_AS_OUTDEV,
|
|
RENDER_AS_BITMAPEX,
|
|
RENDER_AS_ALPHA_OUTDEV
|
|
};
|
|
|
|
void SizeAndRender(OutputDevice &rDev, Rectangle r, RenderType eType,
|
|
const RenderContext &rCtx)
|
|
{
|
|
VirtualDevice *pNested;
|
|
|
|
if ((int)eType < RENDER_AS_BITMAPEX)
|
|
pNested = new VirtualDevice(rDev);
|
|
else
|
|
pNested = new VirtualDevice(rDev,0,0);
|
|
|
|
pNested->SetOutputSizePixel(r.GetSize());
|
|
Rectangle aWhole(Point(0,0), r.GetSize());
|
|
|
|
// mini me
|
|
rCtx.mpDemoWin->drawToDevice(*pNested, true);
|
|
|
|
if (eType == RENDER_AS_BITMAP)
|
|
{
|
|
Bitmap aBitmap(pNested->GetBitmap(Point(0,0),aWhole.GetSize()));
|
|
rDev.DrawBitmap(r.TopLeft(), aBitmap);
|
|
}
|
|
else if (eType == RENDER_AS_BITMAPEX)
|
|
{
|
|
BitmapEx aBitmapEx(pNested->GetBitmapEx(Point(0,0),aWhole.GetSize()));
|
|
rDev.DrawBitmapEx(r.TopLeft(), aBitmapEx);
|
|
}
|
|
else if (eType == RENDER_AS_OUTDEV ||
|
|
eType == RENDER_AS_ALPHA_OUTDEV)
|
|
{
|
|
rDev.DrawOutDev(r.TopLeft(), r.GetSize(),
|
|
aWhole.TopLeft(), aWhole.GetSize(),
|
|
*pNested);
|
|
}
|
|
delete pNested;
|
|
}
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) SAL_OVERRIDE
|
|
{
|
|
// avoid infinite recursion
|
|
if (rCtx.mbVDev)
|
|
return;
|
|
|
|
if (rCtx.meStyle == RENDER_EXPANDED)
|
|
{
|
|
std::vector<Rectangle> aRegions(DemoWin::partition(rDev, 2, 2));
|
|
DemoWin::clearRects(rDev, aRegions);
|
|
|
|
RenderType eRenderTypes[] = { RENDER_AS_BITMAP, RENDER_AS_OUTDEV,
|
|
RENDER_AS_BITMAPEX, RENDER_AS_ALPHA_OUTDEV };
|
|
for (size_t i = 0; i < aRegions.size(); i++)
|
|
SizeAndRender(rDev, aRegions[i], eRenderTypes[i], rCtx);
|
|
}
|
|
else
|
|
SizeAndRender(rDev, r, RENDER_AS_BITMAP, rCtx);
|
|
}
|
|
};
|
|
|
|
struct DrawIcons : public RegionRenderer
|
|
{
|
|
std::vector<OUString> maIconNames;
|
|
std::vector<BitmapEx> maIcons;
|
|
bool bHasLoadedAll;
|
|
DrawIcons() : bHasLoadedAll(false)
|
|
{
|
|
// a few icons to start with
|
|
const char *pNames[] = {
|
|
"cmd/lc_openurl.png",
|
|
"cmd/lc_newdoc.png",
|
|
"cmd/lc_choosemacro.png",
|
|
"cmd/lc_save.png",
|
|
"cmd/lc_saveas.png",
|
|
"cmd/lc_importdialog.png",
|
|
"cmd/lc_sendmail.png",
|
|
"cmd/lc_editdoc.png",
|
|
"cmd/lc_print.png",
|
|
"cmd/lc_combobox.png",
|
|
"cmd/lc_insertformcombo.png",
|
|
"cmd/lc_printpreview.png",
|
|
"cmd/lc_cut.png",
|
|
"cmd/lc_copy.png",
|
|
"cmd/lc_paste.png",
|
|
"cmd/sc_autopilotmenu.png",
|
|
"cmd/lc_formatpaintbrush.png",
|
|
"cmd/lc_undo.png",
|
|
"cmd/lc_redo.png",
|
|
"cmd/lc_marks.png",
|
|
"cmd/lc_fieldnames.png",
|
|
"cmd/lc_hyperlinkdialog.png",
|
|
};
|
|
for (size_t i = 0; i < SAL_N_ELEMENTS(pNames); i++)
|
|
{
|
|
maIconNames.push_back(OUString::createFromAscii(pNames[i]));
|
|
maIcons.push_back(BitmapEx(maIconNames[i]));
|
|
}
|
|
}
|
|
|
|
void LoadAllImages()
|
|
{
|
|
if (bHasLoadedAll)
|
|
return;
|
|
bHasLoadedAll = true;
|
|
|
|
css::uno::Sequence< OUString > aAllIcons = ImageTree_getAllImageNames();
|
|
for (sal_Int32 i = 0; i < aAllIcons.getLength(); i++)
|
|
{
|
|
maIconNames.push_back(aAllIcons[i]);
|
|
maIcons.push_back(BitmapEx(aAllIcons[i]));
|
|
}
|
|
}
|
|
|
|
void doDrawIcons(OutputDevice &rDev, Rectangle r, bool bExpanded)
|
|
{
|
|
long nMaxH = 0, nVPos = 0;
|
|
Point p(r.TopLeft());
|
|
size_t nToRender = maIcons.size();
|
|
|
|
if (!bExpanded && maIcons.size() > 64)
|
|
nToRender = 64;
|
|
for (size_t i = 0; i < nToRender; i++)
|
|
{
|
|
Size aSize(maIcons[i].GetSizePixel());
|
|
// sAL_DEBUG("Draw icon '" << maIconNames[i] << "'");
|
|
|
|
if (!i % 4)
|
|
rDev.DrawBitmapEx(p, maIcons[i]);
|
|
else
|
|
{
|
|
basegfx::B2DHomMatrix aTransform;
|
|
aTransform.scale(aSize.Width(), aSize.Height());
|
|
switch (i % 4)
|
|
{
|
|
case 2:
|
|
aTransform.shearX((double)((i >> 2) % 8) / 8);
|
|
aTransform.shearY((double)((i >> 4) % 8) / 8);
|
|
break;
|
|
case 3:
|
|
aTransform.translate(-aSize.Width()/2, -aSize.Height()/2);
|
|
aTransform.rotate(i);
|
|
if (i & 0x100)
|
|
{
|
|
aTransform.shearX((double)((i >> 2) % 8) / 8);
|
|
aTransform.shearY((double)((i >> 4) % 8) / 8);
|
|
}
|
|
aTransform.translate(aSize.Width()/2, aSize.Height()/2);
|
|
break;
|
|
default:
|
|
aTransform.translate(-aSize.Width()/2, -aSize.Height()/2);
|
|
aTransform.rotate(2 * F_2PI * i / nToRender);
|
|
aTransform.translate(aSize.Width()/2, aSize.Height()/2);
|
|
break;
|
|
}
|
|
aTransform.translate(p.X(), p.Y());
|
|
rDev.DrawTransformedBitmapEx(aTransform, maIcons[i]);
|
|
}
|
|
|
|
// next position
|
|
p.Move(aSize.Width(), 0);
|
|
if (aSize.Height() > nMaxH)
|
|
nMaxH = aSize.Height();
|
|
if (p.X() >= r.Right()) // wrap to next line
|
|
{
|
|
nVPos += nMaxH;
|
|
nMaxH = 0;
|
|
p = Point(r.Left(), r.Top() + nVPos);
|
|
}
|
|
if (p.Y() >= r.Bottom()) // re-start at top
|
|
{
|
|
p = r.TopLeft();
|
|
nVPos = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &rCtx) SAL_OVERRIDE
|
|
{
|
|
if (rCtx.meStyle == RENDER_EXPANDED)
|
|
{
|
|
LoadAllImages();
|
|
doDrawIcons(rDev, r, true);
|
|
}
|
|
else
|
|
{
|
|
doDrawIcons(rDev, r, false);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct FetchDrawBitmap : public RegionRenderer
|
|
{
|
|
virtual void RenderRegion(OutputDevice &rDev, Rectangle r,
|
|
const RenderContext &) SAL_OVERRIDE
|
|
{
|
|
Bitmap aBitmap(rDev.GetBitmap(Point(0,0),rDev.GetOutputSizePixel()));
|
|
aBitmap.Scale(r.GetSize(), BMP_SCALE_BESTQUALITY);
|
|
rDev.DrawBitmap(r.TopLeft(), aBitmap);
|
|
}
|
|
};
|
|
|
|
void drawToDevice(OutputDevice &rDev, bool bVDev)
|
|
{
|
|
RenderContext aCtx;
|
|
aCtx.mbVDev = bVDev;
|
|
aCtx.mpDemoWin = this;
|
|
|
|
Rectangle aWholeWin(Point(0,0), rDev.GetOutputSizePixel());
|
|
|
|
drawBackground(rDev, aWholeWin);
|
|
|
|
if (!bVDev /* want everything in the vdev */ &&
|
|
mnSelectedRenderer >= 0)
|
|
{
|
|
aCtx.meStyle = RENDER_EXPANDED;
|
|
maRenderers[mnSelectedRenderer]->RenderRegion(rDev, aWholeWin, aCtx);
|
|
}
|
|
else
|
|
{
|
|
aCtx.meStyle = RENDER_THUMB;
|
|
std::vector<Rectangle> aRegions(DemoWin::partition(rDev, mnSegmentsX, mnSegmentsY));
|
|
DemoWin::clearRects(rDev, aRegions);
|
|
for (size_t i = 0; i < maRenderers.size(); i++)
|
|
maRenderers[i]->RenderRegion(rDev, aRegions[i], aCtx);
|
|
}
|
|
}
|
|
};
|
|
|
|
IMPL_LINK_NOARG(DemoWin,BounceTimerCb)
|
|
{
|
|
mpButton->Check(mnBounceX>0);
|
|
mpButton->SetPressed(mnBounceY>0);
|
|
|
|
Point aCur = mpButtonWin->GetPosPixel();
|
|
static const int nMovePix = 10;
|
|
aCur.Move(mnBounceX * nMovePix, mnBounceX * nMovePix);
|
|
Size aWinSize = GetSizePixel();
|
|
if (aCur.X() <= 0 || aCur.X() >= aWinSize.Width())
|
|
mnBounceX *= -1;
|
|
if (aCur.Y() <= 0 || aCur.Y() >= aWinSize.Height())
|
|
mnBounceX *= -1;
|
|
mpButtonWin->SetPosPixel(aCur);
|
|
|
|
// All smoke and mirrors to test sub-region invalidation underneath
|
|
Rectangle aRect(aCur, mpButtonWin->GetSizePixel());
|
|
Invalidate(aRect);
|
|
return 0;
|
|
}
|
|
|
|
void DemoWin::MouseButtonDown(const MouseEvent& rMEvt)
|
|
{
|
|
// click to zoom out
|
|
if (mnSelectedRenderer >= 0)
|
|
{
|
|
mnSelectedRenderer = -1;
|
|
Invalidate();
|
|
return;
|
|
}
|
|
|
|
// click on a region to zoom into it
|
|
std::vector<Rectangle> aRegions(partition(*this, mnSegmentsX, mnSegmentsY));
|
|
for (size_t i = 0; i < aRegions.size(); i++)
|
|
{
|
|
if (aRegions[i].IsInside(rMEvt.GetPosPixel()))
|
|
{
|
|
mnSelectedRenderer = i;
|
|
Invalidate();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// otherwise bounce floating windows
|
|
if (!mpButton)
|
|
{
|
|
mpButtonWin = new FloatingWindow(this);
|
|
mpButton = new PushButton(mpButtonWin);
|
|
mpButton->SetSymbol(SymbolType::HELP);
|
|
mpButton->SetText("PushButton demo");
|
|
mpButton->SetPosSizePixel(Point(0,0), mpButton->GetOptimalSize());
|
|
mpButton->Show();
|
|
mpButtonWin->SetPosSizePixel(Point(0,0), mpButton->GetOptimalSize());
|
|
mpButtonWin->Show();
|
|
mnBounceX = 1; mnBounceX = 1;
|
|
maBounce.SetTimeoutHdl(LINK(this,DemoWin,BounceTimerCb));
|
|
maBounce.SetTimeout(55);
|
|
maBounce.Start();
|
|
}
|
|
else
|
|
{
|
|
maBounce.Stop();
|
|
delete mpButtonWin;
|
|
mpButtonWin = NULL;
|
|
mpButton = NULL;
|
|
}
|
|
}
|
|
|
|
void DemoWin::InitRenderers()
|
|
{
|
|
maRenderers.push_back(new DrawLines());
|
|
maRenderers.push_back(new DrawText());
|
|
maRenderers.push_back(new DrawPoly());
|
|
maRenderers.push_back(new DrawEllipse());
|
|
maRenderers.push_back(new DrawCheckered());
|
|
maRenderers.push_back(new DrawBitmapEx());
|
|
maRenderers.push_back(new DrawBitmap());
|
|
maRenderers.push_back(new DrawGradient());
|
|
maRenderers.push_back(new DrawPolyPolygons());
|
|
maRenderers.push_back(new DrawToVirtualDevice());
|
|
maRenderers.push_back(new DrawIcons());
|
|
maRenderers.push_back(new FetchDrawBitmap());
|
|
}
|
|
|
|
class DemoApp : public Application
|
|
{
|
|
public:
|
|
DemoApp() {}
|
|
|
|
virtual int Main() SAL_OVERRIDE
|
|
{
|
|
try
|
|
{
|
|
DemoWin aMainWin;
|
|
aMainWin.SetText("Interactive VCL demo");
|
|
aMainWin.Show();
|
|
Application::Execute();
|
|
}
|
|
catch (const css::uno::Exception& e)
|
|
{
|
|
SAL_WARN("vcl.app", "Fatal exception: " << e.Message);
|
|
return 1;
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
SAL_WARN("vcl.app", "Fatal exception: " << e.what());
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
protected:
|
|
uno::Reference<lang::XMultiServiceFactory> xMSF;
|
|
void Init() SAL_OVERRIDE
|
|
{
|
|
try
|
|
{
|
|
uno::Reference<uno::XComponentContext> xComponentContext
|
|
= ::cppu::defaultBootstrap_InitialComponentContext();
|
|
xMSF = uno::Reference<lang::XMultiServiceFactory>
|
|
(xComponentContext->getServiceManager(), uno::UNO_QUERY);
|
|
if(!xMSF.is())
|
|
Application::Abort("Bootstrap failure - no service manager");
|
|
|
|
::comphelper::setProcessServiceFactory(xMSF);
|
|
}
|
|
catch (const uno::Exception &e)
|
|
{
|
|
Application::Abort("Bootstrap exception " + e.Message);
|
|
}
|
|
}
|
|
void DeInit() SAL_OVERRIDE
|
|
{
|
|
uno::Reference< lang::XComponent >(
|
|
comphelper::getProcessComponentContext(),
|
|
uno::UNO_QUERY_THROW)-> dispose();
|
|
::comphelper::setProcessServiceFactory(NULL);
|
|
}
|
|
};
|
|
|
|
void vclmain::createApplication()
|
|
{
|
|
static DemoApp aApp;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|