Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
printing.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011 Henrik Andersson.
4 Copyright (C) 2010, 2012 johannes hanika.
5 Copyright (C) 2012 Richard Wonka.
6 Copyright (C) 2013, 2019-2021 Pascal Obry.
7 Copyright (C) 2014-2015 Jérémy Rosen.
8 Copyright (C) 2014, 2016 Tobias Ellinghaus.
9 Copyright (C) 2016 Roman Lebedev.
10 Copyright (C) 2022 Martin Bařinka.
11 Copyright (C) 2023, 2025 Aurélien PIERRE.
12
13 darktable is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 darktable is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with darktable. If not, see <http://www.gnu.org/licenses/>.
25*/
26
27#include "common/printing.h"
28#include "common/image.h"
29#include "common/pdf.h"
30#include "common/logging.h"
31#include "math/math.h"
32
34{
35 pos->x = pos->y = pos->width = pos->height = 0.0f;
36}
37
39{
40 img->imgid = UNKNOWN_IMAGE;
41 img->max_width = img->max_height = 0;
42 img->exp_width = img->exp_height = 0;
43 img->dis_width = img->dis_height = 0;
44 img->img_width = img->img_height = 0;
46 img->buf = NULL;
47
48 _clear_pos(&img->screen);
49 _clear_pos(&img->pos);
50 _clear_pos(&img->print);
51}
52
54{
55 for(int k=0; k<MAX_IMAGE_PER_PAGE; k++)
57
58 _clear_pos(&imgs->screen.page);
60
61 imgs->count = 0;
62 imgs->motion_over = -1;
63 imgs->page_width = imgs->page_height = 0;
64 imgs->page_width_mm = imgs->page_height_mm = 0;
65 imgs->imgid_to_load = -1;
66}
67
68int32_t dt_printing_get_image_box(const dt_images_box *imgs, const int x, const int y)
69{
70 int box = -1;
71 float dist = FLT_MAX;
72
73 for(int k=0; k<imgs->count; k++)
74 {
75 const dt_image_box *b = &imgs->box[k];
76
77 const float x1 = b->screen.x;
78 const float x2 = b->screen.x + b->screen.width;
79 const float y1 = b->screen.y;
80 const float y2 = b->screen.y + b->screen.height;
81
82 // check if over a box
83 if(x > x1 && x < x2 && y > y1 && y < y2)
84 {
85 // compute min dist
86 float dd = sqf(x1 - x);
87 dd = fminf(dd, sqf(x2 - x));
88 dd = fminf(dd, sqf(y1 - y));
89 dd = fminf(dd, sqf(y2 - y));
90
91 if(dd < dist)
92 {
93 box = k;
94 dist = dd;
95 }
96 }
97 }
98
99 return box;
100}
101
102void _compute_rel_pos(const dt_images_box *imgs, const dt_image_pos *ref, dt_image_pos *pos)
103{
104 // compute the printing position & width as % of the page
105
106 const float ofsx = imgs->screen.page.x;
107 const float ofsy = imgs->screen.page.y;
108 const float page_width = imgs->screen.page.width;
109 const float page_height = imgs->screen.page.height;
110
111 pos->x = (ref->x - ofsx) / page_width;
112 pos->y = (ref->y - ofsy) / page_height;
113 pos->width = ref->width / page_width;
114 pos->height = ref->height / page_height;
115}
116
118 const float px, const float py, const float pwidth, const float pheight,
119 const float ax, const float ay, const float awidth, const float aheight,
120 gboolean borderless)
121{
122 imgs->screen.page.x = px;
123 imgs->screen.page.y = py;
124 imgs->screen.page.width = pwidth;
125 imgs->screen.page.height = pheight;
126
127 imgs->screen.print_area.x = ax;
128 imgs->screen.print_area.y = ay;
129 imgs->screen.print_area.width = awidth;
130 imgs->screen.print_area.height = aheight;
131
132 dt_print(DT_DEBUG_PRINT, "[printing] screen/page (%3.1f, %3.1f) -> (%3.1f, %3.1f)\n",
133 px, py, pwidth, pheight);
134 dt_print(DT_DEBUG_PRINT, "[printing] screen/parea (%3.1f, %3.1f) -> (%3.1f, %3.1f)\n",
135 ax, ay, awidth, aheight);
136
137 imgs->screen.borderless = borderless;
138
139 // and now reset the box to be resised accordingly if needed
140 for(int k=0; k<imgs->count; k++)
141 {
142 dt_image_box *box = &imgs->box[k];
143
144 /* A valid box can start exactly at the page origin, so `pos.x == 0`
145 * is not an empty-box sentinel here. Recompute screen geometry for every
146 * box that has a non-zero relative extent. */
147 if(box->pos.width > 0.0f && box->pos.height > 0.0f)
148 {
149 box->screen.x = pwidth * box->pos.x + px;
150 box->screen.y = pheight * box->pos.y + py;
151 box->screen.width = pwidth * box->pos.width;
152 box->screen.height = pheight * box->pos.height;
153 }
154 }
155}
156
157void dt_printing_setup_box(dt_images_box *imgs, const int idx,
158 const float x, const float y,
159 const float width, const float height)
160{
161 if(!isfinite(imgs->screen.page.width) || !isfinite(imgs->screen.page.height)
162 || !isfinite(imgs->screen.print_area.width) || !isfinite(imgs->screen.print_area.height)
163 || imgs->screen.page.width <= 0.0f || imgs->screen.page.height <= 0.0f
164 || imgs->screen.print_area.width <= 0.0f || imgs->screen.print_area.height <= 0.0f)
165 {
166 /* Box coordinates are stored relatively to the display page. If the page
167 * has not been laid out yet, dividing by its size would poison the model
168 * with NaN positions and later redraws would never recover. */
169 return;
170 }
171
172 const float dx = fminf(imgs->screen.print_area.width,
173 fmaxf(100.0f, width));
174 const float dy = fminf(imgs->screen.print_area.height,
175 fmaxf(100.0f, height));
176
177 // setup screen position & width
178
179 dt_image_box *box = &imgs->box[idx];
180
181 box->screen.x = fmaxf(imgs->screen.print_area.x, x);
182 box->screen.y = fmaxf(imgs->screen.print_area.y, y);
183 box->screen.width = dx;
184 box->screen.height = dy;
185
186 if(box->screen.x + dx > imgs->screen.print_area.x + imgs->screen.print_area.width)
187 {
188 const float off = (box->screen.x + dx - imgs->screen.print_area.x - imgs->screen.print_area.width);
189 box->screen.x = fmaxf(imgs->screen.print_area.x, box->screen.x - off);
190 }
191 if(box->screen.y + dy > imgs->screen.print_area.y + imgs->screen.print_area.height)
192 {
193 const float off = (box->screen.y + dy - imgs->screen.print_area.y - imgs->screen.print_area.height);
194 box->screen.y = fmaxf(imgs->screen.print_area.y, box->screen.y - off);
195 }
196
197 _compute_rel_pos(imgs, &box->screen, &box->pos);
198
199 if(idx == imgs->count) imgs->count++;
200}
201
203 const float page_width, const float page_height,
204 const int resolution)
205{
206 imgs->page_width_mm = page_width;
207 imgs->page_height_mm = page_height;
208 imgs->page_width = dt_pdf_point_to_pixel(dt_pdf_mm_to_point(page_width), resolution);
209 imgs->page_height = dt_pdf_point_to_pixel(dt_pdf_mm_to_point(page_height), resolution);
210
211 for(int k=0; k<imgs->count; k++)
212 {
213 dt_image_box *box = &imgs->box[k];
214
215 box->max_width = box->pos.width * imgs->page_width;
216 box->max_height = box->pos.height * imgs->page_height;
217 }
218}
219
220void _align_pos(const dt_image_pos *ref, const dt_alignment_t alignment,
221 const int32_t width, const int32_t height, dt_image_pos *pos)
222{
223 pos->width = width;
224 pos->height = height;
225
226 switch(alignment)
227 {
229 pos->x = ref->x;
230 pos->y = ref->y;
231 break;
232 case ALIGNMENT_TOP:
233 pos->x = ref->x + (ref->width - width) / 2;
234 pos->y = ref->y;
235 break;
237 pos->x = ref->x + (ref->width - width);
238 pos->y = ref->y;
239 break;
240 case ALIGNMENT_LEFT:
241 pos->x = ref->x;
242 pos->y = ref->y + (ref->height - height) / 2;
243 break;
244 case ALIGNMENT_CENTER:
245 pos->x = ref->x + (ref->width - width) / 2;
246 pos->y = ref->y + (ref->height - height) / 2;
247 break;
248 case ALIGNMENT_RIGHT:
249 pos->x = ref->x + (ref->width - width);
250 pos->y = ref->y + (ref->height - height) / 2;
251 break;
253 pos->x = ref->x;
254 pos->y = ref->y + (ref->height - height);
255 break;
256 case ALIGNMENT_BOTTOM:
257 pos->x = ref->x + (ref->width - width) / 2;
258 pos->y = ref->y + (ref->height - height);
259 break;
261 pos->x = ref->x + (ref->width - width);
262 pos->y = ref->y + (ref->height - height);
263 break;
264 }
265}
266
268{
269 _clear_pos(pos);
270
271 _align_pos(&img->screen, img->alignment, img->dis_width, img->dis_height, pos);
272}
273
275{
276 dt_image_pos screen_pos;
277
278 dt_printing_get_screen_pos(imgs, img, &screen_pos);
279
280 _compute_rel_pos(imgs, &screen_pos, pos);
281}
282
284{
285 dt_image_pos rpos;
286
287 dt_printing_get_screen_rel_pos(imgs, img, &rpos);
288
289 pos->x = rpos.x * imgs->page_width_mm;
290 pos->y = rpos.y * imgs->page_height_mm;
291 pos->width = rpos.width * imgs->page_width_mm;
292 pos->height = rpos.height * imgs->page_height_mm;
293}
294
296{
297 dt_image_pos rpos;
298
299 dt_printing_get_screen_rel_pos(imgs, img, &rpos);
300
301 pos->x = rpos.x * imgs->page_width;
302 pos->y = rpos.y * imgs->page_height;
303 pos->width = rpos.width * imgs->page_width;
304 pos->height = rpos.height * imgs->page_height;
305}
306
307void dt_printing_setup_image(dt_images_box *imgs, const int idx,
308 const int32_t imgid, const int32_t width, const int32_t height,
309 const dt_alignment_t alignment)
310{
311 dt_image_box *box = &imgs->box[idx];
312
313 // FIXME: broken by design
314 // re-implement a non-shitty way of getting final size
315 //if(box->imgid != imgid)
316 // dt_image_get_final_size(imgid, &box->img_width, &box->img_height);
317
318 box->imgid = imgid;
319 box->exp_width = width;
320 box->exp_height = height;
321 box->alignment = alignment;
322
323 // for the print (pdf) the origin is bottom/left, so y must be inverted compared to
324 // screen coordinates.
325 box->print.x = box->pos.x * imgs->page_width;
326 box->print.y = box->pos.y * imgs->page_height;
327 box->print.width = box->pos.width * imgs->page_width;
328 box->print.height = box->pos.height * imgs->page_height;
329
330 dt_image_pos pos = { .x = 0, .y = 0, .width = 0, .height = 0 };
331 _align_pos(&box->print, box->alignment, box->exp_width, box->exp_height, &pos);
332
333 box->print.x = pos.x;
334 box->print.y = imgs->page_height - (pos.y + pos.height);
335 box->print.width = pos.width;
336 box->print.height = pos.height;
337
338 // compute image size on display
339
340 box->dis_width = box->img_width;
341 box->dis_height = box->img_height;
342
343 if(box->dis_width > box->screen.width)
344 {
345 const float scale = box->screen.width / (float)box->dis_width;
346 box->dis_width = box->screen.width;
347 box->dis_height = (int32_t)(((float)box->dis_height + 0.5f) * scale);
348 }
349
350 if(box->dis_height > box->screen.height)
351 {
352 const float scale = box->screen.height / (float)box->dis_height;
353 box->dis_height = box->screen.height;
354 box->dis_width = (int32_t)(((float)box->dis_width + 0.5f) * scale);
355 }
356}
357
358// clang-format off
359// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
360// vim: shiftwidth=2 expandtab tabstop=2 cindent
361// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
362// clang-format on
static double dist(double x1, double y1, double x2, double y2)
Definition ashift_lsd.c:250
static const float x
dt_alignment_t
Definition cups_print.h:31
@ ALIGNMENT_TOP_RIGHT
Definition cups_print.h:34
@ ALIGNMENT_LEFT
Definition cups_print.h:35
@ ALIGNMENT_CENTER
Definition cups_print.h:36
@ ALIGNMENT_BOTTOM_RIGHT
Definition cups_print.h:40
@ ALIGNMENT_TOP_LEFT
Definition cups_print.h:32
@ ALIGNMENT_BOTTOM
Definition cups_print.h:39
@ ALIGNMENT_TOP
Definition cups_print.h:33
@ ALIGNMENT_RIGHT
Definition cups_print.h:37
@ ALIGNMENT_BOTTOM_LEFT
Definition cups_print.h:38
#define UNKNOWN_IMAGE
Definition image.h:78
@ DT_DEBUG_PRINT
Definition logging.h:65
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
#define dt_pdf_point_to_pixel(pt, dpi)
Definition pdf.h:44
#define dt_pdf_mm_to_point(mm)
Definition pdf.h:42
void _align_pos(const dt_image_pos *ref, const dt_alignment_t alignment, const int32_t width, const int32_t height, dt_image_pos *pos)
Definition printing.c:220
void dt_printing_get_screen_pos(const dt_images_box *imgs, const dt_image_box *img, dt_image_pos *pos)
Definition printing.c:267
void _clear_pos(dt_image_pos *pos)
Definition printing.c:33
void dt_printing_setup_display(dt_images_box *imgs, const float px, const float py, const float pwidth, const float pheight, const float ax, const float ay, const float awidth, const float aheight, gboolean borderless)
Definition printing.c:117
void dt_printing_get_image_pos(const dt_images_box *imgs, const dt_image_box *img, dt_image_pos *pos)
Definition printing.c:295
int32_t dt_printing_get_image_box(const dt_images_box *imgs, const int x, const int y)
Definition printing.c:68
void dt_printing_clear_box(dt_image_box *img)
Definition printing.c:38
void dt_printing_setup_box(dt_images_box *imgs, const int idx, const float x, const float y, const float width, const float height)
Definition printing.c:157
void _compute_rel_pos(const dt_images_box *imgs, const dt_image_pos *ref, dt_image_pos *pos)
Definition printing.c:102
void dt_printing_setup_image(dt_images_box *imgs, const int idx, const int32_t imgid, const int32_t width, const int32_t height, const dt_alignment_t alignment)
Definition printing.c:307
void dt_printing_get_screen_rel_pos(const dt_images_box *imgs, const dt_image_box *img, dt_image_pos *pos)
Definition printing.c:274
void dt_printing_setup_page(dt_images_box *imgs, const float page_width, const float page_height, const int resolution)
Definition printing.c:202
void dt_printing_clear_boxes(dt_images_box *imgs)
Definition printing.c:53
void dt_printing_get_image_pos_mm(const dt_images_box *imgs, const dt_image_box *img, dt_image_pos *pos)
Definition printing.c:283
#define MAX_IMAGE_PER_PAGE
Definition printing.h:35
dt_image_pos screen
Definition printing.h:51
int32_t dis_width
Definition printing.h:47
int32_t exp_height
Definition printing.h:46
int32_t exp_width
Definition printing.h:46
int32_t dis_height
Definition printing.h:47
dt_alignment_t alignment
Definition printing.h:49
int32_t max_width
Definition printing.h:45
int32_t img_height
Definition printing.h:48
int32_t imgid
Definition printing.h:44
dt_image_pos pos
Definition printing.h:50
int32_t max_height
Definition printing.h:45
uint16_t * buf
Definition printing.h:53
int32_t img_width
Definition printing.h:48
dt_image_pos print
Definition printing.h:52
float width
Definition printing.h:39
float x
Definition printing.h:39
float height
Definition printing.h:39
float y
Definition printing.h:39
float page_height
Definition printing.h:75
int32_t imgid_to_load
Definition printing.h:71
float page_width
Definition printing.h:75
dt_image_box box[20]
Definition printing.h:74
int32_t motion_over
Definition printing.h:72
dt_screen_pos screen
Definition printing.h:77
float page_width_mm
Definition printing.h:76
float page_height_mm
Definition printing.h:76
gboolean borderless
Definition printing.h:65
dt_image_pos print_area
Definition printing.h:62
dt_image_pos page
Definition printing.h:58