Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
print_settings.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2014-2018, 2020-2022 Pascal Obry.
4 Copyright (C) 2015 Jérémy Rosen.
5 Copyright (C) 2015-2016 Roman Lebedev.
6 Copyright (C) 2015-2020 Tobias Ellinghaus.
7 Copyright (C) 2017-2018, 2021-2022 Dan Torop.
8 Copyright (C) 2017, 2019, 2022 luzpaz.
9 Copyright (C) 2018 Maurizio Paglia.
10 Copyright (C) 2018 rawfiner.
11 Copyright (C) 2019 Denis Dyakov.
12 Copyright (C) 2019 Edgardo Hoszowski.
13 Copyright (C) 2019 jakubfi.
14 Copyright (C) 2019 Pascal de Bruijn.
15 Copyright (C) 2019 Philippe Weyland.
16 Copyright (C) 2020, 2022 Aldric Renaudin.
17 Copyright (C) 2020-2022 Diederik Ter Rahe.
18 Copyright (C) 2020 Hubert Kowalski.
19 Copyright (C) 2020 JP Verrue.
20 Copyright (C) 2021 Ralf Brown.
21 Copyright (C) 2022, 2025 Aurélien PIERRE.
22 Copyright (C) 2022 Martin Bařinka.
23 Copyright (C) 2022 Miloš Komarčević.
24 Copyright (C) 2022 Victor Forsiuk.
25
26 darktable is free software: you can redistribute it and/or modify
27 it under the terms of the GNU General Public License as published by
28 the Free Software Foundation, either version 3 of the License, or
29 (at your option) any later version.
30
31 darktable is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 GNU General Public License for more details.
35
36 You should have received a copy of the GNU General Public License
37 along with darktable. If not, see <http://www.gnu.org/licenses/>.
38*/
39
40#include "common/darktable.h"
41#include <glib.h>
42
43#include "bauhaus/bauhaus.h"
44#include "common/collection.h"
45#include "common/colorspaces.h"
46#include "common/cups_print.h"
48#include "common/image_cache.h"
49#include "common/metadata.h"
50#include "common/pdf.h"
51#include "common/printprof.h"
52#include "common/printing.h"
53#include "common/styles.h"
54#include "common/tags.h"
55#include "common/variables.h"
56#include "control/jobs.h"
57#include "dtgtk/resetlabel.h"
58
59#include "gui/drag_and_drop.h"
60#include "gui/gtk.h"
61#include "libs/lib.h"
62#include "libs/lib_api.h"
63
64DT_MODULE(4)
65
66const char *name(struct dt_lib_module_t *self)
67{
68 return _("print settings");
69}
70
71const char **views(dt_lib_module_t *self)
72{
73 static const char *v[] = {"print", NULL};
74 return v;
75}
76
81
94
95typedef enum _unit_t
96{
100 UNIT_N // needs to be the last one
102
103
104static const float units[UNIT_N] = { 1.0f, 0.1f, 1.0f/25.4f };
105static const gchar *_unit_names[] = { N_("mm"), N_("cm"), N_("inch"), NULL };
106
143
158
160{
161 dt_colorspaces_color_profile_type_t type; // filename is only used for type DT_COLORSPACE_FILE
162 char filename[512]; // icc file name
163 char name[512]; // product name
164 int pos, ppos; // position in combo boxen
166
168{
169 const char *name;
171
173static void _width_changed(GtkWidget *widget, gpointer user_data);
174static void _height_changed(GtkWidget *widget, gpointer user_data);
175static void _x_changed(GtkWidget *widget, gpointer user_data);
176static void _y_changed(GtkWidget *widget, gpointer user_data);
177
178int
180{
181 return 990;
182}
183
184/* get paper dimension for the orientation (in mm) */
185static void _get_page_dimension(dt_print_info_t *prt, float *width, float *height)
186{
187 if(prt->page.landscape)
188 {
189 *width = prt->paper.height;
190 *height = prt->paper.width;
191 }
192 else
193 {
194 *width = prt->paper.width;
195 *height = prt->paper.height;
196 }
197}
198
199static void _precision_by_unit(_unit_t unit, int *n_digits, float *incr, char **format)
200{
201 // this gives us these precisions
202 // unit precision increment
203 // mm 1 1
204 // cm 0.1 0.1
205 // in 0.01 0.05
206 //
207 // This allows for >= 1mm precision display regardless of unit, and
208 // allows for entering common fractions (e.g. 1/4 as .25) for
209 // inches. Increment is kept to 1mm except in the cases of inches,
210 // where we round up from 0.03937 (1mm) to 0.05 to keep to a factor
211 // of a power of ten.
212 *n_digits = ceilf(log10f(1.0f / units[unit]));
213 if(incr)
214 {
215 *incr = roundf(units[unit] * 20.0f) / 20.0f;
216 }
217 if(format)
218 {
219 *format = g_strdup_printf("%%.%df", *n_digits);
220 }
221}
222
223// unit conversion
224
225static float _to_mm(dt_lib_print_settings_t *ps, double value)
226{
227 return value / units[ps->unit];
228}
229
230// horizontal mm to pixels
231static float _mm_to_hscreen(dt_lib_print_settings_t *ps, const float value, const gboolean offset)
232{
233 float width, height;
235
236 return (offset ? ps->imgs.screen.page.x : 0)
237 + (ps->imgs.screen.page.width * value / width);
238}
239
240// vertical mm to pixels
241static float _mm_to_vscreen(dt_lib_print_settings_t *ps, const float value, const gboolean offset)
242{
243 float width, height;
245
246 return (offset ? ps->imgs.screen.page.y : 0)
247 + (ps->imgs.screen.page.height * value / height);
248}
249
250static float _hscreen_to_mm(dt_lib_print_settings_t *ps, const float value, const gboolean offset)
251{
252 float width, height;
254
255 return width * (value - (offset ? ps->imgs.screen.page.x : 0.0f))
256 / ps->imgs.screen.page.width;
257}
258
259static float _vscreen_to_mm(dt_lib_print_settings_t *ps, const float value, const gboolean offset)
260{
261 float width, height;
263
264 return height * (value - (offset ? ps->imgs.screen.page.y : 0.0f))
265 / ps->imgs.screen.page.height;
266}
267
268
269static inline float _percent_unit_of(dt_lib_print_settings_t *ps, float ref, float value)
270{
271 return value * ref * units[ps->unit];
272}
273
274// callbacks for in-memory export
275
282
284{
285 const dt_print_format_t *d = (dt_print_format_t *)data;
286 return d->bpp;
287}
288
290{
291 const dt_print_format_t *d = (dt_print_format_t *)data;
292 return IMAGEIO_RGB | (d->bpp == 8 ? IMAGEIO_INT8 : IMAGEIO_INT16);
293}
294
295static const char *mime(dt_imageio_module_data_t *data)
296{
297 return "memory";
298}
299
300static int write_image(dt_imageio_module_data_t *data, const char *filename, const void *in,
301 dt_colorspaces_color_profile_type_t over_type, const char *over_filename,
302 void *exif, int exif_len, int32_t imgid, int num, int total, dt_dev_pixelpipe_t *pipe,
303 const gboolean export_masks)
304{
306
307 d->params->buf = (uint16_t *)malloc((size_t)3 * (d->bpp == 8?1:2) * d->head.width * d->head.height);
308
309 if(d->bpp == 8)
310 {
311 const uint8_t *in_ptr = (const uint8_t *)in;
312 uint8_t *out_ptr = (uint8_t *)d->params->buf;
313 for(int y = 0; y < d->head.height; y++)
314 {
315 for(int x = 0; x < d->head.width; x++, in_ptr += 4, out_ptr += 3)
316 memcpy(out_ptr, in_ptr, 3);
317 }
318 }
319 else
320 {
321 const uint16_t *in_ptr = (const uint16_t *)in;
322 uint16_t *out_ptr = (uint16_t *)d->params->buf;
323 for(int y = 0; y < d->head.height; y++)
324 {
325 for(int x = 0; x < d->head.width; x++, in_ptr += 4, out_ptr += 3)
326 memcpy(out_ptr, in_ptr, 6);
327 }
328 }
329
330 return 0;
331}
332
333// export image imgid with given max_width & max_height, set iwidth & iheight with the
334// final image size as exported.
335static int _export_image(dt_job_t *job, dt_image_box *img)
336{
338
340 buf.mime = mime;
341 buf.levels = levels;
342 buf.bpp = bpp;
343 buf.write_image = write_image;
344
346 dat.head.max_width = img->max_width;
347 dat.head.max_height = img->max_height;
348 dat.head.style[0] = '\0';
349 dat.bpp = *params->p_icc_profile ? 16 : 8; // set to 16bit when a profile is to be applied
350 dat.params = params;
351
352 if(params->style) g_strlcpy(dat.head.style, params->style, sizeof(dat.head.style));
353
354 // let the user know something is happening
356 dt_control_log(_("processing `%s' for `%s'"), params->job_title, params->prt.printer.name);
357
358 const gboolean export_masks = FALSE;
359 const gboolean is_scaling = FALSE;
360
362 (img->imgid, "unused", &buf, (dt_imageio_module_data_t *)&dat, TRUE, FALSE,
363 TRUE, is_scaling, FALSE, NULL, FALSE, export_masks, params->buf_icc_type,
364 params->buf_icc_profile, params->buf_icc_intent, NULL, NULL, 1, 1, NULL, NULL);
365
366 img->exp_width = dat.head.width;
367 img->exp_height = dat.head.height;
368
369 // we have the exported buffer, let's apply the printer profile
370
371 const dt_colorspaces_color_profile_t *buf_profile =
373 &params->buf_icc_type,
374 params->buf_icc_profile);
375 if(*params->p_icc_profile)
376 {
377 const dt_colorspaces_color_profile_t *pprof =
378 dt_colorspaces_get_profile(params->p_icc_type, params->p_icc_profile,
380 if(IS_NULL_PTR(pprof))
381 {
382 dt_control_log(_("cannot open printer profile `%s'"), params->p_icc_profile);
383 fprintf(stderr, "cannot open printer profile `%s'\n", params->p_icc_profile);
385 return 1;
386 }
387 else
388 {
389 if(IS_NULL_PTR(buf_profile) || IS_NULL_PTR(buf_profile->profile))
390 {
391 dt_control_log(_("error getting output profile for image %d"), img->imgid);
392 fprintf(stderr, "error getting output profile for image %d\n", img->imgid);
394 return 1;
395 }
397 ((void **)&(params->buf), dat.head.width, dat.head.height, dat.bpp, buf_profile->profile,
398 pprof->profile, params->p_icc_intent, params->black_point_compensation))
399 {
400 dt_control_log(_("cannot apply printer profile `%s'"), params->p_icc_profile);
401 fprintf(stderr, "cannot apply printer profile `%s'\n", params->p_icc_profile);
403 return 1;
404 }
405 }
406 }
407
408 img->buf = params->buf;
409 params->buf = NULL;
410
411 return 0;
412}
413
414static void _create_pdf(dt_job_t *job, dt_images_box imgs, const float width, const float height)
415{
417
418 const float page_width = dt_pdf_mm_to_point(width);
419 const float page_height = dt_pdf_mm_to_point(height);
420 const int icc_id = 0;
421
423
424 // create the PDF page
425 dt_pdf_t *pdf = dt_pdf_start(params->pdf_filename, page_width, page_height,
426 params->prt.printer.resolution, DT_PDF_STREAM_ENCODER_FLATE);
427
428/*
429 // ??? should a profile be embedded here?
430 if (*printer_profile)
431 icc_id = dt_pdf_add_icc(pdf, printer_profile);
432*/
433 int32_t count = 0;
434
435 for(int k=0; k<imgs.count; k++)
436 {
437 const int resolution = params->prt.printer.resolution;
438 const dt_image_box *box = &imgs.box[k];
439
440 if(box->imgid > UNKNOWN_IMAGE)
441 {
442 pdf_image[count] =
443 dt_pdf_add_image(pdf, (uint8_t *)box->buf, box->exp_width, box->exp_height,
444 8, icc_id, 0.0);
445
446 // PDF bounding-box has origin on bottom-left
447 pdf_image[count]->bb_x = dt_pdf_pixel_to_point(box->print.x, resolution);
448 pdf_image[count]->bb_y = dt_pdf_pixel_to_point(box->print.y, resolution);
449 pdf_image[count]->bb_width = dt_pdf_pixel_to_point(box->print.width, resolution);
450 pdf_image[count]->bb_height = dt_pdf_pixel_to_point(box->print.height, resolution);
451 count++;
452 }
453 }
454
455 params->pdf_page = dt_pdf_add_page(pdf, pdf_image, count);
456 dt_pdf_finish(pdf, &params->pdf_page, 1);
457
458 // now releases all the buf
459 for(int k=0; k<imgs.count; k++)
460 {
461 dt_image_box *box = &imgs.box[k];
462 dt_free(box->buf);
463 }
464}
465
467{
468 float x = 0.0f, y = 0.0f, swidth = 0.0f, sheight = 0.0f;
469
470 if(ps->last_selected != -1)
471 {
472 dt_image_box *box = &ps->imgs.box[ps->last_selected];
473
474 float width, height;
476
477 x = _percent_unit_of(ps, width, box->pos.x);
478 y = _percent_unit_of(ps, height, box->pos.y);
479 swidth = _percent_unit_of(ps, width, box->pos.width);
480 sheight = _percent_unit_of(ps, height, box->pos.height);
481
482 for(int i=0; i<9; i++)
483 {
485 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->dtba[i]), (i == box->alignment));
487 }
488 }
489
491
492 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_x), x);
493
494 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_y), y);
495
496 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_width), swidth);
497
498 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_height), sheight);
499
501}
502
503static int _export_and_setup_pos(dt_job_t *job, dt_image_box *img, const int32_t idx)
504{
506
507 float width, height;
508 _get_page_dimension(&params->prt, &width, &height);
509
510 dt_printing_setup_page(&params->imgs, width, height, params->prt.printer.resolution);
511
512 dt_print(DT_DEBUG_PRINT, "[print] max image size %d x %d (at resolution %d)\n",
513 img->max_width, img->max_height, params->prt.printer.resolution);
514
515 if(_export_image(job, img)) return 1;
516
517 dt_printing_setup_image(&params->imgs, idx,
518 img->imgid, img->exp_width, img->exp_height, img->alignment);
519
520 return 0;
521}
522
523static int _print_job_run(dt_job_t *job)
524{
526
527 // get first image on a box, needed as print leader
528
529 int32_t imgid = UNKNOWN_IMAGE;
530
531 // compute the needed size for picture for the given printer resolution
532
533 for(int k=0; k<params->imgs.count; k++)
534 {
535 if(params->imgs.box[k].imgid > UNKNOWN_IMAGE)
536 {
537 if(imgid == UNKNOWN_IMAGE) imgid = params->imgs.box[k].imgid;
538 if(_export_and_setup_pos(job, &params->imgs.box[k], k))
539 return 1;
540 }
541 }
542
545
546 dt_loc_get_tmp_dir(params->pdf_filename, sizeof(params->pdf_filename));
547 g_strlcat(params->pdf_filename, "/pf.XXXXXX.pdf", sizeof(params->pdf_filename));
548
549 const gint fd = g_mkstemp(params->pdf_filename);
550 if(fd == -1)
551 {
552 dt_control_log(_("failed to create temporary pdf for printing"));
553 fprintf(stderr, "failed to create temporary pdf for printing\n");
554 return 1;
555 }
556 close(fd);
557
558 float width, height;
559 _get_page_dimension(&params->prt, &width, &height);
560
561 _create_pdf(job, params->imgs, width, height);
562
565
566 // send to CUPS
567
568 dt_print_file(imgid, params->pdf_filename, params->job_title, &params->prt);
570
571 // add tag for this image
572
573 char tag[256] = { 0 };
574 guint tagid = 0;
575 snprintf (tag, sizeof(tag), "darktable|printed|%s", params->prt.printer.name);
576 dt_tag_new(tag, &tagid);
577
578 for(int k=0; k<params->imgs.count; k++)
579 {
580 if(params->imgs.box[k].imgid > UNKNOWN_IMAGE)
581 if(dt_tag_attach(tagid, params->imgs.box[k].imgid, FALSE, FALSE))
583
584 /* register print timestamp in cache */
586 }
587
588 return 0;
589}
590
591static void _page_new_area_clicked(GtkWidget *widget, gpointer user_data)
592{
593 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
595
596 if(ps->imgs.count == MAX_IMAGE_PER_PAGE)
597 {
598 dt_control_log(_("maximum image per page reached"));
599 return;
600 }
601
602 dt_control_change_cursor(GDK_PLUS);
603 ps->creation = TRUE;
604 ps->has_changed = TRUE;
605}
606
607static void _page_clear_area_clicked(GtkWidget *widget, gpointer user_data)
608{
609 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
611
612 ps->has_changed = TRUE;
614 gtk_widget_set_sensitive(ps->del, FALSE);
616}
617
618static void _page_delete_area(const dt_lib_module_t *self, const int box_index)
619{
621
622 if(box_index == -1) return;
623
624 for(int k=box_index; k<MAX_IMAGE_PER_PAGE-1; k++)
625 {
626 memcpy(&ps->imgs.box[k], &ps->imgs.box[k+1], sizeof(dt_image_box));
627 }
628 ps->last_selected = -1;
629 ps->selected = -1;
631 ps->imgs.count--;
632
633 if(ps->imgs.count > 0)
634 ps->selected = 0;
635 else
636 gtk_widget_set_sensitive(ps->del, FALSE);
637
639
640 ps->has_changed = TRUE;
642}
643
644static void _page_delete_area_clicked(GtkWidget *widget, gpointer user_data)
645{
646 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
648
650}
651
652static void _print_job_cleanup(void *p)
653{
654 dt_lib_print_job_t *params = p;
655 if(params->pdf_filename[0]) g_unlink(params->pdf_filename);
656 dt_free(params->pdf_page);
657 dt_free(params->buf);
658 dt_free(params->style);
659 dt_free(params->buf_icc_profile);
660 dt_free(params->p_icc_profile);
661 dt_free(params->job_title);
662 dt_free(params);
663}
664
665static void _print_button_clicked(GtkWidget *widget, gpointer user_data)
666{
667 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
669
670 int32_t imgid = UNKNOWN_IMAGE;
671
672 // at least one image on a box
673
674 for(int k=0; k<ps->imgs.count; k++)
675 {
676 if(ps->imgs.box[k].imgid > UNKNOWN_IMAGE)
677 {
678 imgid = ps->imgs.box[k].imgid;
679 break;
680 }
681 }
682
683 if(imgid == UNKNOWN_IMAGE)
684 {
685 dt_control_log(_("cannot print until a picture is selected"));
686 return;
687 }
688 if(strlen(ps->prt.printer.name) == 0 || ps->prt.printer.resolution == 0)
689 {
690 dt_control_log(_("cannot print until a printer is selected"));
691 return;
692 }
693 if(ps->prt.paper.width == 0 || ps->prt.paper.height == 0)
694 {
695 dt_control_log(_("cannot print until a paper is selected"));
696 return;
697 }
698
699 dt_job_t *job = dt_control_job_create(&_print_job_run, "print image %d", imgid);
700 if(IS_NULL_PTR(job)) return;
701
702 dt_lib_print_job_t *params = calloc(1, sizeof(dt_lib_print_job_t));
704
705 memcpy(&params->prt, &ps->prt, sizeof(dt_print_info_t));
706 memcpy(&params->imgs, &ps->imgs, sizeof(ps->imgs));
707
708 // what to call the image?
709 GList *res;
710 if((res = dt_metadata_get(imgid, "Xmp.dc.title", NULL)) != NULL)
711 {
712 // FIXME: in metadata_view.c, non-printables are filtered, should we do this here?
713 params->job_title = g_strdup((gchar *)res->data);
714 g_list_free_full(res, dt_free_gpointer);
715 res = NULL;
716 }
717 else
718 {
719 const dt_image_t *img = dt_image_cache_get(darktable.image_cache, imgid, 'r');
720 if(IS_NULL_PTR(img))
721 {
722 // in this case no need to release from cache what we couldn't get
723 dt_control_log(_("cannot get image %d for printing"), imgid);
725 return;
726 }
727 params->job_title = g_strdup(img->filename);
729 }
730 // FIXME: ellipsize title/printer as the export completed message is ellipsized
731 gchar *message = g_strdup_printf(_("processing `%s' for `%s'"), params->job_title, params->prt.printer.name);
732 dt_control_job_add_progress(job, message, TRUE);
733 dt_free(message);
734
735 // FIXME: getting this from conf as w/prior code, but switch to getting from ps
736 params->style = dt_conf_get_string("plugins/print/print/style");
737
738 // FIXME: getting these from conf as w/prior code, but switch to getting them from ps
739 params->buf_icc_type = dt_conf_get_int("plugins/print/print/icctype");
740 params->buf_icc_profile = dt_conf_get_string("plugins/print/print/iccprofile");
741 params->buf_icc_intent = dt_conf_get_int("plugins/print/print/iccintent");
742
743 params->p_icc_type = ps->v_picctype;
744 params->p_icc_profile = g_strdup(ps->v_piccprofile);
745 params->p_icc_intent = ps->v_pintent;
746 params->black_point_compensation = ps->v_black_point_compensation;
747
749}
750
751static void _set_printer(const dt_lib_module_t *self, const char *printer_name)
752{
754
755 dt_get_printer_info(printer_name, &ps->prt.printer);
756
757 // if this is a turboprint printer, disable the printer profile
758
761
762 dt_conf_set_string("plugins/print/print/printer", printer_name);
763
764 // add papers for the given printer
766 if(ps->paper_list)
767 {
768 g_list_free_full(ps->paper_list, dt_free_gpointer);
769 ps->paper_list = NULL;
770 }
771 ps->paper_list = dt_get_papers (&ps->prt.printer);
772 for(const GList *papers = ps->paper_list; papers; papers = g_list_next (papers))
773 {
774 const dt_paper_info_t *p = (dt_paper_info_t *)papers->data;
775 dt_bauhaus_combobox_add(ps->papers, p->common_name);
776 }
777 const char *default_paper = dt_conf_get_string_const("plugins/print/print/paper");
778 if(!dt_bauhaus_combobox_set_from_text(ps->papers, default_paper))
780
781 const gchar *paper_name = dt_bauhaus_combobox_get_text(ps->papers);
782 if(paper_name)
783 {
784 const dt_paper_info_t *paper = dt_get_paper(ps->paper_list, paper_name);
785 if(paper)
786 memcpy(&ps->prt.paper, paper, sizeof(dt_paper_info_t));
787 }
788
789 // add corresponding supported media
791 if(ps->media_list)
792 {
793 g_list_free_full(ps->media_list, dt_free_gpointer);
794 ps->media_list = NULL;
795 }
797 for(const GList *media = ps->media_list; media; media = g_list_next (media))
798 {
799 const dt_medium_info_t *m = (dt_medium_info_t *)media->data;
800 dt_bauhaus_combobox_add(ps->media, m->common_name);
801 }
802 const char *default_medium = dt_conf_get_string_const("plugins/print/print/medium");
803 if(!dt_bauhaus_combobox_set_from_text(ps->media, default_medium))
805
806 const gchar *medium_name = dt_bauhaus_combobox_get_text(ps->media);
807 if(medium_name)
808 {
809 const dt_medium_info_t *medium = dt_get_medium(ps->media_list, medium_name);
810 if(medium)
811 memcpy(&ps->prt.medium, medium, sizeof(dt_medium_info_t));
812 }
813
814 if(ps->prt.paper.width > 0.0f && ps->prt.paper.height > 0.0f && ps->prt.printer.resolution > 0)
815 {
816 float width, height;
819 }
820
821 dt_view_print_settings(darktable.view_manager, &ps->prt, &ps->imgs);
822}
823
824static void
826{
827 const gchar *printer_name = dt_bauhaus_combobox_get_text(combo);
828
829 if(printer_name)
830 _set_printer (self, printer_name);
831}
832
833static void
835{
837
838 const gchar *paper_name = dt_bauhaus_combobox_get_text(combo);
839
840 if(IS_NULL_PTR(paper_name)) return;
841
842 const dt_paper_info_t *paper = dt_get_paper(ps->paper_list, paper_name);
843
844 if(paper)
845 memcpy(&ps->prt.paper, paper, sizeof(dt_paper_info_t));
846
847 float width, height;
849
851
852 dt_conf_set_string("plugins/print/print/paper", paper_name);
853 dt_view_print_settings(darktable.view_manager, &ps->prt, &ps->imgs);
854
855 _update_slider(ps);
856}
857
858static void
860{
862
863 const gchar *medium_name = dt_bauhaus_combobox_get_text(combo);
864
865 if(IS_NULL_PTR(medium_name)) return;
866
867 const dt_medium_info_t *medium = dt_get_medium(ps->media_list, medium_name);
868
869 if(medium)
870 memcpy(&ps->prt.medium, medium, sizeof(dt_medium_info_t));
871
872 dt_conf_set_string("plugins/print/print/medium", medium_name);
873 dt_view_print_settings(darktable.view_manager, &ps->prt, &ps->imgs);
874
875 _update_slider(ps);
876}
877
878static void
880{
881 dt_view_print_settings(darktable.view_manager, &ps->prt, &ps->imgs);
882
883 // if widget are created, let's display the current image size
884
885 // FIXME: why doesn't this update when units are changed?
886 if(ps->selected != -1
887 && ps->imgs.box[ps->selected].imgid != UNKNOWN_IMAGE
888 && ps->width && ps->height
889 && ps->info)
890 {
891 const dt_image_box *box = &ps->imgs.box[ps->selected];
892
893 dt_image_pos box_size_mm, box_size;
894 dt_printing_get_image_pos_mm(&ps->imgs, box, &box_size_mm);
895 dt_printing_get_image_pos(&ps->imgs, box, &box_size);
896
897 const double w = box_size_mm.width * units[ps->unit];
898 const double h = box_size_mm.height * units[ps->unit];
899 char *value, *precision;
900 int n_digits;
901 _precision_by_unit(ps->unit, &n_digits, NULL, &precision);
902
903 value = g_strdup_printf(precision, w);
904 gtk_label_set_text(GTK_LABEL(ps->width), value);
905 dt_free(value);
906
907 value = g_strdup_printf(precision, h);
908 gtk_label_set_text(GTK_LABEL(ps->height), value);
909 dt_free(value);
911
912 // compute the image down/up scale and report information
913
914 const float iwidth = box->img_width;
915 const float iheight = box->img_height;
916 const float awidth = box_size.width;
917 const float aheight = box_size.height;
918
919 const double scale = (iwidth <= awidth)
920 ? awidth / iwidth
921 : aheight/ iheight;
922
923 value = g_strdup_printf(_("%3.2f (dpi:%d)"), scale,
924 scale <= 1.0
925 ? (int)ps->prt.printer.resolution
926 : (int)(ps->prt.printer.resolution / scale));
927 gtk_label_set_text(GTK_LABEL(ps->info), value);
928 dt_free(value);
929 }
930}
931
932static void
933_top_border_callback(GtkWidget *spin, gpointer user_data)
934{
935 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
937 const double value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin));
938
939 dt_conf_set_float("plugins/print/print/top_margin", value);
940
941 ps->prt.page.margin_top = _to_mm(ps, value);
942
943 if(ps->lock_activated == TRUE)
944 {
945 ps->prt.page.margin_bottom = _to_mm(ps, value);
946 ps->prt.page.margin_left = _to_mm(ps, value);
947 ps->prt.page.margin_right = _to_mm(ps, value);
948
949 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_bottom), value);
950 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_left), value);
951 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_right), value);
952
953 dt_conf_set_float("plugins/print/print/bottom_margin", value);
954 dt_conf_set_float("plugins/print/print/left_margin", value);
955 dt_conf_set_float("plugins/print/print/right_margin", value);
956 }
957
958 _update_slider(ps);
959}
960
961static void
962_bottom_border_callback(GtkWidget *spin, gpointer user_data)
963{
964 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
966 const double value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin));
967
968 dt_conf_set_float("plugins/print/print/bottom_margin", value);
969
970 ps->prt.page.margin_bottom = _to_mm(ps, value);
971 _update_slider(ps);
972}
973
974static void
975_left_border_callback(GtkWidget *spin, gpointer user_data)
976{
977 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
979 const double value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin));
980
981 dt_conf_set_float("plugins/print/print/left_margin", value);
982
983 ps->prt.page.margin_left = _to_mm(ps, value);
984 _update_slider(ps);
985}
986
987static void
988_right_border_callback(GtkWidget *spin, gpointer user_data)
989{
990 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
992 const double value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin));
993
994 dt_conf_set_float("plugins/print/print/right_margin", value);
995
996 ps->prt.page.margin_right = _to_mm(ps, value);
997 _update_slider(ps);
998}
999
1000static void
1001_lock_callback(GtkWidget *button, gpointer user_data)
1002{
1003 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
1005
1006 ps->lock_activated = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
1007
1008 dt_conf_set_bool("plugins/print/print/lock_borders", ps->lock_activated);
1009
1010 gtk_widget_set_sensitive(GTK_WIDGET(ps->b_bottom), !ps->lock_activated);
1011 gtk_widget_set_sensitive(GTK_WIDGET(ps->b_left), !ps->lock_activated);
1012 gtk_widget_set_sensitive(GTK_WIDGET(ps->b_right), !ps->lock_activated);
1013
1014 // get value of top and set it to all other borders
1015
1016 const double value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(ps->b_top));
1017 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_bottom), value);
1018 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_left), value);
1019 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_right), value);
1020
1021 _update_slider (ps);
1022}
1023
1024static void
1025_alignment_callback(GtkWidget *tb, gpointer user_data)
1026{
1027 if(darktable.gui->reset) return;
1028
1029 int index=-1;
1030 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
1032
1033 for(int i=0; i<9; i++)
1034 {
1035 /* block signal handler */
1036 g_signal_handlers_block_by_func(ps->dtba[i],_alignment_callback, user_data);
1037
1038 if(GTK_WIDGET(ps->dtba[i]) == tb)
1039 {
1040 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->dtba[i]), TRUE);
1041 index=i;
1042 }
1043 else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->dtba[i]), FALSE);
1044
1045 /* unblock signal handler */
1046 g_signal_handlers_unblock_by_func(ps->dtba[i], _alignment_callback, user_data);
1047 }
1048
1049 if(ps->last_selected != -1)
1050 {
1052 ps->imgs.box[ps->last_selected].imgid, 100, 100, index);
1053 }
1054
1055 _update_slider(ps);
1056}
1057
1058static void
1067
1068static void
1073
1074static void
1079
1081{
1082 if(darktable.gui->reset) return;
1083
1085 const float value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(ps->grid_size));
1086 dt_conf_set_float("plugins/print/print/grid_size", _to_mm(ps, value));
1087
1089}
1090
1091static void
1093{
1094 if(darktable.gui->reset) return;
1095
1097
1098 const float grid_size = dt_conf_get_float("plugins/print/print/grid_size");
1099
1100 const int unit = dt_bauhaus_combobox_get(combo);
1101 if(unit < 0) return; // shouldn't happen, but it could be -1 if nothing is selected
1102 ps->unit = unit;
1103 dt_conf_set_string("plugins/print/print/unit", _unit_names[unit]);
1104
1105 const double margin_top = ps->prt.page.margin_top;
1106 const double margin_left = ps->prt.page.margin_left;
1107 const double margin_right = ps->prt.page.margin_right;
1108 const double margin_bottom = ps->prt.page.margin_bottom;
1109
1110 int n_digits;
1111 float incr;
1112 _precision_by_unit(ps->unit, &n_digits, &incr, NULL);
1113
1114 ++darktable.gui->reset;
1115
1116 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->b_top), n_digits);
1117 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->b_bottom), n_digits);
1118 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->b_left), n_digits);
1119 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->b_right), n_digits);
1120 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->b_top), incr, 10.f*incr);
1121 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->b_bottom), incr, 10.f*incr);
1122 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->b_left), incr, 10.f*incr);
1123 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->b_right), incr, 10.f*incr);
1124
1125 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->b_x), n_digits);
1126 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->b_y), n_digits);
1127 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->b_width), n_digits);
1128 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->b_height), n_digits);
1129 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->b_x), incr, 10.f*incr);
1130 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->b_y), incr, 10.f*incr);
1131 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->b_width), incr, 10.f*incr);
1132 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->b_height), incr, 10.f*incr);
1133
1134 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(ps->grid_size), n_digits);
1135 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(ps->grid_size), incr, 10.f*incr);
1136
1137 _update_slider(ps);
1138
1139 // convert margins to new unit
1140 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_top), margin_top * units[ps->unit]);
1141 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_bottom), margin_bottom * units[ps->unit]);
1142 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_left), margin_left * units[ps->unit]);
1143 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_right), margin_right * units[ps->unit]);
1144
1145 // grid size
1146 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->grid_size), grid_size * units[ps->unit]);
1147
1148 --darktable.gui->reset;
1149
1150 _fill_box_values(ps);
1151}
1152
1153static void
1155{
1157
1158 if(dt_bauhaus_combobox_get(ps->style) == 0)
1159 {
1160 dt_conf_set_string("plugins/print/print/style", "");
1161 }
1162 else
1163 {
1164 const gchar *style = dt_bauhaus_combobox_get_text(ps->style);
1165 dt_conf_set_string("plugins/print/print/style", style);
1166 }
1167
1168 dt_free(ps->v_style);
1169 ps->v_style = dt_conf_get_string("plugins/print/print/style");
1170}
1171
1172static void
1174{
1176 const int pos = dt_bauhaus_combobox_get(widget);
1177 for(const GList *prof = ps->profiles; prof; prof = g_list_next(prof))
1178 {
1180 if(pp->pos == pos)
1181 {
1182 dt_conf_set_int("plugins/print/print/icctype", pp->type);
1183 dt_conf_set_string("plugins/print/print/iccprofile", pp->filename);
1184 dt_free(ps->v_iccprofile);
1185 ps->v_icctype = pp->type;
1186 ps->v_iccprofile = g_strdup(pp->filename);
1187 return;
1188 }
1189 }
1190 dt_conf_set_int("plugins/print/print/icctype", DT_COLORSPACE_NONE);
1191 dt_conf_set_string("plugins/print/print/iccprofile", "");
1192 dt_free(ps->v_iccprofile);
1194 ps->v_iccprofile = g_strdup("");
1195}
1196
1197static void
1199{
1201 const int pos = dt_bauhaus_combobox_get(widget);
1202 for(const GList *prof = ps->profiles; prof; prof = g_list_next(prof))
1203 {
1205 if(pp->ppos == pos)
1206 {
1207 dt_conf_set_int("plugins/print/printer/icctype", pp->type);
1208 dt_conf_set_string("plugins/print/printer/iccprofile", pp->filename);
1210 ps->v_picctype = pp->type;
1211 ps->v_piccprofile = g_strdup(pp->filename);
1212
1213 // activate the black compensation and printer intent
1214 gtk_widget_set_sensitive(GTK_WIDGET(ps->black_point_compensation), TRUE);
1215 return;
1216 }
1217 }
1218 dt_conf_set_int("plugins/print/printer/icctype", DT_COLORSPACE_NONE);
1219 dt_conf_set_string("plugins/print/printer/iccprofile", "");
1222 ps->v_piccprofile = g_strdup("");
1223 gtk_widget_set_sensitive(GTK_WIDGET(ps->black_point_compensation), FALSE);
1224}
1225
1226static void
1228{
1230 const int pos = dt_bauhaus_combobox_get(widget);
1231 dt_conf_set_int("plugins/print/printer/iccintent", pos);
1232 ps->v_pintent = pos;
1233 ps->prt.printer.intent = pos;
1234}
1235
1236static void
1238{
1240 ps->v_black_point_compensation = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ps->black_point_compensation));
1241 dt_conf_set_bool("plugins/print/print/black_point_compensation", ps->v_black_point_compensation);
1242}
1243
1244static void
1246{
1248 const int pos = dt_bauhaus_combobox_get(widget);
1249 // record the intent that will override the out rendering module on export
1250 dt_conf_set_int("plugins/print/print/iccintent", pos - 1);
1251 ps->v_intent = pos - 1;
1252}
1253
1254static void _set_orientation(dt_lib_print_settings_t *ps, int32_t imgid)
1255{
1258 imgid, DT_MIPMAP_0, DT_MIPMAP_BLOCKING, 'r');
1259
1260 // If there's a mipmap available, figure out orientation based upon
1261 // its dimensions. Otherwise, don't touch orientation until the
1262 // mipmap arrives.
1263 if(buf.size != DT_MIPMAP_NONE)
1264 {
1265 ps->prt.page.landscape = (buf.width > buf.height);
1266 dt_view_print_settings(darktable.view_manager, &ps->prt, &ps->imgs);
1268 }
1269
1272}
1273
1274static void _print_settings_activate_or_update_callback(gpointer instance, int32_t imgid, gpointer user_data)
1275{
1276 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
1278
1279 // load an image with a simple click on the filmstrip only if a single image is present
1280 if(ps->imgs.count == 1)
1281 {
1282 if(ps->has_changed)
1283 {
1284 dt_printing_setup_image(&ps->imgs, 0, imgid, 100, 100, ps->imgs.box[0].alignment);
1285 }
1286 else
1287 {
1288 _set_orientation(ps, imgid);
1290 ps->imgs.imgid_to_load = imgid;
1292 }
1293 }
1294}
1295
1296static GList* _get_profiles()
1297{
1298 // Create list of profiles
1299 GList *list = NULL;
1300
1302 prof->type = DT_COLORSPACE_SRGB;
1303 dt_utf8_strlcpy(prof->name, _("sRGB (web-safe)"), sizeof(prof->name));
1304 prof->pos = -2;
1305 prof->ppos = -2;
1306 list = g_list_prepend(list, prof);
1307
1308 prof = (dt_lib_export_profile_t *)g_malloc0(sizeof(dt_lib_export_profile_t));
1310 dt_utf8_strlcpy(prof->name, _("Adobe RGB (compatible)"), sizeof(prof->name));
1311 prof->pos = -2;
1312 prof->ppos = -2;
1313 list = g_list_prepend(list, prof);
1314
1315 // add the profiles from datadir/color/out/*.icc
1316 for(GList *iter = darktable.color_profiles->profiles; iter; iter = g_list_next(iter))
1317 {
1319 if(p->type == DT_COLORSPACE_FILE)
1320 {
1321 prof = (dt_lib_export_profile_t *)g_malloc0(sizeof(dt_lib_export_profile_t));
1322 g_strlcpy(prof->name, p->name, sizeof(prof->name));
1323 g_strlcpy(prof->filename, p->filename, sizeof(prof->filename));
1324 prof->type = DT_COLORSPACE_FILE;
1325 prof->pos = -2;
1326 prof->ppos = -2;
1327 list = g_list_prepend(list, prof);
1328 }
1329 }
1330
1331 return g_list_reverse(list); // list was built in reverse order, so un-reverse it
1332}
1333
1334static void _new_printer_callback(dt_printer_info_t *printer, void *user_data)
1335{
1336 static int count = 0;
1337 const dt_lib_module_t *self = (dt_lib_module_t *)user_data;
1339
1340 char *default_printer = dt_conf_get_string("plugins/print/print/printer");
1341
1342 g_signal_handlers_block_by_func(G_OBJECT(d->printers), G_CALLBACK(_printer_changed), NULL);
1343
1344 dt_bauhaus_combobox_add(d->printers, printer->name);
1345
1346 if(!g_strcmp0(default_printer, printer->name) || default_printer[0]=='\0')
1347 {
1348 dt_bauhaus_combobox_set(d->printers, count);
1349 _set_printer(self, printer->name);
1350 }
1351 count++;
1352 dt_free(default_printer);
1353
1354 g_signal_handlers_unblock_by_func(G_OBJECT(d->printers), G_CALLBACK(_printer_changed), NULL);
1355}
1356
1357void view_enter(struct dt_lib_module_t *self,struct dt_view_t *old_view,struct dt_view_t *new_view)
1358{
1360
1361 // Re-publish the settings payload on each entry so the print view never
1362 // keeps a stale or not-yet-initialized images box between switches.
1363 dt_view_print_settings(darktable.view_manager, &ps->prt, &ps->imgs);
1364
1365 // user activated a new image via the filmstrip or user entered view
1366 // mode which activates an image: get image_id and orientation
1369
1370 // NOTE: it would be proper to set image_id here to -1, but this seems to make no difference
1371}
1372
1373void view_leave(struct dt_lib_module_t *self,struct dt_view_t *old_view,struct dt_view_t *new_view)
1374{
1377 self);
1378}
1379
1380void _get_control(dt_lib_print_settings_t *ps, float x, float y)
1381{
1382 const float dist = 20.0;
1383
1384 const dt_image_box *b = &ps->imgs.box[ps->selected];
1385
1386 ps->sel_controls = 0;
1387
1388 if(fabsf(b->screen.x - x) < dist)
1389 ps->sel_controls |= BOX_LEFT;
1390
1391 if(fabsf(b->screen.y - y) < dist)
1392 ps->sel_controls |= BOX_TOP;
1393
1394 if(fabsf((b->screen.x + b->screen.width) - x) < dist)
1395 ps->sel_controls |= BOX_RIGHT;
1396
1397 if(fabsf((b->screen.y + b->screen.height) - y) < dist)
1398 ps->sel_controls |= BOX_BOTTOM;
1399
1400 if(ps->sel_controls == 0) ps->sel_controls = BOX_ALL;
1401}
1402
1404{
1406
1407 if(ps->last_selected != -1)
1408 {
1410 }
1411
1412 return 0;
1413}
1414
1415static void _snap_to_grid(dt_lib_print_settings_t *ps, float *x, float *y)
1416{
1417 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ps->snap_grid)))
1418 {
1419 // V lines
1420 const float step = gtk_spin_button_get_value(GTK_SPIN_BUTTON(ps->grid_size)) * units[ps->unit];
1421
1422 // only display the grid if a step of 5 pixels
1423 const float diff = DT_PIXEL_APPLY_DPI(5);
1424
1425 float grid_pos = (float)ps->imgs.screen.page.x;
1426
1427 const float h_step = _mm_to_hscreen(ps, step, FALSE);
1428
1429 while(grid_pos < ps->imgs.screen.page.x + ps->imgs.screen.page.width)
1430 {
1431 if(fabsf(*x - grid_pos) < diff) *x = grid_pos;
1432 grid_pos += h_step;
1433 }
1434
1435 // H lines
1436 grid_pos = (float)ps->imgs.screen.page.y;
1437
1438 const float v_step = _mm_to_vscreen(ps, step, FALSE);
1439
1440 while(grid_pos < ps->imgs.screen.page.y + ps->imgs.screen.page.height)
1441 {
1442 if(fabsf(*y - grid_pos) < diff) *y = grid_pos;
1443 grid_pos += v_step;
1444 }
1445 }
1446 // FIXME: should clamp values to page size here?
1447}
1448
1449int mouse_moved(struct dt_lib_module_t *self, double x, double y, double pressure, int which)
1450{
1452
1453 gboolean expose = FALSE;
1454
1455 if(ps->creation)
1456 dt_control_change_cursor(GDK_PLUS);
1457
1458 if(ps->creation && ps->dragging)
1459 {
1460 ps->x2 = x;
1461 ps->y2 = y;
1462 _snap_to_grid(ps, &ps->x2, &ps->y2);
1463 expose = TRUE;
1464 }
1465 else if(ps->dragging)
1466 {
1467 dt_image_box *b = &ps->imgs.box[ps->selected];
1468 const float dx = x - ps->click_pos_x;
1469 const float dy = y - ps->click_pos_y;
1470 const float coef = dx / b->screen.width;
1471
1472 switch(ps->sel_controls)
1473 {
1474 case BOX_ALL:
1475 ps->x1 = b->screen.x + dx;
1476 ps->y1 = b->screen.y + dy;
1477 ps->x2 = b->screen.x + b->screen.width + dx;
1478 ps->y2 = b->screen.y + b->screen.height + dy;
1479 break;
1480 case BOX_LEFT:
1481 ps->x1 = b->screen.x + dx;
1482 break;
1483 case BOX_TOP:
1484 ps->y1 = b->screen.y + dy;
1485 break;
1486 case BOX_RIGHT:
1487 ps->x2 = b->screen.x + b->screen.width + dx;
1488 break;
1489 case BOX_BOTTOM:
1490 ps->y2 = b->screen.y + b->screen.height + dy;
1491 break;
1492 case BOX_TOP_LEFT:
1493 ps->x1 = b->screen.x + dx;
1494 ps->y1 = b->screen.y + (coef * b->screen.height);
1495 break;
1496 case BOX_TOP_RIGHT:
1497 ps->x2 = b->screen.x + b->screen.width + dx;
1498 ps->y1 = b->screen.y - (coef * b->screen.height);
1499 break;
1500 case BOX_BOTTOM_LEFT:
1501 ps->x1 = b->screen.x + dx;
1502 ps->y2 = b->screen.y + b->screen.height - (coef * b->screen.height);
1503 break;
1504 case BOX_BOTTOM_RIGHT:
1505 ps->x2 = b->screen.x + b->screen.width + dx;
1506 ps->y2 = b->screen.y + b->screen.height + (coef * b->screen.height);
1507 break;
1508 default:
1509 break;
1510 }
1511 expose = TRUE;
1512
1513 _snap_to_grid(ps, &ps->x1, &ps->y1);
1514 _snap_to_grid(ps, &ps->x2, &ps->y2);
1515 }
1516 else if(!ps->creation)
1517 {
1518 const int bidx = dt_printing_get_image_box(&ps->imgs, x, y);
1519 ps->sel_controls = 0;
1520
1521 if(bidx == -1)
1522 {
1523 if(ps->selected != -1) expose = TRUE;
1524 ps->selected = -1;
1525 }
1526 else
1527 {
1528 expose = TRUE;
1529 ps->selected = bidx;
1530 _fill_box_values(ps);
1531 _get_control(ps, x, y);
1532 }
1533 }
1534
1536
1537 return 0;
1538}
1539
1540static void _swap(float *a, float *b)
1541{
1542 const float tmp = *a;
1543 *a = *b;
1544 *b = tmp;
1545}
1546
1547int button_released(struct dt_lib_module_t *self, double x, double y, int which, uint32_t state)
1548{
1550
1551 if(ps->dragging)
1552 {
1553 int idx = -1;
1554
1555 gtk_widget_set_sensitive(ps->del, TRUE);
1556
1557 // handle new area
1558 if(ps->creation)
1559 {
1560 idx = ps->imgs.count++;
1561 }
1562 else if(ps->selected != -1)
1563 {
1564 idx = ps->selected;
1565 }
1566
1567 if(idx != -1)
1568 {
1569 // make sure the area is in the the printable area taking into account the margins
1570
1571 // don't allow a too small area
1572 if(ps->x2 < ps->x1) _swap(&ps->x1, &ps->x2);
1573 if(ps->y2 < ps->y1) _swap(&ps->y1, &ps->y2);
1574
1575 const float dx = ps->x2 - ps->x1;
1576 const float dy = ps->y2 - ps->y1;
1577
1578 dt_printing_setup_box(&ps->imgs, idx, ps->x1, ps->y1, dx, dy);
1579 // make the new created box the last edited one
1580 ps->last_selected = idx;
1581 _fill_box_values(ps);
1582 }
1583 }
1584
1585 _update_slider(ps);
1586
1587 ps->creation = FALSE;
1588 ps->dragging = FALSE;
1589
1590 dt_control_change_cursor(GDK_LEFT_PTR);
1591
1592 return 0;
1593}
1594
1595int button_pressed(struct dt_lib_module_t *self, double x, double y, double pressure,
1596 int which, int type, uint32_t state)
1597{
1599
1600 ps->click_pos_x = x;
1601 ps->click_pos_y = y;
1602 ps->last_selected = -1;
1603
1604 if(ps->creation)
1605 {
1606 ps->dragging = TRUE;
1607 ps->selected = -1;
1608 ps->x1 = ps->x2 = x;
1609 ps->y1 = ps->y2 = y;
1610
1611 _snap_to_grid(ps, &ps->x1, &ps->y1);
1612 }
1613 else if(ps->selected > 0
1614 && (which == 2 || (which == 1 && dt_modifier_is(state, GDK_CONTROL_MASK))))
1615 {
1616 // middle click (or ctrl-click), move selected image down
1617 dt_image_box b;
1618 memcpy(&b, &ps->imgs.box[ps->selected], sizeof(dt_image_box));
1619 memcpy(&ps->imgs.box[ps->selected], &ps->imgs.box[ps->selected-1], sizeof(dt_image_box));
1620 memcpy(&ps->imgs.box[ps->selected-1], &b, sizeof(dt_image_box));
1621 }
1622 else if(ps->selected != -1 && which == 1)
1623 {
1624 dt_image_box *b = &ps->imgs.box[ps->selected];
1625
1626 ps->dragging = TRUE;
1627 ps->x1 = b->screen.x;
1628 ps->y1 = b->screen.y;
1629 ps->x2 = b->screen.x + b->screen.width;
1630 ps->y2 = b->screen.y + b->screen.height;
1631
1632 ps->last_selected = ps->selected;
1633 ps->has_changed = TRUE;
1634
1635 _get_control(ps, x, y);
1636
1637 dt_control_change_cursor(GDK_HAND1);
1638 }
1639 else if(ps->selected != -1 && which == 3)
1640 {
1641 dt_image_box *b = &ps->imgs.box[ps->selected];
1642
1643 // if image present remove it, otherwise remove the box
1644 if(b->imgid != UNKNOWN_IMAGE)
1645 b->imgid = UNKNOWN_IMAGE;
1646 else
1647 _page_delete_area(self, ps->selected);
1648
1649 ps->last_selected = ps->selected;
1650 ps->has_changed = TRUE;
1651 }
1652
1653 return 0;
1654}
1655
1656void _cairo_rectangle(cairo_t *cr, const int sel_controls,
1657 const int x1, const int y1, const int x2, const int y2)
1658{
1659 const float sel_width = DT_PIXEL_APPLY_DPI(3.0);
1660 const float std_width = DT_PIXEL_APPLY_DPI(1.0);
1661
1662 const gboolean all = sel_controls == BOX_ALL;
1663
1664 cairo_move_to(cr, x1, y1);
1665 cairo_set_line_width(cr, (all || sel_controls == BOX_LEFT) ? sel_width : std_width);
1666 cairo_line_to(cr, x1, y2);
1667 cairo_stroke(cr);
1668
1669 cairo_move_to(cr, x1, y2);
1670 cairo_set_line_width(cr, (all || sel_controls == BOX_BOTTOM) ? sel_width : std_width);
1671 cairo_line_to(cr, x2, y2);
1672 cairo_stroke(cr);
1673
1674 cairo_move_to(cr, x2, y2);
1675 cairo_set_line_width(cr, (all || sel_controls == BOX_RIGHT) ? sel_width : std_width);
1676 cairo_line_to(cr, x2, y1);
1677 cairo_stroke(cr);
1678
1679 cairo_move_to(cr, x2, y1);
1680 cairo_set_line_width(cr, (all || sel_controls == BOX_TOP) ? sel_width : std_width);
1681 cairo_line_to(cr, x1, y1);
1682 cairo_stroke(cr);
1683
1684 if(sel_controls == 0)
1685 {
1686 const double dash[] = { DT_PIXEL_APPLY_DPI(3.0), DT_PIXEL_APPLY_DPI(3.0) };
1687 cairo_set_dash(cr, dash, 2, 0);
1688
1689 // no image inside
1690 cairo_move_to(cr, x1, y1);
1691 cairo_line_to(cr, x2, y2);
1692
1693 cairo_move_to(cr, x1, y2);
1694 cairo_line_to(cr, x2, y1);
1695 cairo_stroke(cr);
1696 }
1697
1698 cairo_set_dash(cr, NULL, 0, 0);
1699 cairo_set_line_width(cr, sel_width);
1700
1701 if(sel_controls == BOX_TOP_LEFT)
1702 {
1703 cairo_rectangle (cr, x1, y1, DT_PIXEL_APPLY_DPI(15), DT_PIXEL_APPLY_DPI(15));
1704 cairo_stroke(cr);
1705 }
1706
1707 if(sel_controls == BOX_TOP_RIGHT)
1708 {
1709 cairo_rectangle (cr, x2 - DT_PIXEL_APPLY_DPI(15), y1,
1711 cairo_stroke(cr);
1712 }
1713
1714 if(sel_controls == BOX_BOTTOM_LEFT)
1715 {
1716 cairo_rectangle (cr, x1, y2 - DT_PIXEL_APPLY_DPI(15),
1718 cairo_stroke(cr);
1719 }
1720
1721 if(sel_controls == BOX_BOTTOM_RIGHT)
1722 {
1723 cairo_rectangle (cr, x2 - DT_PIXEL_APPLY_DPI(15), y2 - DT_PIXEL_APPLY_DPI(15),
1725 cairo_stroke(cr);
1726 }
1727}
1728
1729void gui_post_expose(struct dt_lib_module_t *self, cairo_t *cr, int32_t width, int32_t height,
1730 int32_t pointerx, int32_t pointery)
1731{
1733
1734 // display grid
1735
1736 // 1mm
1737
1738 const float step = gtk_spin_button_get_value(GTK_SPIN_BUTTON(ps->grid_size)) / units[ps->unit];
1739
1740 // only display grid if spacing more than 5 pixels
1741 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ps->grid))
1742 && (int)_mm_to_hscreen(ps, step, FALSE) > DT_PIXEL_APPLY_DPI(5))
1743 {
1744 const double dash[] = { DT_PIXEL_APPLY_DPI(5.0), DT_PIXEL_APPLY_DPI(5.0) };
1745 cairo_set_source_rgba(cr, 1, .2, .2, 0.6);
1746
1747 // V lines
1748 float grid_pos = (float)ps->imgs.screen.page.x;
1749
1750 const float h_step = _mm_to_hscreen(ps, step, FALSE);
1751 int n = 0;
1752
1753 while(grid_pos < ps->imgs.screen.page.x + ps->imgs.screen.page.width)
1754 {
1755 cairo_set_dash(cr, dash, ((n % 5) == 0) ? 0 : 2, DT_PIXEL_APPLY_DPI(5));
1756 cairo_set_line_width(cr, ((n % 5) == 0) ? DT_PIXEL_APPLY_DPI(1.0) : DT_PIXEL_APPLY_DPI(0.5));
1757 cairo_move_to(cr, grid_pos, ps->imgs.screen.page.y);
1758 cairo_line_to(cr, grid_pos, ps->imgs.screen.page.y + ps->imgs.screen.page.height);
1759 cairo_stroke(cr);
1760 grid_pos += h_step;
1761 n++;
1762 }
1763
1764 // H lines
1765 grid_pos = (float)ps->imgs.screen.page.y;
1766
1767 const float v_step = _mm_to_vscreen(ps, step, FALSE);
1768 n = 0;
1769
1770 while(grid_pos < ps->imgs.screen.page.y + ps->imgs.screen.page.height)
1771 {
1772 cairo_set_dash(cr, dash, ((n % 5) == 0) ? 0 : 2, DT_PIXEL_APPLY_DPI(5));
1773 cairo_set_line_width(cr, ((n % 5) == 0) ? DT_PIXEL_APPLY_DPI(1.0) : DT_PIXEL_APPLY_DPI(0.5));
1774 cairo_move_to(cr, ps->imgs.screen.page.x, grid_pos);
1775 cairo_line_to(cr, ps->imgs.screen.page.x + ps->imgs.screen.page.width, grid_pos);
1776 cairo_stroke(cr);
1777 grid_pos += v_step;
1778 n++;
1779 }
1780 }
1781
1782 // disable dash
1783 cairo_set_source_rgba(cr, 1, .2, .2, 0.6);
1784 cairo_set_dash(cr, NULL, 0, 0);
1785
1786 for(int k=0; k<ps->imgs.count; k++)
1787 {
1788 dt_image_box *img = &ps->imgs.box[k];
1789
1790 if(k == ps->selected || img->imgid == UNKNOWN_IMAGE)
1791 {
1792 cairo_set_source_rgba(cr, .4, .4, .4, 1.0);
1793 _cairo_rectangle(cr, (k == ps->selected) ? ps->sel_controls : 0,
1794 img->screen.x, img->screen.y,
1795 img->screen.x + img->screen.width, img->screen.y + img->screen.height);
1796 cairo_stroke(cr);
1797 }
1798
1799 if(k == ps->imgs.motion_over)
1800 {
1801 cairo_set_source_rgba(cr, .2, .2, .2, 1.0);
1802 cairo_rectangle(cr, img->screen.x, img->screen.y, img->screen.width, img->screen.height);
1803 cairo_fill(cr);
1804 }
1805 }
1806
1807 // now display new area if any
1808 if(ps->dragging || ps->selected != -1)
1809 {
1810 float dx1, dy1, dx2, dy2, dwidth, dheight; // displayed values
1811 float x1, y1, x2, y2; // box screen coordinates
1812
1813 float pwidth, pheight;
1814 _get_page_dimension(&ps->prt, &pwidth, &pheight);
1815
1816 if(ps->dragging)
1817 {
1818 x1 = ps->x1;
1819 y1 = ps->y1;
1820 x2 = ps->x2;
1821 y2 = ps->y2;
1822
1823 dx1 = _hscreen_to_mm(ps, ps->x1, TRUE) * units[ps->unit];
1824 dy1 = _vscreen_to_mm(ps, ps->y1, TRUE) * units[ps->unit];
1825 dx2 = _hscreen_to_mm(ps, ps->x2, TRUE) * units[ps->unit];
1826 dy2 = _vscreen_to_mm(ps, ps->y2, TRUE) * units[ps->unit];
1827 dwidth = fabsf(dx2 - dx1);
1828 dheight = fabsf(dy2 - dy1);
1829 }
1830 else
1831 {
1832 const dt_image_box *box = &ps->imgs.box[ps->selected];
1833
1834 // we could use a simpler solution but we want to use the same formulae used
1835 // to fill the editable box values to avoid discrepancies between values due
1836 // to rounding errors.
1837
1838 dx1 = _percent_unit_of(ps, pwidth, box->pos.x);
1839 dy1 = _percent_unit_of(ps, pheight, box->pos.y);
1840 dwidth = _percent_unit_of(ps, pwidth, box->pos.width);
1841 dheight = _percent_unit_of(ps, pheight, box->pos.height);
1842 dx2 = dx1 + dwidth;
1843 dy2 = dy1 + dheight;
1844
1845 x1 = box->screen.x;
1846 y1 = box->screen.y;
1847 x2 = box->screen.x + box->screen.width;
1848 y2 = box->screen.y + box->screen.height;
1849 }
1850
1851 cairo_set_source_rgba(cr, .4, .4, .4, 1.0);
1852 _cairo_rectangle(cr, ps->sel_controls, x1, y1, x2, y2);
1853
1854 // display corner coordinates
1855 // FIXME: here and elsewhere eliminate hardcoded RGB values -- use CSS
1856 char dimensions[16];
1857 PangoLayout *layout;
1858 PangoRectangle ext;
1859 PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc);
1860 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
1861 pango_font_description_set_absolute_size(desc, DT_PIXEL_APPLY_DPI(16) * PANGO_SCALE);
1862 layout = pango_cairo_create_layout(cr);
1863 pango_layout_set_font_description(layout, desc);
1864 const double text_h = DT_PIXEL_APPLY_DPI(16+2);
1865 const double margin = DT_PIXEL_APPLY_DPI(6);
1866 const double dash = DT_PIXEL_APPLY_DPI(4.0);
1867 int n_digits;
1868 char *precision;
1869 _precision_by_unit(ps->unit, &n_digits, NULL, &precision);
1870 double xp, yp;
1871
1872 yp = y1 + (y2 - y1 - text_h) * 0.5;
1873
1874 if(x1 >= ps->imgs.screen.page.x && x1 <= (ps->imgs.screen.page.x + ps->imgs.screen.page.width))
1875 {
1876 snprintf(dimensions, sizeof(dimensions), precision, dx1);
1877 pango_layout_set_text(layout, dimensions, -1);
1878 pango_layout_get_pixel_extents(layout, NULL, &ext);
1879 xp = ps->imgs.screen.page.x + (x1 - text_h - ps->imgs.screen.page.x - ext.width) * 0.5;
1880 if(xp < ps->imgs.screen.page.x + 3 * margin)
1881 {
1882 xp = x1 + 2 * margin;
1883 // somewhat hacky, assumes that all numeric labels are about
1884 // the same width
1885 yp = MIN(y2 - text_h, yp + ext.width + 0.5 * text_h + margin * 3);
1886 }
1887 cairo_set_source_rgba(cr, .7, .7, .7, .9);
1888 cairo_move_to(cr, ps->imgs.screen.page.x, yp + text_h * 0.5);
1889 cairo_line_to(cr, x1, yp + text_h * 0.5);
1890 cairo_stroke_preserve(cr);
1891 cairo_set_source_rgba(cr, .5, .5, .5, .9);
1892 cairo_set_dash(cr, &dash, 1, dash);
1893 cairo_stroke(cr);
1894 cairo_set_dash(cr, NULL, 0, 0);
1895 dt_gui_draw_rounded_rectangle(cr, ext.width + 2 * margin, text_h + 2 * margin, xp - margin, yp - margin);
1896 cairo_set_source_rgb(cr, .8, .8, .8);
1897 cairo_move_to(cr, xp, yp);
1898 pango_cairo_show_layout(cr, layout);
1899 }
1900
1901 if(x2 >= ps->imgs.screen.page.x && x2 <= (ps->imgs.screen.page.x + ps->imgs.screen.page.width))
1902 {
1903 snprintf(dimensions, sizeof(dimensions), precision, pwidth * units[ps->unit] - dx2);
1904 pango_layout_set_text(layout, dimensions, -1);
1905 pango_layout_get_pixel_extents(layout, NULL, &ext);
1906 xp = x2 + (ps->imgs.screen.page.x + ps->imgs.screen.page.width - x2 - ext.width) * 0.5;
1907 if(xp + ext.width + margin > ps->imgs.screen.page.x + ps->imgs.screen.page.width)
1908 xp = x2 - ext.width - 2 * margin;
1909 cairo_set_source_rgba(cr, .7, .7, .7, .9);
1910 cairo_move_to(cr, x2, yp + text_h * 0.5);
1911 cairo_line_to(cr, ps->imgs.screen.page.x + ps->imgs.screen.page.width, yp + text_h * 0.5);
1912 cairo_stroke_preserve(cr);
1913 cairo_set_source_rgba(cr, .5, .5, .5, .9);
1914 cairo_set_dash(cr, &dash, 1, dash);
1915 cairo_stroke(cr);
1916 cairo_set_dash(cr, NULL, 0, 0);
1917 dt_gui_draw_rounded_rectangle(cr, ext.width + 2 * margin, text_h + 2 * margin,
1918 xp - margin, yp - margin);
1919 cairo_set_source_rgb(cr, .8, .8, .8);
1920 cairo_move_to(cr, xp, yp);
1921 pango_cairo_show_layout(cr, layout);
1922 }
1923
1924 xp = x1 + (x2 - x1 - text_h) * 0.5;
1925
1926 if(y1 >= ps->imgs.screen.page.y && y1 <= (ps->imgs.screen.page.y + ps->imgs.screen.page.height))
1927 {
1928 snprintf(dimensions, sizeof(dimensions), precision, dy1);
1929 pango_layout_set_text(layout, dimensions, -1);
1930 pango_layout_get_pixel_extents(layout, NULL, &ext);
1931 yp = ps->imgs.screen.page.y + (y1 - text_h - ps->imgs.screen.page.y - ext.width) * 0.5;
1932 if(yp < ps->imgs.screen.page.y + 3 * margin)
1933 {
1934 xp = MIN(x2 - text_h, xp + ext.width + 0.5 * text_h + margin * 3);
1935 yp = y1 + 2 * margin;
1936 }
1937 cairo_set_source_rgba(cr, .7, .7, .7, .9);
1938 cairo_move_to(cr, xp + text_h * 0.5, ps->imgs.screen.page.y);
1939 cairo_line_to(cr, xp + text_h * 0.5, y1);
1940 cairo_stroke_preserve(cr);
1941 cairo_set_source_rgba(cr, .5, .5, .5, .9);
1942 cairo_set_dash(cr, &dash, 1, dash);
1943 cairo_stroke(cr);
1944 cairo_set_dash(cr, NULL, 0, 0);
1945 dt_gui_draw_rounded_rectangle(cr, text_h + 2 * margin, ext.width + 2 * margin,
1946 xp - margin, yp - margin);
1947 cairo_set_source_rgb(cr, .8, .8, .8);
1948 cairo_move_to(cr, xp + text_h * 0.5, yp + ext.width * 0.5);
1949 cairo_save(cr);
1950 cairo_rotate(cr, -M_PI_2);
1951 cairo_rel_move_to(cr, -0.5 * ext.width, -0.5 * text_h);
1952 pango_cairo_update_layout(cr, layout);
1953 pango_cairo_show_layout(cr, layout);
1954 cairo_restore(cr);
1955 }
1956
1957 if(y2 >= ps->imgs.screen.page.y && y2 <= (ps->imgs.screen.page.y + ps->imgs.screen.page.height))
1958 {
1959 snprintf(dimensions, sizeof(dimensions), precision, pheight * units[ps->unit] - dy2);
1960 pango_layout_set_text(layout, dimensions, -1);
1961 pango_layout_get_pixel_extents(layout, NULL, &ext);
1962 yp = y2 + (ps->imgs.screen.page.y + ps->imgs.screen.page.height - y2 - ext.width) * 0.5;
1963 if(yp + ext.width + margin > ps->imgs.screen.page.y + ps->imgs.screen.page.height)
1964 yp = y2 - ext.width - 2 * margin;
1965 cairo_set_source_rgba(cr, .7, .7, .7, .9);
1966 cairo_move_to(cr, xp + text_h * 0.5, y2);
1967 cairo_line_to(cr, xp + text_h * 0.5, ps->imgs.screen.page.y + ps->imgs.screen.page.height);
1968 cairo_stroke_preserve(cr);
1969 cairo_set_source_rgba(cr, .5, .5, .5, .9);
1970 cairo_set_dash(cr, &dash, 1, dash);
1971 cairo_stroke(cr);
1972 cairo_set_dash(cr, NULL, 0, 0);
1973 dt_gui_draw_rounded_rectangle(cr, text_h + 2 * margin, ext.width + 2 * margin,
1974 xp - margin, yp - margin);
1975 cairo_set_source_rgb(cr, .8, .8, .8);
1976 cairo_move_to(cr, xp + text_h * 0.5, yp + ext.width * 0.5);
1977 cairo_save(cr);
1978 cairo_rotate(cr, -M_PI_2);
1979 cairo_rel_move_to(cr, -0.5 * ext.width, -0.5 * text_h);
1980 pango_cairo_update_layout(cr, layout);
1981 pango_cairo_show_layout(cr, layout);
1982 cairo_restore(cr);
1983 }
1984
1985 // display width and height
1986 snprintf(dimensions, sizeof(dimensions), precision, dwidth);
1987 pango_layout_set_text(layout, dimensions, -1);
1988 pango_layout_get_pixel_extents(layout, NULL, &ext);
1989 xp = (x1 + x2 - ext.width) * .5;
1990 if(y1 > text_h * 0.5 + margin)
1991 yp = y1 - text_h * 0.5;
1992 else
1993 yp = y1 + text_h - 2 * margin;
1994 cairo_set_source_rgba(cr, .5, .5, .5, .9);
1995 dt_gui_draw_rounded_rectangle(cr, ext.width + 2 * margin, text_h + 2 * margin,
1996 xp - margin, yp - margin);
1997 cairo_set_source_rgb(cr, .8, .8, .8);
1998 cairo_move_to(cr, xp, yp);
1999 pango_cairo_show_layout(cr, layout);
2000
2001 snprintf(dimensions, sizeof(dimensions), precision, dheight);
2002 pango_layout_set_text(layout, dimensions, -1);
2003 pango_layout_get_pixel_extents(layout, NULL, &ext);
2004 if(x1 > text_h * 0.5 + margin)
2005 xp = x1 - text_h * 0.5;
2006 else
2007 xp = x1 + text_h - 2 * margin;
2008 yp = (y1 + y2) * .5;
2009 cairo_set_source_rgba(cr, .5, .5, .5, .9);
2010 dt_gui_draw_rounded_rectangle(cr, text_h + 2 * margin, ext.width + 2 * margin,
2011 xp - margin, yp - margin - 0.5 * ext.width);
2012 cairo_set_source_rgb(cr, .8, .8, .8);
2013 cairo_move_to(cr, xp + text_h * 0.5, yp);
2014 cairo_save(cr);
2015 cairo_rotate(cr, -M_PI_2);
2016 cairo_rel_move_to(cr, -0.5 * ext.width, -0.5 * text_h);
2017 pango_cairo_update_layout(cr, layout);
2018 pango_cairo_show_layout(cr, layout);
2019 cairo_restore(cr);
2020
2021 pango_font_description_free(desc);
2022 g_object_unref(layout);
2024 }
2025
2026 if(ps->imgs.screen.borderless)
2027 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->borderless), TRUE);
2028 else
2029 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->borderless), FALSE);
2030}
2031
2032static void _width_changed(GtkWidget *widget, gpointer user_data)
2033{
2034 if(darktable.gui->reset) return;
2035
2037
2038 const float nv = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
2039 const float nv_mm = nv / units[ps->unit];
2040
2041 dt_image_box *box = &ps->imgs.box[ps->last_selected];
2042
2044 box->screen.x, box->screen.y,
2045 _mm_to_hscreen(ps, nv_mm, FALSE), box->screen.height);
2046
2047 ps->has_changed = TRUE;
2049}
2050
2051static void _height_changed(GtkWidget *widget, gpointer user_data)
2052{
2053 if(darktable.gui->reset) return;
2054
2056
2057 const float nv = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
2058 const float nv_mm = nv / units[ps->unit];
2059
2060 dt_image_box *box = &ps->imgs.box[ps->last_selected];
2061
2063 box->screen.x, box->screen.y,
2064 box->screen.width, _mm_to_vscreen(ps, nv_mm, FALSE));
2065
2066 ps->has_changed = TRUE;
2068}
2069
2070static void _x_changed(GtkWidget *widget, gpointer user_data)
2071{
2072 if(darktable.gui->reset) return;
2073
2075
2076 const float nv = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
2077 const float nv_mm = nv / units[ps->unit];
2078
2079 dt_image_box *box = &ps->imgs.box[ps->last_selected];
2080
2082 _mm_to_hscreen(ps, nv_mm, TRUE), box->screen.y,
2083 box->screen.width, box->screen.height);
2084
2085 ps->has_changed = TRUE;
2087}
2088
2089static void _y_changed(GtkWidget *widget, gpointer user_data)
2090{
2091 if(darktable.gui->reset) return;
2092
2094
2095 const float nv = gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
2096 const float nv_mm = nv / units[ps->unit];
2097
2098 dt_image_box *box = &ps->imgs.box[ps->last_selected];
2099
2101 box->screen.x, _mm_to_vscreen(ps, nv_mm, TRUE),
2102 box->screen.width, box->screen.height);
2103
2104 ps->has_changed = TRUE;
2106}
2107
2109{
2111 self->data = d;
2112 self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
2113 dt_gui_add_help_link(self->widget, dt_get_help_url("print_overview"));
2114
2115 char datadir[PATH_MAX] = { 0 };
2116 char confdir[PATH_MAX] = { 0 };
2117 dt_loc_get_user_config_dir(confdir, sizeof(confdir));
2118 dt_loc_get_datadir(datadir, sizeof(datadir));
2119 char *system_profile_dir = g_build_filename(datadir, "color", "out", NULL);
2120 char *user_profile_dir = g_build_filename(confdir, "color", "out", NULL);
2121
2122 GtkWidget *label;
2123
2124 d->paper_list = NULL;
2125 d->media_list = NULL;
2126 d->unit = 0;
2127 d->width = d->height = NULL;
2128 d->v_piccprofile = NULL;
2129 d->v_iccprofile = NULL;
2130 d->v_style = NULL;
2131 d->creation = d->dragging = FALSE;
2132 d->selected = -1;
2133 d->last_selected = -1;
2134 d->has_changed = FALSE;
2135
2136 dt_init_print_info(&d->prt);
2137 dt_view_print_settings(darktable.view_manager, &d->prt, &d->imgs);
2138
2139 d->profiles = _get_profiles();
2140
2141 d->imgs.motion_over = -1;
2142
2143 const char *str = dt_conf_get_string_const("plugins/print/print/unit");
2144 const char **names = _unit_names;
2145 for(_unit_t i=0; *names; names++, i++)
2146 if(g_strcmp0(str, *names) == 0)
2147 d->unit = i;
2148
2149 dt_printing_clear_boxes(&d->imgs);
2150
2151 // set all margins + unit from settings
2152
2153 const float top_b = dt_conf_get_float("plugins/print/print/top_margin");
2154 const float bottom_b = dt_conf_get_float("plugins/print/print/bottom_margin");
2155 const float left_b = dt_conf_get_float("plugins/print/print/left_margin");
2156 const float right_b = dt_conf_get_float("plugins/print/print/right_margin");
2157
2158 d->prt.page.margin_top = _to_mm(d, top_b);
2159 d->prt.page.margin_bottom = _to_mm(d, bottom_b);
2160 d->prt.page.margin_left = _to_mm(d, left_b);
2161 d->prt.page.margin_right = _to_mm(d, right_b);
2162
2163 // create the spin-button now as values could be set when the printer has no hardware margin
2164
2165 // FIXME: set digits/increments on all of these by calling _unit_changed() later?
2166 int n_digits;
2167 float incr;
2168 _precision_by_unit(d->unit, &n_digits, &incr, NULL);
2169
2170 d->b_top = gtk_spin_button_new_with_range(0, 1000, incr);
2171 d->b_left = gtk_spin_button_new_with_range(0, 1000, incr);
2172 d->b_right = gtk_spin_button_new_with_range(0, 1000, incr);
2173 d->b_bottom = gtk_spin_button_new_with_range(0, 1000, incr);
2174 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->b_top), n_digits);
2175 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->b_bottom), n_digits);
2176 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->b_left), n_digits);
2177 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->b_right), n_digits);
2178
2179 d->b_x = gtk_spin_button_new_with_range(0, 1000, incr);
2180 d->b_y = gtk_spin_button_new_with_range(0, 1000, incr);
2181 d->b_width = gtk_spin_button_new_with_range(0, 1000, incr);
2182 d->b_height = gtk_spin_button_new_with_range(0, 1000, incr);
2183 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->b_x), n_digits);
2184 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->b_y), n_digits);
2185 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->b_width), n_digits);
2186 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->b_height), n_digits);
2187
2188 d->grid_size = gtk_spin_button_new_with_range(0, 100, incr);
2189 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(d->grid_size), n_digits);
2190
2191 gtk_entry_set_alignment(GTK_ENTRY(d->b_top), 1);
2192 gtk_entry_set_alignment(GTK_ENTRY(d->b_left), 1);
2193 gtk_entry_set_alignment(GTK_ENTRY(d->b_right), 1);
2194 gtk_entry_set_alignment(GTK_ENTRY(d->b_bottom), 1);
2195
2196 gtk_entry_set_alignment(GTK_ENTRY(d->b_x), 1);
2197 gtk_entry_set_alignment(GTK_ENTRY(d->b_y), 1);
2198 gtk_entry_set_alignment(GTK_ENTRY(d->b_width), 1);
2199 gtk_entry_set_alignment(GTK_ENTRY(d->b_height), 1);
2200
2201 gtk_entry_set_alignment(GTK_ENTRY(d->grid_size), 1);
2202
2203
2205
2206 // create papers combo as filled when adding printers
2208
2209 label = dt_ui_section_label_new(_("printer"));
2210 gtk_box_pack_start(GTK_BOX(self->widget), label, TRUE, TRUE, 0);
2211 dt_gui_add_help_link(self->widget, dt_get_help_url("print_settings_printer"));
2213
2214 gtk_box_pack_start(GTK_BOX(self->widget), d->printers, TRUE, TRUE, 0);
2215 g_signal_connect(G_OBJECT(d->printers), "value-changed", G_CALLBACK(_printer_changed), self);
2216
2218
2220
2221 dt_bauhaus_widget_set_label(d->media, N_("media"));
2222
2223 g_signal_connect(G_OBJECT(d->media), "value-changed", G_CALLBACK(_media_changed), self);
2224 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->media), TRUE, TRUE, 0);
2225
2226 // Add printer profile combo
2227
2229 dt_bauhaus_widget_set_label(d->pprofile, N_("profile"));
2230
2231 int combo_idx, n;
2232
2233 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->pprofile), TRUE, TRUE, 0);
2234 int printer_profile_type = dt_conf_get_int("plugins/print/printer/icctype");
2235 const char *printer_profile = dt_conf_get_string_const("plugins/print/printer/iccprofile");
2236 combo_idx = -1;
2237 n = 0;
2238
2239 dt_bauhaus_combobox_add(d->pprofile, _("color management in printer driver"));
2240 for(const GList *l = d->profiles; l; l = g_list_next(l))
2241 {
2243 // do not add built-in profiles, these are in no way for printing
2244 if(prof->type == DT_COLORSPACE_FILE)
2245 {
2246 dt_bauhaus_combobox_add(d->pprofile, prof->name);
2247 prof->ppos = ++n;
2248 if(prof->type == printer_profile_type &&
2249 (prof->type != DT_COLORSPACE_FILE || !g_strcmp0(prof->filename, printer_profile)))
2250 {
2251 dt_free(d->v_piccprofile);
2252 d->v_picctype = printer_profile_type;
2253 d->v_piccprofile = g_strdup(printer_profile);
2254 combo_idx = n;
2255 }
2256 }
2257 }
2258
2259 // profile not found, maybe a profile has been removed? revert to none
2260 if(combo_idx == -1)
2261 {
2262 dt_conf_set_int("plugins/print/printer/icctype", DT_COLORSPACE_NONE);
2263 dt_conf_set_string("plugins/print/printer/iccprofile", "");
2264 dt_free(d->v_piccprofile);
2265 d->v_picctype = DT_COLORSPACE_NONE;
2266 d->v_piccprofile = g_strdup("");
2267 combo_idx = 0;
2268 }
2269 dt_bauhaus_combobox_set(d->pprofile, combo_idx);
2270
2271 char *tooltip = g_strdup_printf(_("printer ICC profiles in %s or %s"), user_profile_dir, system_profile_dir);
2272 gtk_widget_set_tooltip_text(d->pprofile, tooltip);
2274
2275 g_signal_connect(G_OBJECT(d->pprofile), "value-changed", G_CALLBACK(_printer_profile_changed), (gpointer)self);
2276
2277 // Add printer intent combo
2278
2280 dt_bauhaus_widget_set_label(d->pintent, N_("intent"));
2281 dt_bauhaus_combobox_add(d->pintent, _("perceptual"));
2282 dt_bauhaus_combobox_add(d->pintent, _("relative colorimetric"));
2283 dt_bauhaus_combobox_add(d->pintent, C_("rendering intent", "saturation"));
2284 dt_bauhaus_combobox_add(d->pintent, _("absolute colorimetric"));
2285 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->pintent), TRUE, TRUE, 0);
2286
2287 d->v_pintent = dt_conf_get_int("plugins/print/printer/iccintent");
2288 dt_bauhaus_combobox_set(d->pintent, d->v_pintent);
2289
2290 g_signal_connect (G_OBJECT (d->pintent), "value-changed", G_CALLBACK (_printer_intent_callback), (gpointer)self);
2291 d->prt.printer.intent = d->v_pintent;
2292
2293 d->black_point_compensation = gtk_check_button_new_with_label(_("black point compensation"));
2294 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->black_point_compensation), TRUE, FALSE, 0);
2295 g_signal_connect(d->black_point_compensation, "toggled", G_CALLBACK(_printer_bpc_callback), (gpointer)self);
2296
2297 d->v_black_point_compensation = dt_conf_get_bool("plugins/print/print/black_point_compensation");
2298 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(d->black_point_compensation), d->v_black_point_compensation);
2299
2300 gtk_widget_set_tooltip_text(d->black_point_compensation,
2301 _("activate black point compensation when applying the printer profile"));
2302
2303 gtk_widget_set_sensitive(GTK_WIDGET(d->black_point_compensation), combo_idx==0?FALSE:TRUE);
2304
2306
2307 label = dt_ui_section_label_new(_("page"));
2308 gtk_box_pack_start(GTK_BOX(self->widget), label, TRUE, TRUE, 0);
2309 dt_gui_add_help_link(self->widget, dt_get_help_url("print_settings_page"));
2310
2312
2313 dt_bauhaus_widget_set_label(d->papers, N_("paper size"));
2314
2315 g_signal_connect(G_OBJECT(d->papers), "value-changed", G_CALLBACK(_paper_changed), self);
2316 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->papers), TRUE, TRUE, 0);
2317
2319
2321 dt_bauhaus_widget_set_label(d->orientation, N_("orientation"));
2322 dt_bauhaus_combobox_add(d->orientation, _("portrait"));
2323 dt_bauhaus_combobox_add(d->orientation, _("landscape"));
2324 g_signal_connect(G_OBJECT(d->orientation), "value-changed", G_CALLBACK(_orientation_changed), self);
2325 dt_bauhaus_combobox_set(d->orientation, d->prt.page.landscape?1:0);
2326 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->orientation), TRUE, TRUE, 0);
2327
2328 // NOTE: units has no label, which makes for cleaner UI but means that no action can be assigned
2329 GtkWidget *ucomb = dt_bauhaus_combobox_new_full(darktable.bauhaus, DT_GUI_MODULE(NULL), _("measurement units"), NULL, (int)d->unit,
2330 (GtkCallback)_unit_changed, self, _unit_names);
2331 gtk_box_pack_start(GTK_BOX(self->widget), ucomb, TRUE, TRUE, 0);
2332
2334
2335 GtkWidget *hboxdim = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
2336 label = gtk_label_new(_("image width/height"));
2337 gtk_box_pack_start(GTK_BOX(hboxdim), GTK_WIDGET(label), TRUE, TRUE, DT_PIXEL_APPLY_DPI(3));
2338 d->width = gtk_label_new(_("width"));
2339 gtk_box_pack_start(GTK_BOX(hboxdim), GTK_WIDGET(d->width), TRUE, TRUE, 0);
2340 label = gtk_label_new(_(" x "));
2341 gtk_box_pack_start(GTK_BOX(hboxdim), GTK_WIDGET(label), TRUE, TRUE, 0);
2342 d->height = gtk_label_new(_("height"));
2343 gtk_box_pack_start(GTK_BOX(hboxdim), GTK_WIDGET(d->height), TRUE, TRUE, 0);
2344
2346
2347 GtkWidget *hboxinfo = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
2348 label = gtk_label_new(_("scale factor"));
2349 gtk_box_pack_start(GTK_BOX(hboxinfo), GTK_WIDGET(label), TRUE, TRUE, DT_PIXEL_APPLY_DPI(3));
2350 d->info = gtk_label_new("1.0");
2351 gtk_box_pack_start(GTK_BOX(hboxinfo), GTK_WIDGET(d->info), TRUE, TRUE, 0);
2352 gtk_widget_set_tooltip_text(hboxinfo,
2353 _("image scale factor from native printer DPI:\n"
2354 " < 1 means that it is downscaled (best quality)\n"
2355 " > 1 means that the image is upscaled\n"
2356 " a too large value may result in poor print quality"));
2357
2359
2360 GtkGrid *bds = GTK_GRID(gtk_grid_new());
2361 gtk_grid_set_row_spacing(bds, DT_GUI_BOX_SPACING);
2362 gtk_grid_set_column_spacing(bds, DT_GUI_BOX_SPACING);
2363
2364 d->lock_activated = FALSE;
2365
2366 //d->b_top = gtk_spin_button_new_with_range(0, 10000, 1);
2367 gtk_widget_set_tooltip_text(GTK_WIDGET(d->b_top), _("top margin"));
2368 gtk_grid_attach(bds, GTK_WIDGET(d->b_top), 1, 0, 1, 1);
2369
2370 //d->b_left = gtk_spin_button_new_with_range(0, 10000, 1);
2371 gtk_widget_set_tooltip_text(GTK_WIDGET(d->b_left), _("left margin"));
2372 gtk_grid_attach(bds, GTK_WIDGET(d->b_left), 0, 1, 1, 1);
2373
2374 d->lock_button = GTK_TOGGLE_BUTTON(gtk_toggle_button_new_with_label(_("lock")));
2375 gtk_widget_set_tooltip_text(GTK_WIDGET(d->lock_button), _("change all margins uniformly"));
2376 gtk_grid_attach(bds, GTK_WIDGET(d->lock_button), 1, 1, 1, 1);
2377
2378 //d->b_right = gtk_spin_button_new_with_range(0, 10000, 1);
2379 gtk_widget_set_tooltip_text(GTK_WIDGET(d->b_right), _("right margin"));
2380 gtk_grid_attach(bds, GTK_WIDGET(d->b_right), 2, 1, 1, 1);
2381
2382 //d->b_bottom = gtk_spin_button_new_with_range(0, 10000, 1);
2383 gtk_widget_set_tooltip_text(GTK_WIDGET(d->b_bottom), _("bottom margin"));
2384 gtk_grid_attach(bds, GTK_WIDGET(d->b_bottom), 1, 2, 1, 1);
2385
2386 gtk_widget_set_halign(GTK_WIDGET(bds), GTK_ALIGN_CENTER);
2387 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(bds), TRUE, TRUE, 0);
2388
2389 gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->b_top), top_b);
2390 gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->b_bottom), bottom_b);
2391 gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->b_left), left_b);
2392 gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->b_right), right_b);
2393
2394 g_signal_connect(G_OBJECT (d->b_top), "value-changed",
2395 G_CALLBACK (_top_border_callback), self);
2396 g_signal_connect(G_OBJECT (d->b_bottom), "value-changed",
2397 G_CALLBACK (_bottom_border_callback), self);
2398 g_signal_connect(G_OBJECT (d->b_left), "value-changed",
2399 G_CALLBACK (_left_border_callback), self);
2400 g_signal_connect(G_OBJECT (d->b_right), "value-changed",
2401 G_CALLBACK (_right_border_callback), self);
2402 g_signal_connect(G_OBJECT(d->lock_button), "toggled",
2403 G_CALLBACK(_lock_callback), self);
2404
2405 gtk_widget_set_halign(GTK_WIDGET(hboxdim), GTK_ALIGN_CENTER);
2406 gtk_widget_set_halign(GTK_WIDGET(hboxinfo), GTK_ALIGN_CENTER);
2407
2408 const gboolean lock_active = dt_conf_get_bool("plugins/print/print/lock_borders");
2409 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(d->lock_button), lock_active);
2410
2411 // grid & snap grid
2412 {
2413 GtkWidget *vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
2414 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
2415
2416 d->grid = gtk_check_button_new_with_label(_("display grid"));
2417 // d->grid_size = gtk_spin_button_new_with_range(0, 100, 0.1);
2418 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(d->grid), TRUE, TRUE, 0);
2419 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(d->grid_size), TRUE, TRUE, 0);
2420
2421 gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->grid_size),
2422 dt_conf_get_float("plugins/print/print/grid_size") * units[d->unit]);
2423
2424 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), TRUE, TRUE, 0);
2425
2426 d->snap_grid = gtk_check_button_new_with_label(_("snap to grid"));
2427 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(d->snap_grid), TRUE, TRUE, 0);
2428
2429 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(vbox), TRUE, TRUE, 0);
2430
2431 g_signal_connect(G_OBJECT(d->grid_size), "value-changed", G_CALLBACK(_grid_size_changed), self);
2432 g_signal_connect(G_OBJECT(d->grid), "toggled", G_CALLBACK(_grid_callback), self);
2433 g_signal_connect(d->snap_grid, "toggled", G_CALLBACK(_snap_grid_callback), (gpointer)self);
2434 }
2435
2436 d->borderless = gtk_check_button_new_with_label(_("borderless mode required"));
2437 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->borderless), TRUE, TRUE, 0);
2438 gtk_widget_set_tooltip_text(d->borderless,
2439 _("indicates that the borderless mode should be activated\n"
2440 "in the printer driver because the selected margins are\n"
2441 "below the printer hardware margins"));
2442 gtk_widget_set_sensitive(d->borderless, FALSE);
2443
2444 // pack image dimension hbox here
2445
2446 label = dt_ui_section_label_new(_("image layout"));
2447 gtk_box_pack_start(GTK_BOX(self->widget), label, TRUE, TRUE, 0);
2448 dt_gui_add_help_link(self->widget, dt_get_help_url("print_image_layout"));
2449
2450 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(hboxdim), TRUE, TRUE, 0);
2451 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(hboxinfo), TRUE, TRUE, 0);
2452
2454
2455 // Auto-fit: Create the 3x3 gtk table toggle button table...
2456 GtkGrid *bat = GTK_GRID(gtk_grid_new());
2457 gtk_grid_set_row_spacing(bat, DT_GUI_BOX_SPACING);
2458 gtk_grid_set_column_spacing(bat, DT_GUI_BOX_SPACING);
2459 for(int i=0; i<9; i++)
2460 {
2461 d->dtba[i]
2463 gtk_grid_attach (GTK_GRID (bat), GTK_WIDGET (d->dtba[i]), (i%3), i/3, 1, 1);
2464 g_signal_connect (G_OBJECT (d->dtba[i]), "toggled",G_CALLBACK (_alignment_callback), self);
2465 }
2466
2467 GtkWidget *hbox22 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
2468 GtkWidget *label4 = gtk_label_new(_("alignment"));
2469 gtk_box_pack_start(GTK_BOX(hbox22),GTK_WIDGET(label4),TRUE,TRUE,0);
2470 gtk_box_pack_start(GTK_BOX(hbox22), GTK_WIDGET(bat), TRUE, TRUE, 0);
2471 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(hbox22), TRUE, TRUE, 0);
2472
2473 // Manual fit
2474 GtkWidget *hfitbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
2475
2476 GtkWidget *mfitbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
2477
2478 GtkGrid *fitbut = GTK_GRID(gtk_grid_new());
2479 gtk_grid_set_row_spacing(fitbut, DT_GUI_BOX_SPACING);
2480 gtk_grid_set_column_spacing(fitbut, DT_GUI_BOX_SPACING);
2481 gtk_grid_set_column_homogeneous(fitbut, TRUE);
2482 gtk_grid_set_row_homogeneous(fitbut, TRUE);
2483
2484 GtkWidget *bnew = dt_action_button_new(self, N_("new image area"), _page_new_area_clicked, self,
2485 _("add a new image area on the page\n"
2486 "click and drag on the page to place the area\n"
2487 "drag&drop image from film strip on it"), 0, 0);
2488
2489 d->del = dt_action_button_new(self, N_("delete image area"), _page_delete_area_clicked, self,
2490 _("delete the currently selected image area"), 0, 0);
2491 gtk_widget_set_sensitive(d->del, FALSE);
2492
2493 GtkWidget *bclear = dt_action_button_new(self, N_("clear layout"), _page_clear_area_clicked, self,
2494 _("remove all image areas from the page"), 0, 0);
2495
2496 gtk_grid_attach(fitbut, GTK_WIDGET(bnew), 0, 0, 2, 1);
2497 gtk_grid_attach(fitbut, GTK_WIDGET(d->del), 0, 1, 1, 1);
2498 gtk_grid_attach(fitbut, GTK_WIDGET(bclear), 1, 1, 1, 1);
2499
2500 gtk_box_pack_start(GTK_BOX(mfitbox), GTK_WIDGET(fitbut), TRUE, TRUE, 0);
2501 gtk_box_pack_start(GTK_BOX(hfitbox), GTK_WIDGET(mfitbox), TRUE, TRUE, 0);
2502
2503 // X x Y
2504 GtkWidget *box;
2505 // FIXME: add labels to x/y/width/height as otherwise are obscure -- and there is the horizontal space to do this
2506
2507 box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
2508 // d->b_x = gtk_spin_button_new_with_range(0, 1000, 1);
2509 gtk_widget_set_tooltip_text(d->b_x, _("image area x origin (in current unit)"));
2510 gtk_entry_set_width_chars(GTK_ENTRY(d->b_x), 5);
2511
2512 // d->b_y = gtk_spin_button_new_with_range(0, 1000, 1);
2513 gtk_widget_set_tooltip_text(d->b_y, _("image area y origin (in current unit)"));
2514 gtk_entry_set_width_chars(GTK_ENTRY(d->b_y), 5);
2515
2516 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(d->b_x), TRUE, TRUE, 0);
2517 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(d->b_y), TRUE, TRUE, 0);
2518
2519 gtk_box_pack_start(GTK_BOX(hfitbox), GTK_WIDGET(box), TRUE, TRUE, 0);
2520
2521 // width x height
2522 box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, DT_GUI_BOX_SPACING);
2523 // d->b_width = gtk_spin_button_new_with_range(0, 1000, 1);
2524 gtk_widget_set_tooltip_text(d->b_width, _("image area width (in current unit)"));
2525 gtk_entry_set_width_chars(GTK_ENTRY(d->b_width), 5);
2526
2527 // d->b_height = gtk_spin_button_new_with_range(0, 1000, 1);
2528 gtk_widget_set_tooltip_text(d->b_height, _("image area height (in current unit)"));
2529 gtk_entry_set_width_chars(GTK_ENTRY(d->b_height), 5);
2530
2531 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(d->b_width), TRUE, TRUE, 0);
2532 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(d->b_height), TRUE, TRUE, 0);
2533
2534 gtk_box_pack_start(GTK_BOX(hfitbox), GTK_WIDGET(box), TRUE, TRUE, 0);
2535
2536 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(hfitbox), TRUE, TRUE, 0);
2537
2538 gtk_widget_add_events(d->b_x, GDK_BUTTON_PRESS_MASK);
2539 gtk_widget_add_events(d->b_y, GDK_BUTTON_PRESS_MASK);
2540 gtk_widget_add_events(d->b_width, GDK_BUTTON_PRESS_MASK);
2541 gtk_widget_add_events(d->b_height, GDK_BUTTON_PRESS_MASK);
2542
2543 g_signal_connect(G_OBJECT(d->b_x), "value-changed", G_CALLBACK(_x_changed), (gpointer)d);
2544 g_signal_connect(G_OBJECT(d->b_y), "value-changed", G_CALLBACK(_y_changed), (gpointer)d);
2545 g_signal_connect(G_OBJECT(d->b_width), "value-changed", G_CALLBACK(_width_changed), (gpointer)d);
2546 g_signal_connect(G_OBJECT(d->b_height), "value-changed", G_CALLBACK(_height_changed), (gpointer)d);
2547
2549
2550 label = dt_ui_section_label_new(_("print settings"));
2551 gtk_box_pack_start(GTK_BOX(self->widget), label, TRUE, TRUE, 0);
2552 dt_gui_add_help_link(self->widget, dt_get_help_url("print_settings"));
2553
2554 // Add export profile combo
2555
2557 dt_bauhaus_widget_set_label(d->profile, N_("profile"));
2558
2559 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->profile), TRUE, TRUE, 0);
2560 dt_bauhaus_combobox_add(d->profile, _("image settings"));
2561
2562 const int icctype = dt_conf_get_int("plugins/print/print/icctype");
2563 const gchar *iccprofile = dt_conf_get_string_const("plugins/print/print/iccprofile");
2564 combo_idx = -1;
2565 n = 0;
2566
2567 for(const GList *l = d->profiles; l; l = g_list_next(l))
2568 {
2570 dt_bauhaus_combobox_add(d->profile, prof->name);
2571 prof->pos = ++n;
2572 if(prof->type == icctype
2573 && (prof->type != DT_COLORSPACE_FILE || !g_strcmp0(prof->filename, iccprofile)))
2574 {
2575 dt_free(d->v_iccprofile);
2576 d->v_icctype = icctype;
2577 d->v_iccprofile = g_strdup(iccprofile);
2578 combo_idx = n;
2579 }
2580 }
2581
2582 if(combo_idx == -1)
2583 {
2584 dt_conf_set_int("plugins/print/print/icctype", DT_COLORSPACE_NONE);
2585 dt_conf_set_string("plugins/print/print/iccprofile", "");
2586 dt_free(d->v_iccprofile);
2587 d->v_icctype = DT_COLORSPACE_NONE;
2588 d->v_iccprofile = g_strdup("");
2589 combo_idx = 0;
2590 }
2591
2592 dt_bauhaus_combobox_set(d->profile, combo_idx);
2593
2594 tooltip = g_strdup_printf(_("output ICC profiles in %s or %s"), user_profile_dir, system_profile_dir);
2595 gtk_widget_set_tooltip_text(d->profile, tooltip);
2597
2598 g_signal_connect(G_OBJECT(d->profile), "value-changed", G_CALLBACK(_profile_changed), (gpointer)self);
2599
2600 // Add export intent combo
2601
2603 dt_bauhaus_widget_set_label(d->intent, N_("intent"));
2604
2605 dt_bauhaus_combobox_add(d->intent, _("image settings"));
2606 dt_bauhaus_combobox_add(d->intent, _("perceptual"));
2607 dt_bauhaus_combobox_add(d->intent, _("relative colorimetric"));
2608 dt_bauhaus_combobox_add(d->intent, C_("rendering intent", "saturation"));
2609 dt_bauhaus_combobox_add(d->intent, _("absolute colorimetric"));
2610 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->intent), TRUE, TRUE, 0);
2611
2612 dt_bauhaus_combobox_set(d->intent, dt_conf_get_int("plugins/print/print/iccintent") + 1);
2613
2614 g_signal_connect (G_OBJECT (d->intent), "value-changed", G_CALLBACK (_intent_callback), (gpointer)self);
2615
2616 // Add export style combo
2617
2619 dt_bauhaus_widget_set_label(d->style, N_("style"));
2620
2621 dt_bauhaus_combobox_add(d->style, _("none"));
2622
2623 GList *styles = dt_styles_get_list("");
2624 const char *current_style = dt_conf_get_string_const("plugins/print/print/style");
2625 combo_idx = -1; n=0;
2626
2627 for(const GList *st_iter = styles; st_iter; st_iter = g_list_next(st_iter))
2628 {
2629 dt_style_t *style=(dt_style_t *)st_iter->data;
2630 dt_bauhaus_combobox_add(d->style, style->name);
2631 n++;
2632 if(g_strcmp0(style->name,current_style)==0)
2633 {
2634 dt_free(d->v_style);
2635 d->v_style = g_strdup(current_style);
2636 combo_idx=n;
2637 }
2638 }
2639 g_list_free_full(styles, dt_style_free);
2640 styles = NULL;
2641 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(d->style), TRUE, TRUE, 0);
2642 gtk_widget_set_tooltip_text(d->style, _("temporary style to use while printing"));
2643
2644 // style not found, maybe a style has been removed? revert to none
2645 if(combo_idx == -1)
2646 {
2647 dt_conf_set_string("plugins/print/print/style", "");
2648 dt_free(d->v_style);
2649 d->v_style = g_strdup("");
2650 combo_idx=0;
2651 }
2652 dt_bauhaus_combobox_set(d->style, combo_idx);
2653
2654 g_signal_connect (G_OBJECT (d->style), "value-changed",
2655 G_CALLBACK (_style_callback),
2656 (gpointer)self);
2657
2658 // Print button
2659
2660 GtkWidget *button = dt_action_button_new(self, N_("print"), _print_button_clicked, self,
2661 _("print with current settings"), GDK_KEY_p, GDK_CONTROL_MASK);
2662 d->print_button = GTK_BUTTON(button);
2663 gtk_box_pack_start(GTK_BOX(self->widget), button, TRUE, TRUE, 0);
2664 dt_gui_add_help_link(button, dt_get_help_url("print_settings_button"));
2665
2666 dt_free(system_profile_dir);
2667 dt_free(user_profile_dir);
2668
2669 // Let's start the printer discovery now
2670
2672}
2673
2674void *legacy_params(dt_lib_module_t *self, const void *const old_params, const size_t old_params_size,
2675 const int old_version, int *new_version, size_t *new_size)
2676{
2677 if(old_version == 1)
2678 {
2679 // we added the profile type
2680 //
2681 // old format:
2682 // char *printer
2683 // char *paper
2684 // int32_t landscape
2685 // char *f_profile
2686 // int32_t intent
2687 // char *f_pprofile
2688 // <rest>
2689 //
2690 // new format:
2691 // char *printer
2692 // char *paper
2693 // int32_t landscape
2694 // int32_t f_profile_type
2695 // char *f_profile
2696 // int32_t intent
2697 // int32_t f_pprofile_type
2698 // char *f_pprofile
2699 // <rest>
2700
2701 const char *buf = (const char *)old_params;
2702
2703 // printer
2704 const char *printer = buf;
2705 const int32_t printer_len = strlen(printer) + 1;
2706 buf += printer_len;
2707
2708 // paper
2709 const char *paper = buf;
2710 const int32_t paper_len = strlen(paper) + 1;
2711 buf += paper_len;
2712
2713 // landscape
2714 const int32_t landscape = *(int32_t *)buf;
2715 buf += sizeof(int32_t);
2716
2717 // profile
2718 const char *profile = buf;
2719 const int32_t profile_len = strlen(profile) + 1;
2720 buf += profile_len;
2721
2722 // intent
2723 const int32_t intent = *(int32_t *)buf;
2724 buf += sizeof(int32_t);
2725
2726 // pprofile
2727 const char *pprofile = buf;
2728 const int32_t pprofile_len = strlen(pprofile) + 1;
2729 buf += pprofile_len;
2730
2731
2732 // now we got all fields from the start of the buffer and buf points to the beginning or <rest>
2733
2734 // find the new values for the two profiles
2735 dt_colorspaces_color_profile_type_t profile_type, pprofile_type;
2736 const char *profile_filename = "", *pprofile_filename = "";
2737
2738 if(*profile == '\0' || !g_strcmp0(profile, "none"))
2739 {
2740 profile_type = DT_COLORSPACE_NONE;
2741 }
2742 else if(!g_strcmp0(profile, "sRGB"))
2743 {
2744 profile_type = DT_COLORSPACE_SRGB;
2745 }
2746 else if(!g_strcmp0(profile, "adobergb"))
2747 {
2748 profile_type = DT_COLORSPACE_ADOBERGB;
2749 }
2750 else
2751 {
2752 profile_type = DT_COLORSPACE_FILE;
2753 profile_filename = &profile[1]; // the old code had a '/' in the beginning
2754 }
2755
2756 // in theory pprofile can't be srgb or adobergb, but checking for them won't hurt
2757 if(*pprofile == '\0')
2758 {
2759 pprofile_type = DT_COLORSPACE_NONE;
2760 }
2761 else if(!g_strcmp0(pprofile, "sRGB"))
2762 {
2763 pprofile_type = DT_COLORSPACE_SRGB;
2764 }
2765 else if(!g_strcmp0(pprofile, "adobergb"))
2766 {
2767 pprofile_type = DT_COLORSPACE_ADOBERGB;
2768 }
2769 else
2770 {
2771 pprofile_type = DT_COLORSPACE_FILE;
2772 pprofile_filename = &pprofile[1]; // the old code had a '/' in the beginning
2773 }
2774
2775 const int32_t new_profile_len = strlen(profile_filename) + 1;
2776 const int32_t new_pprofile_len = strlen(pprofile_filename) + 1;
2777
2778 // now we got everything to reassemble the new params
2779 size_t new_params_size = old_params_size - profile_len - pprofile_len;
2780 new_params_size += 2 * sizeof(dt_colorspaces_color_profile_type_t);
2781 new_params_size += new_profile_len + new_pprofile_len;
2782 void *new_params = malloc(new_params_size);
2783
2784 size_t pos = 0;
2785 // char *printer
2786 memcpy((uint8_t *)new_params + pos, printer, printer_len);
2787 pos += printer_len;
2788 // char *paper
2789 memcpy((uint8_t *)new_params + pos, paper, paper_len);
2790 pos += paper_len;
2791 // int32_t landscape
2792 memcpy((uint8_t *)new_params + pos, &landscape, sizeof(int32_t));
2793 pos += sizeof(int32_t);
2794 // int32_t f_profile_type
2795 memcpy((uint8_t *)new_params + pos, &profile_type, sizeof(int32_t));
2796 pos += sizeof(int32_t);
2797 // char *f_profile
2798 memcpy((uint8_t *)new_params + pos, profile_filename, new_profile_len);
2799 pos += new_profile_len;
2800 // int32_t intent
2801 memcpy((uint8_t *)new_params + pos, &intent, sizeof(int32_t));
2802 pos += sizeof(int32_t);
2803 // int32_t f_pprofile_type
2804 memcpy((uint8_t *)new_params + pos, &pprofile_type, sizeof(int32_t));
2805 pos += sizeof(int32_t);
2806 // char *f_pprofile
2807 memcpy((uint8_t *)new_params + pos, pprofile_filename, new_pprofile_len);
2808 pos += new_pprofile_len;
2809 // <rest>
2810 memcpy((uint8_t *)new_params + pos, buf, old_params_size - ((char *)buf - (char *)old_params));
2811
2812 *new_size = new_params_size;
2813 *new_version = 2;
2814 return new_params;
2815 }
2816 else if(old_version == 2)
2817 {
2818 // add upscale to params
2819 size_t new_params_size = old_params_size + 1;
2820 void *new_params = calloc(1, new_params_size);
2821
2822 memcpy(new_params, old_params, old_params_size);
2823 // no media type specified
2824 ((char *)new_params)[old_params_size] = '\0';
2825
2826 *new_size = new_params_size;
2827 *new_version = 3;
2828 return new_params;
2829 }
2830 else if(old_version == 3)
2831 {
2832 // no box
2833 size_t new_params_size = old_params_size + sizeof(int32_t) + 4 * sizeof(float);
2834 void *new_params = calloc(1, new_params_size);
2835
2836 memcpy(new_params, old_params, old_params_size);
2837
2838 // single image box specified (there is no way to create a box on the size
2839 // of the page at this stage).
2840 int32_t idx = old_params_size;
2841 *(int32_t *)((uint8_t *)new_params + idx) = 1;
2842 idx += sizeof(int32_t);
2843 *(float *)((uint8_t *)new_params + idx) = 0.05f;
2844 idx += sizeof(float);
2845 *(float *)((uint8_t *)new_params + idx) = 0.05f;
2846 idx += sizeof(float);
2847 *(float *)((uint8_t *)new_params + idx) = 0.90f;
2848 idx += sizeof(float);
2849 *(float *)((uint8_t *)new_params + idx) = 0.90f;
2850 // idx += sizeof(float);
2851
2852 *new_size = new_params_size;
2853 *new_version = 4;
2854 return new_params;
2855 }
2856
2857 return NULL;
2858}
2859
2860int set_params(dt_lib_module_t *self, const void *params, int size)
2861{
2863
2864 if(IS_NULL_PTR(params)) return 1;
2865
2866 // get the parameters buffer
2867 const char *buf = (char *)params;
2868
2869 // get individual items
2870 const char *printer = buf;
2871 if(IS_NULL_PTR(printer)) return 1;
2872 const int32_t printer_len = strlen(printer) + 1;
2873 buf += printer_len;
2874
2875 const char *paper = buf;
2876 if(IS_NULL_PTR(paper)) return 1;
2877 const int32_t paper_len = strlen(paper) + 1;
2878 buf += paper_len;
2879
2880 const int32_t landscape = *(int32_t *)buf;
2881 buf += sizeof(int32_t);
2882
2883 const int32_t f_profile_type = *(int32_t *)buf;
2884 buf += sizeof(int32_t);
2885
2886 const char *f_profile = buf;
2887 if(IS_NULL_PTR(f_profile)) return 1;
2888 const int32_t profile_len = strlen(f_profile) + 1;
2889 buf += profile_len;
2890
2891 const int32_t intent = *(int32_t *)buf;
2892 buf += sizeof(int32_t);
2893
2894 const int32_t f_pprofile_type = *(int32_t *)buf;
2895 buf += sizeof(int32_t);
2896
2897 const char *f_pprofile = buf;
2898 if(IS_NULL_PTR(f_pprofile)) return 1;
2899 const int32_t pprofile_len = strlen(f_pprofile) + 1;
2900 buf += pprofile_len;
2901
2902 const int32_t pintent = *(int32_t *)buf;
2903 buf += sizeof(int32_t);
2904
2905 const int32_t bpc = *(int32_t *)buf;
2906 buf += sizeof(int32_t);
2907
2908 const char *style = buf;
2909 if(IS_NULL_PTR(style)) return 1;
2910 const int32_t style_len = strlen(style) + 1;
2911 buf += style_len;
2912
2913 //const int32_t style_mode = *(int32_t *)buf;
2914 buf += sizeof(int32_t);
2915
2916 const double b_top = *(double *)buf;
2917 buf += sizeof(double);
2918
2919 const double b_bottom = *(double *)buf;
2920 buf += sizeof(double);
2921
2922 const double b_left = *(double *)buf;
2923 buf += sizeof(double);
2924
2925 const double b_right = *(double *)buf;
2926 buf += sizeof(double);
2927
2928 const int32_t alignment = *(int32_t *)buf;
2929 buf += sizeof(int32_t);
2930
2931 const char *media = buf;
2932 if(IS_NULL_PTR(media)) return 1;
2933 const int32_t media_len = strlen(media) + 1;
2934 buf += media_len;
2935
2936 ps->imgs.count = *(int32_t *)buf;
2937 buf += sizeof(int32_t);
2938
2939 for(int k=0; k<ps->imgs.count; k++)
2940 {
2941 ps->imgs.box[k].pos.x = *(float *)buf;
2942 buf += sizeof(float);
2943 ps->imgs.box[k].pos.y = *(float *)buf;
2944 buf += sizeof(float);
2945 ps->imgs.box[k].pos.width = *(float *)buf;
2946 buf += sizeof(float);
2947 ps->imgs.box[k].pos.height = *(float *)buf;
2948 buf += sizeof(float);
2949 }
2950
2951 // ensure that the size is correct
2952 if(size != printer_len + paper_len + media_len + profile_len + pprofile_len + style_len + 8 * sizeof(int32_t) + 4 * sizeof(double) + sizeof(int32_t) + (ps->imgs.count * 4 * sizeof(float)))
2953 return 1;
2954
2955 // set the GUI with corresponding values
2956 if(printer[0] != '\0')
2958
2959 if(paper[0] != '\0')
2961
2962 if(media[0] != '\0')
2964
2965 dt_bauhaus_combobox_set (ps->orientation, landscape);
2966
2968 for(GList *iter = ps->profiles; iter; iter = g_list_next(iter))
2969 {
2971 if(f_profile_type == p->type && (f_profile_type != DT_COLORSPACE_FILE || !g_strcmp0(f_profile, p->filename)))
2972 {
2974 break;
2975 }
2976 }
2977
2978 dt_bauhaus_combobox_set (ps->intent, intent);
2979
2981 for(GList *iter = ps->profiles; iter; iter = g_list_next(iter))
2982 {
2984 if(f_pprofile_type == p->type && (f_pprofile_type != DT_COLORSPACE_FILE || !g_strcmp0(f_pprofile, p->filename)))
2985 {
2987 break;
2988 }
2989 }
2990
2991 dt_bauhaus_combobox_set (ps->pintent, pintent);
2992 ps->prt.printer.intent = pintent;
2993
2994 if(style[0] != '\0')
2996
2997 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_top), b_top * units[ps->unit]);
2998 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_bottom), b_bottom * units[ps->unit]);
2999 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_left), b_left * units[ps->unit]);
3000 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_right), b_right * units[ps->unit]);
3001
3002 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->dtba[alignment]), TRUE);
3003 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->black_point_compensation), bpc);
3004
3006
3007 return 0;
3008}
3009
3011{
3013
3014 // get the data
3015 const char *printer = dt_bauhaus_combobox_get_text(ps->printers);
3016 const char *paper = dt_bauhaus_combobox_get_text(ps->papers);
3017 const char *media = dt_bauhaus_combobox_get_text(ps->media);
3018 const int32_t profile_pos = dt_bauhaus_combobox_get(ps->profile);
3019 const int32_t intent = dt_bauhaus_combobox_get(ps->intent);
3020 const char *style = dt_bauhaus_combobox_get_text(ps->style);
3021 const int32_t style_mode = 0; // deprecated, kept for compatibility
3022 const int32_t pprofile_pos = dt_bauhaus_combobox_get(ps->pprofile);
3023 const int32_t pintent = dt_bauhaus_combobox_get(ps->pintent);
3024 const int32_t landscape = dt_bauhaus_combobox_get(ps->orientation);
3025 const int32_t bpc = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ps->black_point_compensation));
3026 const double b_top = ps->prt.page.margin_top;
3027 const double b_bottom = ps->prt.page.margin_bottom;
3028 const double b_left = ps->prt.page.margin_left;
3029 const double b_right = ps->prt.page.margin_right;
3030 const int32_t alignment = 0;
3031
3033 const char *profile = "", *pprofile = "";
3034 for(GList *iter = ps->profiles; iter; iter = g_list_next(iter))
3035 {
3037 if(p->pos == profile_pos)
3038 {
3039 profile_type = p->type;
3040 profile = p->filename;
3041 }
3042 if(p->ppos == pprofile_pos)
3043 {
3044 pprofile_type = p->type;
3045 pprofile = p->filename;
3046 }
3047 }
3048
3049 // these will be NULL when no printer is connected/found
3050 if(IS_NULL_PTR(printer)) printer = "";
3051 if(IS_NULL_PTR(paper)) paper = "";
3052 if(IS_NULL_PTR(media)) media = "";
3053
3054 // compute the size of individual items, always get the \0 for strings
3055 const int32_t printer_len = strlen (printer) + 1;
3056 const int32_t paper_len = strlen (paper) + 1;
3057 const int32_t media_len = strlen (media) + 1;
3058 const int32_t profile_len = strlen (profile) + 1;
3059 const int32_t pprofile_len = strlen (pprofile) + 1;
3060 const int32_t style_len = strlen (style) + 1;
3061
3062 // compute the size of all parameters
3063 *size = printer_len + paper_len + media_len + profile_len + pprofile_len + style_len + 8 * sizeof(int32_t) + 4 * sizeof(double) + sizeof(int32_t) + (ps->imgs.count * 4 * sizeof(float));
3064
3065 // allocate the parameter buffer
3066 char *params = (char *)malloc(*size);
3067
3068 int pos = 0;
3069
3070 memcpy(params+pos, printer, printer_len);
3071 pos += printer_len;
3072 memcpy(params+pos, paper, paper_len);
3073 pos += paper_len;
3074 memcpy(params+pos, &landscape, sizeof(int32_t));
3075 pos += sizeof(int32_t);
3076 memcpy(params+pos, &profile_type, sizeof(int32_t));
3077 pos += sizeof(int32_t);
3078 memcpy(params+pos, profile, profile_len);
3079 pos += profile_len;
3080 memcpy(params+pos, &intent, sizeof(int32_t));
3081 pos += sizeof(int32_t);
3082 memcpy(params+pos, &pprofile_type, sizeof(int32_t));
3083 pos += sizeof(int32_t);
3084 memcpy(params+pos, pprofile, pprofile_len);
3085 pos += pprofile_len;
3086 memcpy(params+pos, &pintent, sizeof(int32_t));
3087 pos += sizeof(int32_t);
3088 memcpy(params+pos, &bpc, sizeof(int32_t));
3089 pos += sizeof(int32_t);
3090 memcpy(params+pos, style, style_len);
3091 pos += style_len;
3092 memcpy(params+pos, &style_mode, sizeof(int32_t));
3093 pos += sizeof(int32_t);
3094 memcpy(params+pos, &b_top, sizeof(double));
3095 pos += sizeof(double);
3096 memcpy(params+pos, &b_bottom, sizeof(double));
3097 pos += sizeof(double);
3098 memcpy(params+pos, &b_left, sizeof(double));
3099 pos += sizeof(double);
3100 memcpy(params+pos, &b_right, sizeof(double));
3101 pos += sizeof(double);
3102 memcpy(params+pos, &alignment, sizeof(int32_t));
3103 pos += sizeof(int32_t);
3104 memcpy(params+pos, media, media_len);
3105 pos += media_len;
3106
3107 // boxes
3108 memcpy(params+pos, &ps->imgs.count, sizeof(int32_t));
3109 pos += sizeof(int32_t);
3110
3111 for(int k=0; k<ps->imgs.count; k++)
3112 {
3113 memcpy(params+pos, &ps->imgs.box[k].pos.x, sizeof(float));
3114 pos += sizeof(int32_t);
3115 memcpy(params+pos, &ps->imgs.box[k].pos.y, sizeof(float));
3116 pos += sizeof(int32_t);
3117 memcpy(params+pos, &ps->imgs.box[k].pos.width, sizeof(float));
3118 pos += sizeof(int32_t);
3119 memcpy(params+pos, &ps->imgs.box[k].pos.height, sizeof(float));
3120 pos += sizeof(int32_t);
3121 }
3122
3123 g_assert(pos == *size);
3124
3125 return params;
3126}
3127
3129{
3130 if(IS_NULL_PTR(self->data)) return;
3132
3133 // these can be called on shutdown, resulting in null-pointer
3134 // dereference and division by zero -- not sure what interaction
3135 // makes them called, but better to disconnect and not have segfault
3136 g_signal_handlers_disconnect_by_func(G_OBJECT(ps->b_top), G_CALLBACK(_top_border_callback), self);
3137 g_signal_handlers_disconnect_by_func(G_OBJECT(ps->b_bottom), G_CALLBACK(_bottom_border_callback), self);
3138 g_signal_handlers_disconnect_by_func(G_OBJECT(ps->b_left), G_CALLBACK(_left_border_callback), self);
3139 g_signal_handlers_disconnect_by_func(G_OBJECT(ps->b_right), G_CALLBACK(_right_border_callback), self);
3140
3141 g_list_free_full(ps->profiles, dt_free_gpointer);
3142 ps->profiles = NULL;
3143 g_list_free_full(ps->paper_list, dt_free_gpointer);
3144 ps->paper_list = NULL;
3145 g_list_free_full(ps->media_list, dt_free_gpointer);
3146 ps->media_list = NULL;
3147
3148 dt_free(ps->v_iccprofile);
3150 dt_free(ps->v_style);
3151
3152 dt_free(self->data);
3153}
3154
3156{
3158
3159 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_top), 17 * units[ps->unit]);
3160 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_bottom), 17 * units[ps->unit]);
3161 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_left), 17 * units[ps->unit]);
3162 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->b_right), 17 * units[ps->unit]);
3163 gtk_spin_button_set_value(GTK_SPIN_BUTTON(ps->grid_size), 10 * units[ps->unit]);
3164
3165 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->dtba[ALIGNMENT_CENTER]), TRUE);
3172 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps->black_point_compensation), TRUE);
3173 gtk_widget_set_sensitive(GTK_WIDGET(ps->pintent), TRUE);
3174 gtk_widget_set_sensitive(GTK_WIDGET(ps->black_point_compensation), FALSE);
3175
3176 // reset page orientation to fit the picture if a single one is displayed
3177
3178 const int32_t imgid = (ps->imgs.count > 0) ? ps->imgs.box[0].imgid : -1;
3180 ps->imgs.imgid_to_load = imgid;
3181
3182 ps->creation = ps->dragging = FALSE;
3183 ps->selected = -1;
3184 ps->last_selected = -1;
3185 ps->has_changed = FALSE;
3186
3188}
3189
3190// clang-format off
3191// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
3192// vim: shiftwidth=2 expandtab tabstop=2 cindent
3193// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
3194// clang-format on
static double dist(double x1, double y1, double x2, double y2)
Definition ashift_lsd.c:250
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
#define m
Definition basecurve.c:278
GtkWidget * dt_bauhaus_combobox_new_full(dt_bauhaus_t *bh, dt_gui_module_t *self, const char *label, const char *tip, int pos, GtkCallback callback, gpointer data, const char **texts)
Definition bauhaus.c:1849
void dt_bauhaus_combobox_clear(GtkWidget *widget)
Definition bauhaus.c:2189
int dt_bauhaus_combobox_get(GtkWidget *widget)
Definition bauhaus.c:2347
const char * dt_bauhaus_combobox_get_text(GtkWidget *widget)
Definition bauhaus.c:2162
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:2301
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
Definition bauhaus.c:1653
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
Definition bauhaus.c:1842
gboolean dt_bauhaus_combobox_set_from_text(GtkWidget *widget, const char *text)
Definition bauhaus.c:2311
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
Definition bauhaus.c:2016
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
const dt_colorspaces_color_profile_t * dt_colorspaces_get_profile(dt_colorspaces_color_profile_type_t type, const char *filename, dt_colorspaces_profile_direction_t direction)
const dt_colorspaces_color_profile_t * dt_colorspaces_get_output_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *over_type, const char *over_filename)
dt_iop_color_intent_t
Definition colorspaces.h:63
@ DT_INTENT_PERCEPTUAL
Definition colorspaces.h:64
dt_colorspaces_color_profile_type_t
Definition colorspaces.h:81
@ DT_COLORSPACE_ADOBERGB
Definition colorspaces.h:85
@ DT_COLORSPACE_FILE
Definition colorspaces.h:83
@ DT_COLORSPACE_SRGB
Definition colorspaces.h:84
@ DT_COLORSPACE_NONE
Definition colorspaces.h:82
@ DT_PROFILE_DIRECTION_OUT
int type
GList * dt_metadata_get(const int id, const char *key, uint32_t *count)
char * name
dt_pdf_page_t * dt_pdf_add_page(dt_pdf_t *pdf, dt_pdf_image_t **images, int n_images)
Definition common/pdf.c:458
dt_pdf_image_t * dt_pdf_add_image(dt_pdf_t *pdf, const unsigned char *image, int width, int height, int bpp, int icc_id, float border)
Definition common/pdf.c:376
void dt_pdf_finish(dt_pdf_t *pdf, dt_pdf_page_t **pages, int n_pages)
Definition common/pdf.c:640
dt_pdf_t * dt_pdf_start(const char *filename, float width, float height, float dpi, dt_pdf_stream_encoder_t default_encoder)
Definition common/pdf.c:218
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
void dt_conf_set_float(const char *name, float val)
float dt_conf_get_float(const char *name)
gchar * dt_conf_get_string(const char *name)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
void dt_conf_set_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
void dt_control_set_mouse_over_id(int32_t value)
Definition control.c:931
void dt_control_log(const char *msg,...)
Definition control.c:761
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
Definition control.c:861
void dt_control_queue_redraw()
request redraw of the workspace. This redraws the whole workspace within a gdk critical section to pr...
Definition control.c:856
#define dt_control_change_cursor(cursor)
Definition control.h:116
void dt_get_printer_info(const char *printer_name, dt_printer_info_t *pinfo)
Definition cups_print.c:87
void dt_print_file(const int32_t imgid, const char *filename, const char *job_title, const dt_print_info_t *pinfo)
Definition cups_print.c:426
dt_medium_info_t * dt_get_medium(GList *media, const char *name)
Definition cups_print.c:410
GList * dt_get_media_type(const dt_printer_info_t *printer)
Definition cups_print.c:373
void dt_printers_discovery(void(*cb)(dt_printer_info_t *pr, void *user_data), void *user_data)
Definition cups_print.c:215
dt_paper_info_t * dt_get_paper(GList *papers, const char *name)
Definition cups_print.c:245
GList * dt_get_papers(const dt_printer_info_t *printer)
Definition cups_print.c:271
void dt_init_print_info(dt_print_info_t *pinfo)
Definition cups_print.c:77
@ ALIGNMENT_CENTER
Definition cups_print.h:35
void expose(dt_view_t *self, cairo_t *cri, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
Definition darkroom.c:940
darktable_t darktable
Definition darktable.c:181
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
#define DT_MODULE(MODVER)
Definition darktable.h:140
static void dt_free_gpointer(gpointer ptr)
Definition darktable.h:463
#define dt_free(ptr)
Definition darktable.h:456
static const dt_aligned_pixel_simd_t value
Definition darktable.h:577
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
Definition darktable.h:893
#define PATH_MAX
Definition darktable.h:1062
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
void dtgtk_cairo_paint_alignment(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
@ CPF_SPECIAL_FLAG
Definition dtgtk/paint.h:71
void dt_loc_get_tmp_dir(char *tmpdir, size_t bufsize)
void dt_loc_get_datadir(char *datadir, size_t bufsize)
void dt_loc_get_user_config_dir(char *configdir, size_t bufsize)
void dt_gui_draw_rounded_rectangle(cairo_t *cr, float width, float height, float x, float y)
Definition gtk.c:2992
void dt_gui_add_help_link(GtkWidget *widget, char *link)
Definition gtk.c:2022
static GtkWidget * dt_ui_section_label_new(const gchar *str)
Definition gtk.h:451
#define DT_GUI_BOX_SPACING
Definition gtk.h:109
#define DT_PIXEL_APPLY_DPI(value)
Definition gtk.h:90
#define DT_GUI_MODULE(x)
const char * tooltip
Definition image.h:251
void dt_image_cache_read_release(dt_image_cache_t *cache, const dt_image_t *img)
dt_image_t * dt_image_cache_get(dt_image_cache_t *cache, const int32_t imgid, char mode)
void dt_image_cache_set_print_timestamp(dt_image_cache_t *cache, const int32_t imgid)
int bpp
int dt_imageio_export_with_flags(const int32_t imgid, const char *filename, dt_imageio_module_format_t *format, dt_imageio_module_data_t *format_params, const gboolean ignore_exif, const gboolean display_byteorder, const gboolean high_quality, gboolean is_scaling, const gboolean thumbnail_export, const char *filter, const gboolean copy_metadata, const gboolean export_masks, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_imageio_module_storage_t *storage, dt_imageio_module_data_t *storage_params, int num, int total, dt_export_metadata_t *metadata, dt_atomic_int *shutdown)
Definition imageio.c:961
@ IMAGEIO_INT16
Definition imageio.h:64
@ IMAGEIO_RGB
Definition imageio.h:70
@ IMAGEIO_INT8
Definition imageio.h:62
static const float x
const float v
dt_job_state_t dt_control_job_get_state(_dt_job_t *job)
Definition jobs.c:103
dt_job_t * dt_control_job_create(dt_job_execute_callback execute, const char *msg,...)
Definition jobs.c:135
int dt_control_add_job(dt_control_t *control, dt_job_queue_t queue_id, _dt_job_t *job)
Definition jobs.c:405
void * dt_control_job_get_params(const _dt_job_t *job)
Definition jobs.c:129
void dt_control_job_set_progress(dt_job_t *job, double value)
Definition jobs.c:626
void dt_control_job_add_progress(dt_job_t *job, const char *message, gboolean cancellable)
Definition jobs.c:612
void dt_control_job_set_params(_dt_job_t *job, void *params, dt_job_destroy_callback callback)
Definition jobs.c:112
void dt_control_job_dispose(_dt_job_t *job)
Definition jobs.c:153
@ DT_JOB_QUEUE_USER_EXPORT
Definition jobs.h:56
@ DT_JOB_STATE_CANCELLED
Definition jobs.h:46
static int precision(double x, double adj)
Definition lens.cc:1497
GtkWidget * dt_action_button_new(dt_lib_module_t *self, const gchar *label, gpointer callback, gpointer data, const gchar *tooltip, guint accel_key, GdkModifierType mods)
Definition lib.c:1563
float *const restrict const size_t k
size_t size
Definition mipmap_cache.c:3
#define dt_mipmap_cache_get(A, B, C, D, E, F)
@ DT_MIPMAP_BLOCKING
#define dt_mipmap_cache_release(A, B)
@ DT_MIPMAP_0
@ DT_MIPMAP_NONE
#define dt_pdf_pixel_to_point(px, dpi)
Definition pdf.h:44
#define dt_pdf_mm_to_point(mm)
Definition pdf.h:41
@ DT_PDF_STREAM_ENCODER_FLATE
Definition pdf.h:49
static void _page_delete_area(const dt_lib_module_t *self, const int box_index)
static void _print_job_cleanup(void *p)
_unit_t
@ UNIT_CM
@ UNIT_N
@ UNIT_IN
@ UNIT_MM
void gui_reset(dt_lib_module_t *self)
static GList * _get_profiles()
int set_params(dt_lib_module_t *self, const void *params, int size)
void _get_control(dt_lib_print_settings_t *ps, float x, float y)
void * get_params(dt_lib_module_t *self, int *size)
struct _dialog_description dialog_description_t
static void _printer_changed(GtkWidget *combo, const dt_lib_module_t *self)
static void _left_border_callback(GtkWidget *spin, gpointer user_data)
void gui_post_expose(struct dt_lib_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
static int _print_job_run(dt_job_t *job)
int mouse_leave(struct dt_lib_module_t *self)
static void _snap_grid_callback(GtkWidget *widget, dt_lib_module_t *self)
static void _print_button_clicked(GtkWidget *widget, gpointer user_data)
static const float units[UNIT_N]
static void _profile_changed(GtkWidget *widget, dt_lib_module_t *self)
static void _paper_changed(GtkWidget *combo, const dt_lib_module_t *self)
static void _grid_size_changed(GtkWidget *widget, dt_lib_module_t *self)
static float _vscreen_to_mm(dt_lib_print_settings_t *ps, const float value, const gboolean offset)
static void _printer_bpc_callback(GtkWidget *widget, dt_lib_module_t *self)
static void _grid_callback(GtkWidget *widget, dt_lib_module_t *self)
static void _y_changed(GtkWidget *widget, gpointer user_data)
static void _top_border_callback(GtkWidget *spin, gpointer user_data)
void _fill_box_values(dt_lib_print_settings_t *ps)
static void _orientation_changed(GtkWidget *combo, dt_lib_module_t *self)
static void _page_delete_area_clicked(GtkWidget *widget, gpointer user_data)
static void _print_settings_activate_or_update_callback(gpointer instance, int32_t imgid, gpointer user_data)
enum _set_controls dt_box_control_set
static void _create_pdf(dt_job_t *job, dt_images_box imgs, const float width, const float height)
static void _x_changed(GtkWidget *widget, gpointer user_data)
void gui_cleanup(dt_lib_module_t *self)
static void _swap(float *a, float *b)
static void _bottom_border_callback(GtkWidget *spin, gpointer user_data)
static float _to_mm(dt_lib_print_settings_t *ps, double value)
static void _width_changed(GtkWidget *widget, gpointer user_data)
static float _mm_to_hscreen(dt_lib_print_settings_t *ps, const float value, const gboolean offset)
static void _set_orientation(dt_lib_print_settings_t *ps, int32_t imgid)
static void _get_page_dimension(dt_print_info_t *prt, float *width, float *height)
static void _alignment_callback(GtkWidget *tb, gpointer user_data)
static void _lock_callback(GtkWidget *button, gpointer user_data)
static float _percent_unit_of(dt_lib_print_settings_t *ps, float ref, float value)
void _cairo_rectangle(cairo_t *cr, const int sel_controls, const int x1, const int y1, const int x2, const int y2)
static void _new_printer_callback(dt_printer_info_t *printer, void *user_data)
static void _style_callback(GtkWidget *widget, dt_lib_module_t *self)
int mouse_moved(struct dt_lib_module_t *self, double x, double y, double pressure, int which)
static void _intent_callback(GtkWidget *widget, dt_lib_module_t *self)
uint32_t container(dt_lib_module_t *self)
_set_controls
@ BOX_BOTTOM
@ BOX_LEFT
@ BOX_TOP
@ BOX_TOP_LEFT
@ BOX_BOTTOM_LEFT
@ BOX_RIGHT
@ BOX_ALL
@ BOX_TOP_RIGHT
@ BOX_BOTTOM_RIGHT
static void _printer_intent_callback(GtkWidget *widget, dt_lib_module_t *self)
static void _printer_profile_changed(GtkWidget *widget, dt_lib_module_t *self)
int button_pressed(struct dt_lib_module_t *self, double x, double y, double pressure, int which, int type, uint32_t state)
static void _update_slider(dt_lib_print_settings_t *ps)
static void _precision_by_unit(_unit_t unit, int *n_digits, float *incr, char **format)
static float _hscreen_to_mm(dt_lib_print_settings_t *ps, const float value, const gboolean offset)
static void _media_changed(GtkWidget *combo, const dt_lib_module_t *self)
static const char * mime(dt_imageio_module_data_t *data)
void view_leave(struct dt_lib_module_t *self, struct dt_view_t *old_view, struct dt_view_t *new_view)
void gui_init(dt_lib_module_t *self)
void view_enter(struct dt_lib_module_t *self, struct dt_view_t *old_view, struct dt_view_t *new_view)
int position()
const char ** views(dt_lib_module_t *self)
void * legacy_params(dt_lib_module_t *self, const void *const old_params, const size_t old_params_size, const int old_version, int *new_version, size_t *new_size)
static void _snap_to_grid(dt_lib_print_settings_t *ps, float *x, float *y)
static void _page_clear_area_clicked(GtkWidget *widget, gpointer user_data)
static int levels(dt_imageio_module_data_t *data)
static int write_image(dt_imageio_module_data_t *data, const char *filename, const void *in, dt_colorspaces_color_profile_type_t over_type, const char *over_filename, void *exif, int exif_len, int32_t imgid, int num, int total, dt_dev_pixelpipe_t *pipe, const gboolean export_masks)
static void _page_new_area_clicked(GtkWidget *widget, gpointer user_data)
static void _height_changed(GtkWidget *widget, gpointer user_data)
static int _export_and_setup_pos(dt_job_t *job, dt_image_box *img, const int32_t idx)
static float _mm_to_vscreen(dt_lib_print_settings_t *ps, const float value, const gboolean offset)
static void _right_border_callback(GtkWidget *spin, gpointer user_data)
static int _export_image(dt_job_t *job, dt_image_box *img)
static void _set_printer(const dt_lib_module_t *self, const char *printer_name)
static const gchar * _unit_names[]
int button_released(struct dt_lib_module_t *self, double x, double y, int which, uint32_t state)
static void _unit_changed(GtkWidget *combo, dt_lib_module_t *self)
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 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_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
int dt_apply_printer_profile(void **in, uint32_t width, uint32_t height, int bpp, cmsHPROFILE hInProfile, cmsHPROFILE hOutProfile, int intent, gboolean black_point_compensation)
Definition printprof.c:47
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
Definition signal.h:368
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
Definition signal.h:347
@ DT_SIGNAL_TAG_CHANGED
This signal is raised when a tag is added/deleted/changed
Definition signal.h:130
@ DT_SIGNAL_VIEWMANAGER_FILMSTRIP_ACTIVATE
This signal is raised when a thumb is single-clicked in the filmstrip. Views that want filmstrip clic...
Definition signal.h:103
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
Definition signal.h:357
struct _GtkWidget GtkWidget
Definition splash.h:29
void dt_style_free(gpointer data)
GList * dt_styles_get_list(const char *filter)
const float uint32_t state[4]
dt_image_pos screen
Definition printing.h:52
int32_t exp_height
Definition printing.h:47
int32_t exp_width
Definition printing.h:47
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
struct dt_gui_gtk_t * gui
Definition darktable.h:775
struct dt_colorspaces_t * color_profiles
Definition darktable.h:788
struct dt_mipmap_cache_t * mipmap_cache
Definition darktable.h:776
struct dt_control_signal_t * signals
Definition darktable.h:774
struct dt_bauhaus_t * bauhaus
Definition darktable.h:778
struct dt_image_cache_t * image_cache
Definition darktable.h:777
struct dt_view_manager_t * view_manager
Definition darktable.h:772
struct dt_control_t * control
Definition darktable.h:773
PangoFontDescription * pango_font_desc
Definition bauhaus.h:274
int32_t reset
Definition gtk.h:172
char filename[DT_MAX_FILENAME_LEN]
Definition image.h:304
int32_t imgid_to_load
Definition printing.h:72
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
dt_colorspaces_color_profile_type_t type
GModule *void * data
Definition lib.h:80
GtkWidget * widget
Definition lib.h:84
dt_colorspaces_color_profile_type_t p_icc_type
dt_iop_color_intent_t buf_icc_intent
char pdf_filename[PATH_MAX]
dt_pdf_page_t * pdf_page
dt_colorspaces_color_profile_type_t buf_icc_type
gboolean black_point_compensation
dt_print_info_t prt
dt_iop_color_intent_t p_icc_intent
dt_box_control_set sel_controls
GtkWidget * black_point_compensation
GtkToggleButton * lock_button
GtkDarktableToggleButton * dtba[9]
dt_mipmap_size_t size
double margin_bottom
Definition cups_print.h:56
double margin_right
Definition cups_print.h:56
double margin_left
Definition cups_print.h:56
double margin_top
Definition cups_print.h:56
gboolean landscape
Definition cups_print.h:55
float bb_x
Definition pdf.h:73
float bb_width
Definition pdf.h:73
float bb_y
Definition pdf.h:73
float bb_height
Definition pdf.h:73
Definition pdf.h:53
dt_lib_print_job_t * params
dt_imageio_module_data_t head
dt_medium_info_t medium
Definition cups_print.h:74
dt_paper_info_t paper
Definition cups_print.h:73
dt_printer_info_t printer
Definition cups_print.h:71
dt_page_setup_t page
Definition cups_print.h:72
dt_iop_color_intent_t intent
Definition cups_print.h:64
gboolean is_turboprint
Definition cups_print.h:66
gboolean borderless
Definition printing.h:66
dt_image_pos page
Definition printing.h:59
gchar * name
gboolean dt_tag_attach(const guint tagid, const int32_t imgid, const gboolean undo_on, const gboolean group_on)
Definition tags.c:485
gboolean dt_tag_new(const char *name, guint *tagid)
Definition tags.c:179
typedef double((*spd)(unsigned long int wavelength, double TempK))
#define MIN(a, b)
Definition thinplate.c:32
GtkWidget * dtgtk_togglebutton_new(DTGTKCairoPaintIconFunc paint, gint paintflags, void *paintdata)
#define DTGTK_TOGGLEBUTTON(obj)
char * dt_get_help_url(char *name)
size_t dt_utf8_strlcpy(char *dest, const char *src, size_t n)
Definition utility.c:289
@ DT_UI_CONTAINER_PANEL_RIGHT_CENTER