diff options
Diffstat (limited to 'apps/plugins/puzzles/src/printing.c')
-rw-r--r-- | apps/plugins/puzzles/src/printing.c | 280 |
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 | ||
8 | struct puzzle { | 10 | struct 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 | ||
91 | static void get_puzzle_size(document *doc, struct puzzle *pz, | 93 | static 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 | */ |
120 | void document_print(document *doc, drawing *dr) | 122 | int 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 | */ | ||
137 | void document_begin(const document *doc, drawing *dr) | ||
138 | { | ||
139 | print_begin_doc(dr, document_npages(doc)); | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * End a document. | ||
144 | */ | ||
145 | void 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 | */ | ||
153 | void 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 | */ | ||
285 | void 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 | } |