summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/printing.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/printing.c')
-rw-r--r--apps/plugins/puzzles/src/printing.c280
1 files changed, 163 insertions, 117 deletions
diff --git a/apps/plugins/puzzles/src/printing.c b/apps/plugins/puzzles/src/printing.c
index 98fdd841d3..d1a3badaaa 100644
--- a/apps/plugins/puzzles/src/printing.c
+++ b/apps/plugins/puzzles/src/printing.c
@@ -3,6 +3,8 @@
3 * setup and layout. 3 * setup and layout.
4 */ 4 */
5 5
6#include <assert.h>
7
6#include "puzzles.h" 8#include "puzzles.h"
7 9
8struct puzzle { 10struct puzzle {
@@ -88,7 +90,7 @@ void document_add_puzzle(document *doc, const game *game, game_params *par,
88 doc->got_solns = true; 90 doc->got_solns = true;
89} 91}
90 92
91static void get_puzzle_size(document *doc, struct puzzle *pz, 93static void get_puzzle_size(const document *doc, struct puzzle *pz,
92 float *w, float *h, float *scale) 94 float *w, float *h, float *scale)
93{ 95{
94 float ww, hh, ourscale; 96 float ww, hh, ourscale;
@@ -115,133 +117,177 @@ static void get_puzzle_size(document *doc, struct puzzle *pz,
115} 117}
116 118
117/* 119/*
118 * Having accumulated a load of puzzles, actually do the printing. 120 * Calculate the the number of pages for a document.
119 */ 121 */
120void document_print(document *doc, drawing *dr) 122int document_npages(const document *doc)
121{ 123{
122 int ppp; /* puzzles per page */ 124 int ppp; /* puzzles per page */
123 int pages, passes; 125 int pages, passes;
126
127 ppp = doc->pw * doc->ph;
128 pages = (doc->npuzzles + ppp - 1) / ppp;
129 passes = (doc->got_solns ? 2 : 1);
130
131 return pages * passes;
132}
133
134/*
135 * Begin a document.
136 */
137void document_begin(const document *doc, drawing *dr)
138{
139 print_begin_doc(dr, document_npages(doc));
140}
141
142/*
143 * End a document.
144 */
145void document_end(const document *doc, drawing *dr)
146{
147 print_end_doc(dr);
148}
149
150/*
151 * Print a single page of a document.
152 */
153void document_print_page(const document *doc, drawing *dr, int page_nr)
154{
155 int ppp; /* puzzles per page */
156 int pages;
124 int page, pass; 157 int page, pass;
125 int pageno; 158 int pageno;
159 int i, n, offset;
160 float colsum, rowsum;
126 161
127 ppp = doc->pw * doc->ph; 162 ppp = doc->pw * doc->ph;
128 pages = (doc->npuzzles + ppp - 1) / ppp; 163 pages = (doc->npuzzles + ppp - 1) / ppp;
129 passes = (doc->got_solns ? 2 : 1);
130 164
131 print_begin_doc(dr, pages * passes); 165 /* Get the current page, pass, and pageno based on page_nr. */
132 166 if (page_nr < pages) {
133 pageno = 1; 167 page = page_nr;
134 for (pass = 0; pass < passes; pass++) { 168 pass = 0;
135 for (page = 0; page < pages; page++) { 169 }
136 int i, n, offset; 170 else {
137 float colsum, rowsum; 171 assert(doc->got_solns);
138 172 page = page_nr - pages;
139 print_begin_page(dr, pageno); 173 pass = 1;
140 174 }
141 offset = page * ppp; 175 pageno = page_nr + 1;
142 n = min(ppp, doc->npuzzles - offset); 176
143 177 offset = page * ppp;
144 for (i = 0; i < doc->pw; i++) 178 n = min(ppp, doc->npuzzles - offset);
145 doc->colwid[i] = 0; 179
146 for (i = 0; i < doc->ph; i++) 180 print_begin_page(dr, pageno);
147 doc->rowht[i] = 0; 181
148 182 for (i = 0; i < doc->pw; i++)
149 /* 183 doc->colwid[i] = 0;
150 * Lay the page out by computing all the puzzle sizes. 184 for (i = 0; i < doc->ph; i++)
151 */ 185 doc->rowht[i] = 0;
152 for (i = 0; i < n; i++) { 186
153 struct puzzle *pz = doc->puzzles + offset + i; 187 /*
154 int x = i % doc->pw, y = i / doc->pw; 188 * Lay the page out by computing all the puzzle sizes.
155 float w, h, scale; 189 */
156 190 for (i = 0; i < n; i++) {
157 get_puzzle_size(doc, pz, &w, &h, &scale); 191 struct puzzle *pz = doc->puzzles + offset + i;
158 192 int x = i % doc->pw, y = i / doc->pw;
159 /* Update the maximum width/height of this column. */ 193 float w, h, scale;
160 doc->colwid[x] = max(doc->colwid[x], w); 194
161 doc->rowht[y] = max(doc->rowht[y], h); 195 get_puzzle_size(doc, pz, &w, &h, &scale);
162 } 196
163 197 /* Update the maximum width/height of this column. */
164 /* 198 doc->colwid[x] = max(doc->colwid[x], w);
165 * Add up the maximum column/row widths to get the 199 doc->rowht[y] = max(doc->rowht[y], h);
166 * total amount of space used up by puzzles on the 200 }
167 * page. We will use this to compute gutter widths. 201
168 */ 202 /*
169 colsum = 0.0; 203 * Add up the maximum column/row widths to get the
170 for (i = 0; i < doc->pw; i++) 204 * total amount of space used up by puzzles on the
171 colsum += doc->colwid[i]; 205 * page. We will use this to compute gutter widths.
172 rowsum = 0.0; 206 */
173 for (i = 0; i < doc->ph; i++) 207 colsum = 0.0;
174 rowsum += doc->rowht[i]; 208 for (i = 0; i < doc->pw; i++)
175 209 colsum += doc->colwid[i];
176 /* 210 rowsum = 0.0;
177 * Now do the printing. 211 for (i = 0; i < doc->ph; i++)
178 */ 212 rowsum += doc->rowht[i];
179 for (i = 0; i < n; i++) { 213
180 struct puzzle *pz = doc->puzzles + offset + i; 214 /*
181 int x = i % doc->pw, y = i / doc->pw, j; 215 * Now do the printing.
182 float w, h, scale, xm, xc, ym, yc; 216 */
183 int pixw, pixh, tilesize; 217 for (i = 0; i < n; i++) {
184 218 struct puzzle *pz = doc->puzzles + offset + i;
185 if (pass == 1 && !pz->st2) 219 int x = i % doc->pw, y = i / doc->pw, j;
186 continue; /* nothing to do */ 220 float w, h, scale, xm, xc, ym, yc;
187 221 int pixw, pixh, tilesize;
188 /* 222
189 * The total amount of gutter space is the page 223 if (pass == 1 && !pz->st2)
190 * width minus colsum. This is divided into pw+1 224 continue; /* nothing to do */
191 * gutters, so the amount of horizontal gutter 225
192 * space appearing to the left of this puzzle 226 /*
193 * column is 227 * The total amount of gutter space is the page
194 * 228 * width minus colsum. This is divided into pw+1
195 * (width-colsum) * (x+1)/(pw+1) 229 * gutters, so the amount of horizontal gutter
196 * = width * (x+1)/(pw+1) - (colsum * (x+1)/(pw+1)) 230 * space appearing to the left of this puzzle
197 */ 231 * column is
198 xm = (float)(x+1) / (doc->pw + 1); 232 *
199 xc = -xm * colsum; 233 * (width-colsum) * (x+1)/(pw+1)
200 /* And similarly for y. */ 234 * = width * (x+1)/(pw+1) - (colsum * (x+1)/(pw+1))
201 ym = (float)(y+1) / (doc->ph + 1); 235 */
202 yc = -ym * rowsum; 236 xm = (float)(x+1) / (doc->pw + 1);
203 237 xc = -xm * colsum;
204 /* 238 /* And similarly for y. */
205 * However, the amount of space to the left of this 239 ym = (float)(y+1) / (doc->ph + 1);
206 * puzzle isn't just gutter space: we must also 240 yc = -ym * rowsum;
207 * count the widths of all the previous columns. 241
208 */ 242 /*
209 for (j = 0; j < x; j++) 243 * However, the amount of space to the left of this
210 xc += doc->colwid[j]; 244 * puzzle isn't just gutter space: we must also
211 /* And similarly for rows. */ 245 * count the widths of all the previous columns.
212 for (j = 0; j < y; j++) 246 */
213 yc += doc->rowht[j]; 247 for (j = 0; j < x; j++)
214 248 xc += doc->colwid[j];
215 /* 249 /* And similarly for rows. */
216 * Now we adjust for this _specific_ puzzle, which 250 for (j = 0; j < y; j++)
217 * means centring it within the cell we've just 251 yc += doc->rowht[j];
218 * computed. 252
219 */ 253 /*
220 get_puzzle_size(doc, pz, &w, &h, &scale); 254 * Now we adjust for this _specific_ puzzle, which
221 xc += (doc->colwid[x] - w) / 2; 255 * means centring it within the cell we've just
222 yc += (doc->rowht[y] - h) / 2; 256 * computed.
223 257 */
224 /* 258 get_puzzle_size(doc, pz, &w, &h, &scale);
225 * And now we know where and how big we want to 259 xc += (doc->colwid[x] - w) / 2;
226 * print the puzzle, just go ahead and do so. For 260 yc += (doc->rowht[y] - h) / 2;
227 * the moment I'll pick a standard pixel tile size 261
228 * of 512. 262 /*
229 * 263 * And now we know where and how big we want to
230 * (FIXME: would it be better to pick this value 264 * print the puzzle, just go ahead and do so. For
231 * with reference to the printer resolution? Or 265 * the moment I'll pick a standard pixel tile size
232 * permit each game to choose its own?) 266 * of 512.
233 */ 267 *
234 tilesize = 512; 268 * (FIXME: would it be better to pick this value
235 pz->game->compute_size(pz->par, tilesize, &pixw, &pixh); 269 * with reference to the printer resolution? Or
236 print_begin_puzzle(dr, xm, xc, ym, yc, pixw, pixh, w, scale); 270 * permit each game to choose its own?)
237 pz->game->print(dr, pass == 0 ? pz->st : pz->st2, tilesize); 271 */
238 print_end_puzzle(dr); 272 tilesize = 512;
239 } 273 pz->game->compute_size(pz->par, tilesize, &pixw, &pixh);
240 274 print_begin_puzzle(dr, xm, xc, ym, yc, pixw, pixh, w, scale);
241 print_end_page(dr, pageno); 275 pz->game->print(dr, pass == 0 ? pz->st : pz->st2, tilesize);
242 pageno++; 276 print_end_puzzle(dr);
243 }
244 } 277 }
245 278
279 print_end_page(dr, pageno);
280}
281
282/*
283 * Having accumulated a load of puzzles, actually do the printing.
284 */
285void document_print(const document *doc, drawing *dr)
286{
287 int page, pages;
288 pages = document_npages(doc);
289 print_begin_doc(dr, pages);
290 for (page = 0; page < pages; page++)
291 document_print_page(doc, dr, page);
246 print_end_doc(dr); 292 print_end_doc(dr);
247} 293}