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/math.h"
29
31{
32 pos->x = pos->y = pos->width = pos->height = 0.0f;
33}
34
36{
37 img->imgid = UNKNOWN_IMAGE;
38 img->max_width = img->max_height = 0;
39 img->exp_width = img->exp_height = 0;
40 img->dis_width = img->dis_height = 0;
41 img->img_width = img->img_height = 0;
43 img->buf = NULL;
44
45 _clear_pos(&img->screen);
46 _clear_pos(&img->pos);
47 _clear_pos(&img->print);
48}
49
51{
52 for(int k=0; k<MAX_IMAGE_PER_PAGE; k++)
54
55 _clear_pos(&imgs->screen.page);
57
58 imgs->count = 0;
59 imgs->motion_over = -1;
60 imgs->page_width = imgs->page_height = 0;
61 imgs->page_width_mm = imgs->page_height_mm = 0;
62 imgs->imgid_to_load = -1;
63}
64
65int32_t dt_printing_get_image_box(const dt_images_box *imgs, const int x, const int y)
66{
67 int box = -1;
68 float dist = FLT_MAX;
69
70 for(int k=0; k<imgs->count; k++)
71 {
72 const dt_image_box *b = &imgs->box[k];
73
74 const float x1 = b->screen.x;
75 const float x2 = b->screen.x + b->screen.width;
76 const float y1 = b->screen.y;
77 const float y2 = b->screen.y + b->screen.height;
78
79 // check if over a box
80 if(x > x1 && x < x2 && y > y1 && y < y2)
81 {
82 // compute min dist
83 float dd = sqf(x1 - x);
84 dd = fminf(dd, sqf(x2 - x));
85 dd = fminf(dd, sqf(y1 - y));
86 dd = fminf(dd, sqf(y2 - y));
87
88 if(dd < dist)
89 {
90 box = k;
91 dist = dd;
92 }
93 }
94 }
95
96 return box;
97}
98
99void _compute_rel_pos(const dt_images_box *imgs, const dt_image_pos *ref, dt_image_pos *pos)
100{
101 // compute the printing position & width as % of the page
102
103 const float ofsx = imgs->screen.page.x;
104 const float ofsy = imgs->screen.page.y;
105 const float page_width = imgs->screen.page.width;
106 const float page_height = imgs->screen.page.height;
107
108 pos->x = (ref->x - ofsx) / page_width;
109 pos->y = (ref->y - ofsy) / page_height;
110 pos->width = ref->width / page_width;
111 pos->height = ref->height / page_height;
112}
113
115 const float px, const float py, const float pwidth, const float pheight,
116 const float ax, const float ay, const float awidth, const float aheight,
117 gboolean borderless)
118{
119 imgs->screen.page.x = px;
120 imgs->screen.page.y = py;
121 imgs->screen.page.width = pwidth;
122 imgs->screen.page.height = pheight;
123
124 imgs->screen.print_area.x = ax;
125 imgs->screen.print_area.y = ay;
126 imgs->screen.print_area.width = awidth;
127 imgs->screen.print_area.height = aheight;
128
129 dt_print(DT_DEBUG_PRINT, "[printing] screen/page (%3.1f, %3.1f) -> (%3.1f, %3.1f)\n",
130 px, py, pwidth, pheight);
131 dt_print(DT_DEBUG_PRINT, "[printing] screen/parea (%3.1f, %3.1f) -> (%3.1f, %3.1f)\n",
132 ax, ay, awidth, aheight);
133
134 imgs->screen.borderless = borderless;
135
136 // and now reset the box to be resised accordingly if needed
137 for(int k=0; k<imgs->count; k++)
138 {
139 dt_image_box *box = &imgs->box[k];
140
141 /* A valid box can start exactly at the page origin, so `pos.x == 0`
142 * is not an empty-box sentinel here. Recompute screen geometry for every
143 * box that has a non-zero relative extent. */
144 if(box->pos.width > 0.0f && box->pos.height > 0.0f)
145 {
146 box->screen.x = pwidth * box->pos.x + px;
147 box->screen.y = pheight * box->pos.y + py;
148 box->screen.width = pwidth * box->pos.width;
149 box->screen.height = pheight * box->pos.height;
150 }
151 }
152}
153
154void dt_printing_setup_box(dt_images_box *imgs, const int idx,
155 const float x, const float y,
156 const float width, const float height)
157{
158 if(!isfinite(imgs->screen.page.width) || !isfinite(imgs->screen.page.height)
159 || !isfinite(imgs->screen.print_area.width) || !isfinite(imgs->screen.print_area.height)
160 || imgs->screen.page.width <= 0.0f || imgs->screen.page.height <= 0.0f
161 || imgs->screen.print_area.width <= 0.0f || imgs->screen.print_area.height <= 0.0f)
162 {
163 /* Box coordinates are stored relatively to the display page. If the page
164 * has not been laid out yet, dividing by its size would poison the model
165 * with NaN positions and later redraws would never recover. */
166 return;
167 }
168
169 const float dx = fminf(imgs->screen.print_area.width,
170 fmaxf(100.0f, width));
171 const float dy = fminf(imgs->screen.print_area.height,
172 fmaxf(100.0f, height));
173
174 // setup screen position & width
175
176 dt_image_box *box = &imgs->box[idx];
177
178 box->screen.x = fmaxf(imgs->screen.print_area.x, x);
179 box->screen.y = fmaxf(imgs->screen.print_area.y, y);
180 box->screen.width = dx;
181 box->screen.height = dy;
182
183 if(box->screen.x + dx > imgs->screen.print_area.x + imgs->screen.print_area.width)
184 {
185 const float off = (box->screen.x + dx - imgs->screen.print_area.x - imgs->screen.print_area.width);
186 box->screen.x = fmaxf(imgs->screen.print_area.x, box->screen.x - off);
187 }
188 if(box->screen.y + dy > imgs->screen.print_area.y + imgs->screen.print_area.height)
189 {
190 const float off = (box->screen.y + dy - imgs->screen.print_area.y - imgs->screen.print_area.height);
191 box->screen.y = fmaxf(imgs->screen.print_area.y, box->screen.y - off);
192 }
193
194 _compute_rel_pos(imgs, &box->screen, &box->pos);
195
196 if(idx == imgs->count) imgs->count++;
197}
198
200 const float page_width, const float page_height,
201 const int resolution)
202{
203 imgs->page_width_mm = page_width;
204 imgs->page_height_mm = page_height;
205 imgs->page_width = dt_pdf_point_to_pixel(dt_pdf_mm_to_point(page_width), resolution);
206 imgs->page_height = dt_pdf_point_to_pixel(dt_pdf_mm_to_point(page_height), resolution);
207
208 for(int k=0; k<imgs->count; k++)
209 {
210 dt_image_box *box = &imgs->box[k];
211
212 box->max_width = box->pos.width * imgs->page_width;
213 box->max_height = box->pos.height * imgs->page_height;
214 }
215}
216
217void _align_pos(const dt_image_pos *ref, const dt_alignment_t alignment,
218 const int32_t width, const int32_t height, dt_image_pos *pos)
219{
220 pos->width = width;
221 pos->height = height;
222
223 switch(alignment)
224 {
226 pos->x = ref->x;
227 pos->y = ref->y;
228 break;
229 case ALIGNMENT_TOP:
230 pos->x = ref->x + (ref->width - width) / 2;
231 pos->y = ref->y;
232 break;
234 pos->x = ref->x + (ref->width - width);
235 pos->y = ref->y;
236 break;
237 case ALIGNMENT_LEFT:
238 pos->x = ref->x;
239 pos->y = ref->y + (ref->height - height) / 2;
240 break;
241 case ALIGNMENT_CENTER:
242 pos->x = ref->x + (ref->width - width) / 2;
243 pos->y = ref->y + (ref->height - height) / 2;
244 break;
245 case ALIGNMENT_RIGHT:
246 pos->x = ref->x + (ref->width - width);
247 pos->y = ref->y + (ref->height - height) / 2;
248 break;
250 pos->x = ref->x;
251 pos->y = ref->y + (ref->height - height);
252 break;
253 case ALIGNMENT_BOTTOM:
254 pos->x = ref->x + (ref->width - width) / 2;
255 pos->y = ref->y + (ref->height - height);
256 break;
258 pos->x = ref->x + (ref->width - width);
259 pos->y = ref->y + (ref->height - height);
260 break;
261 }
262}
263
265{
266 _clear_pos(pos);
267
268 _align_pos(&img->screen, img->alignment, img->dis_width, img->dis_height, pos);
269}
270
272{
273 dt_image_pos screen_pos;
274
275 dt_printing_get_screen_pos(imgs, img, &screen_pos);
276
277 _compute_rel_pos(imgs, &screen_pos, pos);
278}
279
281{
282 dt_image_pos rpos;
283
284 dt_printing_get_screen_rel_pos(imgs, img, &rpos);
285
286 pos->x = rpos.x * imgs->page_width_mm;
287 pos->y = rpos.y * imgs->page_height_mm;
288 pos->width = rpos.width * imgs->page_width_mm;
289 pos->height = rpos.height * imgs->page_height_mm;
290}
291
293{
294 dt_image_pos rpos;
295
296 dt_printing_get_screen_rel_pos(imgs, img, &rpos);
297
298 pos->x = rpos.x * imgs->page_width;
299 pos->y = rpos.y * imgs->page_height;
300 pos->width = rpos.width * imgs->page_width;
301 pos->height = rpos.height * imgs->page_height;
302}
303
304void dt_printing_setup_image(dt_images_box *imgs, const int idx,
305 const int32_t imgid, const int32_t width, const int32_t height,
306 const dt_alignment_t alignment)
307{
308 dt_image_box *box = &imgs->box[idx];
309
310 // FIXME: broken by design
311 // re-implement a non-shitty way of getting final size
312 //if(box->imgid != imgid)
313 // dt_image_get_final_size(imgid, &box->img_width, &box->img_height);
314
315 box->imgid = imgid;
316 box->exp_width = width;
317 box->exp_height = height;
318 box->alignment = alignment;
319
320 // for the print (pdf) the origin is bottom/left, so y must be inverted compared to
321 // screen coordinates.
322 box->print.x = box->pos.x * imgs->page_width;
323 box->print.y = box->pos.y * imgs->page_height;
324 box->print.width = box->pos.width * imgs->page_width;
325 box->print.height = box->pos.height * imgs->page_height;
326
327 dt_image_pos pos = { .x = 0, .y = 0, .width = 0, .height = 0 };
328 _align_pos(&box->print, box->alignment, box->exp_width, box->exp_height, &pos);
329
330 box->print.x = pos.x;
331 box->print.y = imgs->page_height - (pos.y + pos.height);
332 box->print.width = pos.width;
333 box->print.height = pos.height;
334
335 // compute image size on display
336
337 box->dis_width = box->img_width;
338 box->dis_height = box->img_height;
339
340 if(box->dis_width > box->screen.width)
341 {
342 const float scale = box->screen.width / (float)box->dis_width;
343 box->dis_width = box->screen.width;
344 box->dis_height = (int32_t)(((float)box->dis_height + 0.5f) * scale);
345 }
346
347 if(box->dis_height > box->screen.height)
348 {
349 const float scale = box->screen.height / (float)box->dis_height;
350 box->dis_height = box->screen.height;
351 box->dis_width = (int32_t)(((float)box->dis_width + 0.5f) * scale);
352 }
353}
354
355// clang-format off
356// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
357// vim: shiftwidth=2 expandtab tabstop=2 cindent
358// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
359// clang-format on
static double dist(double x1, double y1, double x2, double y2)
Definition ashift_lsd.c:250
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
dt_alignment_t
Definition cups_print.h:30
@ ALIGNMENT_TOP_RIGHT
Definition cups_print.h:33
@ ALIGNMENT_LEFT
Definition cups_print.h:34
@ ALIGNMENT_CENTER
Definition cups_print.h:35
@ ALIGNMENT_BOTTOM_RIGHT
Definition cups_print.h:39
@ ALIGNMENT_TOP_LEFT
Definition cups_print.h:31
@ ALIGNMENT_BOTTOM
Definition cups_print.h:38
@ ALIGNMENT_TOP
Definition cups_print.h:32
@ ALIGNMENT_RIGHT
Definition cups_print.h:36
@ ALIGNMENT_BOTTOM_LEFT
Definition cups_print.h:37
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1542
#define UNKNOWN_IMAGE
Definition darktable.h:182
@ DT_DEBUG_PRINT
Definition darktable.h:730
static const float x
float *const restrict const size_t k
#define dt_pdf_point_to_pixel(pt, dpi)
Definition pdf.h:43
#define dt_pdf_mm_to_point(mm)
Definition pdf.h:41
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:217
void dt_printing_get_screen_pos(const dt_images_box *imgs, const dt_image_box *img, dt_image_pos *pos)
Definition printing.c:264
void _clear_pos(dt_image_pos *pos)
Definition printing.c:30
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:114
void dt_printing_get_image_pos(const dt_images_box *imgs, const dt_image_box *img, dt_image_pos *pos)
Definition printing.c:292
int32_t dt_printing_get_image_box(const dt_images_box *imgs, const int x, const int y)
Definition printing.c:65
void dt_printing_clear_box(dt_image_box *img)
Definition printing.c:35
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:154
void _compute_rel_pos(const dt_images_box *imgs, const dt_image_pos *ref, dt_image_pos *pos)
Definition printing.c:99
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:304
void dt_printing_get_screen_rel_pos(const dt_images_box *imgs, const dt_image_box *img, dt_image_pos *pos)
Definition printing.c:271
void dt_printing_setup_page(dt_images_box *imgs, const float page_width, const float page_height, const int resolution)
Definition printing.c:199
void dt_printing_clear_boxes(dt_images_box *imgs)
Definition printing.c:50
void dt_printing_get_image_pos_mm(const dt_images_box *imgs, const dt_image_box *img, dt_image_pos *pos)
Definition printing.c:280
#define MAX_IMAGE_PER_PAGE
Definition printing.h:36
dt_image_pos screen
Definition printing.h:52
int32_t dis_width
Definition printing.h:48
int32_t exp_height
Definition printing.h:47
int32_t exp_width
Definition printing.h:47
int32_t dis_height
Definition printing.h:48
dt_alignment_t alignment
Definition printing.h:50
int32_t max_width
Definition printing.h:46
int32_t img_height
Definition printing.h:49
int32_t imgid
Definition printing.h:45
dt_image_pos pos
Definition printing.h:51
int32_t max_height
Definition printing.h:46
uint16_t * buf
Definition printing.h:54
int32_t img_width
Definition printing.h:49
dt_image_pos print
Definition printing.h:53
float width
Definition printing.h:40
float x
Definition printing.h:40
float height
Definition printing.h:40
float y
Definition printing.h:40
float page_height
Definition printing.h:76
int32_t imgid_to_load
Definition printing.h:72
float page_width
Definition printing.h:76
dt_image_box box[20]
Definition printing.h:75
int32_t motion_over
Definition printing.h:73
dt_screen_pos screen
Definition printing.h:78
float page_width_mm
Definition printing.h:77
float page_height_mm
Definition printing.h:77
gboolean borderless
Definition printing.h:66
dt_image_pos print_area
Definition printing.h:63
dt_image_pos page
Definition printing.h:59