1 // tiledAggCanvas.cpp
2 // Context Free
3 // ---------------------
4 // Copyright (C) 2012-2013 John Horigan - john@glyphic.com
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 //
20 // John Horigan can be contacted at john@glyphic.com or at
21 // John Horigan, 1209 Villa St., Mountain View, CA 94041-1123, USA
22 //
23 //
24
25 #include "abstractPngCanvas.h"
26 #include "tiledCanvas.h"
27 #include "makeCFfilename.h"
28 #include <string>
29 #include <iostream>
30 #include <algorithm>
31 #include "prettyint.h"
32
33 using std::cout;
34 using std::endl;
35
36
abstractPngCanvas(const char * outfilename,bool quiet,int width,int height,aggCanvas::PixelFormat pixfmt,bool crop,int frameCount,int variation,bool wallpaper,Renderer * r,int mx,int my)37 abstractPngCanvas::abstractPngCanvas(const char* outfilename, bool quiet, int width, int height,
38 aggCanvas::PixelFormat pixfmt, bool crop, int frameCount,
39 int variation, bool wallpaper, Renderer *r, int mx, int my)
40 : aggCanvas(pixfmt), mOutputFileName(outfilename), mFrameCount(frameCount),
41 mCurrentFrame(1), mVariation(variation), mPixelFormat(pixfmt),
42 mCrop(crop), mQuiet(quiet), mWallpaper(wallpaper), mRenderer(r), mFullWidth(width),
43 mFullHeight(height), mOriginX(0), mOriginY(0)
44 {
45 if (outfilename)
46 mFileName = outfilename;
47 if (wallpaper) {
48 mWidth = r->m_width;
49 mHeight = r->m_height;
50 mFullWidth = width;
51 mFullHeight = height;
52
53 double scalex = static_cast<double>(width) / ( mWidth * mx);
54 double scaley = static_cast<double>(height) / (mHeight * my);
55 double scale = scalex < scaley ? scalex : scaley;
56 mWidth = static_cast<int>(mWidth * scale);
57 mHeight = static_cast<int>(mHeight * scale);
58 } else {
59 mWidth = width;
60 mHeight = height;
61 mFullWidth = mWidth * mx;
62 mFullHeight = mHeight * my;
63 }
64
65 mOriginX = (mFullWidth - mWidth) / 2;
66 mOriginY = (mFullHeight - mHeight) / 2;
67
68 int bpp = BytesPerPixel.at(mPixelFormat);
69 mStride = mFullWidth * bpp;
70 #ifdef _WIN32
71 mStride += ((-mStride) & 3);
72 #endif
73 mData = std::make_unique<unsigned char[]>(mStride * mFullHeight);
74 attach(mData.get() + mOriginY * mStride + mOriginX * bpp, mWidth, mHeight, mStride);
75
76 if (quiet) return;
77 cout << prettyInt(static_cast<unsigned long>(mFullWidth)) << "w x " <<
78 prettyInt(static_cast<unsigned long>(mFullHeight)) << "h pixel image." << endl;
79 cout << "Generating..." << endl;
80 }
81
82 abstractPngCanvas::~abstractPngCanvas() = default;
83
84 void
start(bool clear,const agg::rgba & bk,int width,int height)85 abstractPngCanvas::start(bool clear, const agg::rgba &bk, int width, int height)
86 {
87 if (!mFrameCount && !mQuiet)
88 cout << endl << "Rendering..." << endl;
89
90 aggCanvas::start(clear, bk, width, height);
91 }
92
93 void
end()94 abstractPngCanvas::end()
95 {
96 aggCanvas::end();
97
98 if (mRenderer && mRenderer->m_tiledCanvas) {
99 tileList points = mRenderer->m_tiledCanvas->getTessellation(mFullWidth, mFullHeight,
100 mOriginX, mOriginY, true);
101 std::reverse(points.begin(), points.end()); // could use reverse adapter
102
103 for (auto&& pt: points) {
104 if (pt.x != mOriginX || pt.y != mOriginY)
105 copyImageUnscaled(pt.x, pt.y);
106 }
107
108 }
109
110 std::string name = makeCFfilename(mOutputFileName, mCurrentFrame, mFrameCount,
111 mVariation);
112
113 if (mFrameCount) {
114 output(name.c_str(), mCurrentFrame++);
115 } else {
116 output(name.c_str());
117 }
118 }
119
120 void
copyImageUnscaled(int destx,int desty)121 abstractPngCanvas::copyImageUnscaled(int destx, int desty)
122 {
123 int bpp = BytesPerPixel.at(mPixelFormat);
124 destx *= bpp;
125 int srcx = mOriginX * bpp;
126 int srcy = mOriginY;
127 for (int y = 0; y < mHeight; ++y) {
128 if (y + desty < 0 || y + desty >= mFullHeight) continue;
129 for (int x = 0; x < mWidth * bpp; ++x) {
130 if (destx + x >= 0 && destx + x < mStride)
131 mData[(y + desty) * mStride + destx + x] = mData[(y + srcy) * mStride + srcx + x];
132 }
133 }
134 }
135