]> git.tdb.fi Git - ext/subsurface.git/blob - print.c
Do the pango text layout in multiple chunks
[ext/subsurface.git] / print.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #include <gtk/gtk.h>
5
6 #include "dive.h"
7 #include "display.h"
8 #include "display-gtk.h"
9
10 /*
11  * You know what? Maybe somebody can do a real Pango layout thing.
12  * This is hacky.
13  */
14 static void show_dive_text(struct dive *dive, cairo_t *cr, double w, double h, PangoFontDescription *font)
15 {
16         int len, width, height, maxwidth, maxheight;
17         PangoLayout *layout;
18         struct tm *tm;
19         char buffer[1024], divenr[20];
20
21         maxwidth = w * PANGO_SCALE;
22         maxheight = h * PANGO_SCALE * 0.9;
23
24         layout = pango_cairo_create_layout(cr);
25         pango_layout_set_font_description(layout, font);
26         pango_layout_set_width(layout, maxwidth);
27         pango_layout_set_height(layout, maxheight);
28         pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
29
30         *divenr = 0;
31         if (dive->number)
32                 snprintf(divenr, sizeof(divenr), "Dive #%d - ", dive->number);
33
34
35         tm = gmtime(&dive->when);
36         len = snprintf(buffer, sizeof(buffer),
37                 "<span size=\"large\">"
38                 "%s%s, %s %d, %d   %d:%02d"
39                 "</span>",
40                 divenr,
41                 weekday(tm->tm_wday),
42                 monthname(tm->tm_mon),
43                 tm->tm_mday, tm->tm_year + 1900,
44                 tm->tm_hour, tm->tm_min);
45
46         pango_layout_set_justify(layout, 1);
47         pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
48         pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
49
50         pango_layout_set_markup(layout, buffer, len);
51         pango_layout_get_size(layout, &width, &height);
52
53         cairo_move_to(cr, 0, 0);
54         pango_cairo_show_layout(cr, layout);
55
56         /*
57          * This is still problematic: a long dive location will clash
58          * with the depth/duration information. Need to mask that or
59          * create a box or something.
60          */
61         snprintf(buffer, sizeof(buffer),
62                 "<span size=\"small\">"
63                 "Max depth: %d ft\n"
64                 "Duration: %d:%02d"
65                 "</span>",
66                 to_feet(dive->maxdepth),
67                 dive->duration.seconds / 60,
68                 dive->duration.seconds % 60);
69
70         pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
71         pango_layout_set_markup(layout, buffer, -1);
72
73         cairo_move_to(cr, 0, 0);
74         pango_cairo_show_layout(cr, layout);
75
76         len = snprintf(buffer, sizeof(buffer), "%s\n\n%s",
77                 dive->location ? : "",
78                 dive->notes ? : "");
79
80         maxheight -= height;
81         pango_layout_set_height(layout, maxheight);
82         pango_layout_set_attributes(layout, NULL);
83         pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
84         pango_layout_set_text(layout, buffer, len);
85
86         cairo_move_to(cr, 0, height / (double) PANGO_SCALE);
87         pango_cairo_show_layout(cr, layout);
88
89         g_object_unref(layout);
90 }
91
92 static void show_dive_profile(struct dive *dive, cairo_t *cr, double w, double h)
93 {
94         struct graphics_context gc = {
95                 .printer = 1,
96                 .cr = cr
97         };
98         cairo_save(cr);
99         plot(&gc, w, h, dive);
100         cairo_restore(cr);
101 }
102
103 static void print(int divenr, cairo_t *cr, double x, double y, double w, double h, PangoFontDescription *font)
104 {
105         struct dive *dive;
106
107         dive = get_dive(divenr);
108         if (!dive)
109                 return;
110         cairo_save(cr);
111         cairo_translate(cr, x, y);
112
113         /* Plus 5% on all sides */
114         cairo_translate(cr, w/20, h/20);
115         w *= 0.9; h *= 0.9;
116
117         /* We actually want to scale the text and the lines now */
118         cairo_scale(cr, 0.5, 0.5);
119
120         /* Dive plot in the upper two thirds - note the scaling */
121         show_dive_profile(dive, cr, w*2, h*1.33);
122
123         /* Dive information in the lower third */
124         cairo_translate(cr, 0, h*1.33);
125
126         show_dive_text(dive, cr, w*2, h*0.67, font);
127
128         cairo_restore(cr);
129 }
130
131 static void draw_page(GtkPrintOperation *operation,
132                         GtkPrintContext *context,
133                         gint page_nr,
134                         gpointer user_data)
135 {
136         int nr;
137         cairo_t *cr;
138         double w, h;
139         PangoFontDescription *font;
140
141         cr = gtk_print_context_get_cairo_context(context);
142         font = pango_font_description_from_string("Sans");
143
144         w = gtk_print_context_get_width(context)/2;
145         h = gtk_print_context_get_height(context)/3;
146
147         nr = page_nr*6;
148         print(nr+0, cr, 0,   0, w, h, font);
149         print(nr+1, cr, w,   0, w, h, font);
150         print(nr+2, cr, 0,   h, w, h, font);
151         print(nr+3, cr, w,   h, w, h, font);
152         print(nr+4, cr, 0, 2*h, w, h, font);
153         print(nr+5, cr, w, 2*h, w, h, font);
154
155         pango_font_description_free(font);
156 }
157
158 static void begin_print(GtkPrintOperation *operation, gpointer user_data)
159 {
160 }
161
162 static GtkPrintSettings *settings = NULL;
163
164 void do_print(void)
165 {
166         int pages;
167         GtkPrintOperation *print;
168         GtkPrintOperationResult res;
169
170         repaint_dive();
171         print = gtk_print_operation_new();
172         if (settings != NULL)
173                 gtk_print_operation_set_print_settings(print, settings);
174         pages = (dive_table.nr + 5) / 6;
175         gtk_print_operation_set_n_pages(print, pages);
176         g_signal_connect(print, "begin_print", G_CALLBACK(begin_print), NULL);
177         g_signal_connect(print, "draw_page", G_CALLBACK(draw_page), NULL);
178         res = gtk_print_operation_run(print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
179                                          GTK_WINDOW(main_window), NULL);
180         if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
181                 if (settings != NULL)
182                         g_object_unref(settings);
183                 settings = g_object_ref(gtk_print_operation_get_print_settings(print));
184         }
185         g_object_unref(print);
186 }