Line data Source code
1 : /* File: pencil_diagram_painter.c; Copyright and License: see below */
2 :
3 : #include "pencil_diagram_painter.h"
4 : #include "u8/u8_trace.h"
5 : #include <pango/pangocairo.h>
6 : #include <stdio.h>
7 : #include <stdlib.h>
8 : #include <assert.h>
9 :
10 0 : void pencil_diagram_painter_init( pencil_diagram_painter_t *this_ )
11 : {
12 0 : U8_TRACE_BEGIN();
13 :
14 0 : pencil_marker_init( &((*this_).marker) );
15 0 : draw_diagram_label_init( &((*this_).draw_diagram_label) );
16 :
17 0 : U8_TRACE_END();
18 0 : }
19 :
20 0 : void pencil_diagram_painter_destroy( pencil_diagram_painter_t *this_ )
21 : {
22 0 : U8_TRACE_BEGIN();
23 :
24 0 : draw_diagram_label_init( &((*this_).draw_diagram_label) );
25 0 : pencil_marker_destroy( &((*this_).marker) );
26 :
27 0 : U8_TRACE_END();
28 0 : }
29 :
30 0 : void pencil_diagram_painter_draw ( const pencil_diagram_painter_t *this_,
31 : const layout_diagram_t *layouted_diagram,
32 : bool mark_focused,
33 : bool mark_highlighted,
34 : bool mark_selected,
35 : const data_profile_part_t *profile,
36 : const pencil_size_t *pencil_size,
37 : PangoLayout *font_layout,
38 : cairo_t *cr )
39 : {
40 0 : U8_TRACE_BEGIN();
41 0 : assert( NULL != layouted_diagram );
42 0 : assert( NULL != profile );
43 0 : assert( NULL != pencil_size );
44 0 : assert( NULL != font_layout );
45 0 : assert( NULL != cr );
46 :
47 0 : const data_diagram_t *const the_diagram = layout_diagram_get_data_const( layouted_diagram );
48 0 : const geometry_rectangle_t *const diagram_bounds = layout_diagram_get_bounds_const( layouted_diagram );
49 0 : const geometry_rectangle_t *const label_box = layout_diagram_get_label_box_const( layouted_diagram );
50 :
51 0 : const double left = geometry_rectangle_get_left ( diagram_bounds );
52 0 : const double top = geometry_rectangle_get_top ( diagram_bounds );
53 0 : const double right = geometry_rectangle_get_right ( diagram_bounds );
54 0 : const double bottom = geometry_rectangle_get_bottom ( diagram_bounds );
55 0 : const double width = geometry_rectangle_get_width ( diagram_bounds );
56 0 : const double height = geometry_rectangle_get_height ( diagram_bounds );
57 :
58 0 : U8_TRACE_INFO_INT( "w", (int)(width) );
59 0 : U8_TRACE_INFO_INT( "h", (int)(height) );
60 :
61 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
62 0 : const double f_tab_size = pencil_size_get_font_tab_size( pencil_size );
63 :
64 : /* draw diagram border and name */
65 : {
66 0 : U8_TRACE_INFO_INT("drawing diagram id",data_diagram_get_row_id(the_diagram));
67 :
68 0 : const double std_line_width = pencil_size_get_standard_line_width( pencil_size );
69 0 : cairo_set_line_width( cr, std_line_width );
70 0 : if ( data_diagram_is_valid(the_diagram) )
71 : {
72 : /* draw border line */
73 : const GdkRGBA fg_color
74 : = mark_highlighted
75 0 : ? pencil_size_get_highlight_color( pencil_size )
76 0 : : pencil_size_get_standard_color( pencil_size );
77 0 : cairo_set_source_rgba( cr, fg_color.red, fg_color.green, fg_color.blue, fg_color.alpha );
78 0 : cairo_rectangle ( cr, left+gap, top+gap, width-2.0*gap, height-2.0*gap );
79 0 : cairo_stroke (cr);
80 :
81 : /* draw title corner */
82 0 : draw_diagram_label_draw_type_and_name( &((*this_).draw_diagram_label),
83 : the_diagram,
84 : profile,
85 : &fg_color,
86 : label_box,
87 : pencil_size,
88 : font_layout,
89 : cr
90 : );
91 :
92 0 : const double title_corner_height = geometry_rectangle_get_height( label_box ) + 2.0 * gap;
93 0 : const double title_corner_edge45 = 0.4 * title_corner_height;
94 0 : double title_corner_width
95 0 : = geometry_rectangle_get_width( label_box ) + 2.0 * gap + 2.0 * f_tab_size + title_corner_edge45;
96 0 : if ( title_corner_width > width*0.9 )
97 : {
98 0 : title_corner_width = width*0.9;
99 : }
100 0 : cairo_move_to ( cr, left+gap, top+gap+title_corner_height );
101 0 : cairo_line_to ( cr, left+gap+title_corner_width - title_corner_edge45, top+gap+title_corner_height );
102 0 : cairo_line_to ( cr, left+gap+title_corner_width, top+gap+title_corner_height-title_corner_edge45 );
103 0 : cairo_line_to ( cr, left+gap+title_corner_width, top+gap );
104 0 : cairo_stroke (cr);
105 : }
106 : else
107 : {
108 : /* draw cross line */
109 : GdkRGBA standard_color;
110 0 : standard_color = pencil_size_get_standard_color( pencil_size );
111 0 : cairo_set_source_rgba( cr, standard_color.red, standard_color.green, standard_color.blue, standard_color.alpha );
112 0 : cairo_move_to ( cr, left, top );
113 0 : cairo_line_to ( cr, right, bottom );
114 0 : cairo_move_to ( cr, left, bottom );
115 0 : cairo_line_to ( cr, right, top );
116 0 : cairo_stroke (cr);
117 : }
118 : }
119 :
120 : /* draw id */
121 : {
122 : /* prepare text */
123 0 : const data_id_t the_id = data_diagram_get_data_id(the_diagram);
124 :
125 : char id_buf[DATA_ID_MAX_UTF8STRING_SIZE+5];
126 0 : utf8stringbuf_t id_str = UTF8STRINGBUF( id_buf );
127 0 : utf8stringbuf_copy_str( id_str, "{id=" );
128 0 : data_id_to_utf8stringbuf( &the_id, id_str );
129 0 : utf8stringbuf_append_str( id_str, "}" );
130 :
131 : int text4_width;
132 : int text4_height;
133 0 : pango_layout_set_font_description (font_layout, pencil_size_get_footnote_font_description(pencil_size) );
134 0 : pango_layout_set_text (font_layout, utf8stringbuf_get_string( id_str ), -1);
135 0 : pango_layout_get_pixel_size (font_layout, &text4_width, &text4_height);
136 0 : text4_height += PENCIL_SIZE_FONT_ALIGN_MARGIN; /* allow to align font with pixel border */
137 0 : text4_width += PENCIL_SIZE_FONT_ALIGN_MARGIN;
138 :
139 : /* draw text */
140 : GdkRGBA grey_color;
141 0 : grey_color = pencil_size_get_gray_out_color( pencil_size );
142 0 : cairo_set_source_rgba( cr, grey_color.red, grey_color.green, grey_color.blue, grey_color.alpha );
143 0 : cairo_move_to( cr,
144 0 : ceil( left + width - text4_width - gap - gap ),
145 : ceil( top + gap )
146 : ); /* align font with pixel border */
147 0 : pango_cairo_show_layout( cr, font_layout );
148 : }
149 :
150 : /* mark focused and highlighted */
151 : {
152 0 : if ( mark_focused )
153 : {
154 0 : pencil_marker_mark_focused_rectangle( &((*this_).marker), *diagram_bounds, cr );
155 : }
156 :
157 0 : if ( mark_selected )
158 : {
159 : geometry_rectangle_t selected_rect;
160 0 : geometry_rectangle_init( &selected_rect, left+gap, top+gap, width-2.0*gap, height-2.0*gap );
161 0 : pencil_marker_mark_selected_rectangle( &((*this_).marker), selected_rect, cr );
162 0 : geometry_rectangle_destroy( &selected_rect );
163 : }
164 : }
165 :
166 0 : U8_TRACE_END();
167 0 : }
168 :
169 0 : void pencil_diagram_painter_do_layout ( const pencil_diagram_painter_t *this_,
170 : const data_diagram_t *the_diagram,
171 : const geometry_rectangle_t *diagram_bounds,
172 : const data_profile_part_t *profile,
173 : const pencil_size_t *pencil_size,
174 : PangoLayout *font_layout,
175 : layout_diagram_t *io_layout_diagram )
176 : {
177 0 : U8_TRACE_BEGIN();
178 0 : assert( NULL != the_diagram );
179 0 : assert( NULL != diagram_bounds );
180 0 : assert( NULL != profile );
181 0 : assert( NULL != pencil_size );
182 0 : assert( NULL != font_layout );
183 0 : assert( NULL != io_layout_diagram );
184 :
185 : /* determine diagram bounds */
186 0 : const double left = geometry_rectangle_get_left ( diagram_bounds );
187 0 : const double top = geometry_rectangle_get_top ( diagram_bounds );
188 0 : const double width = geometry_rectangle_get_width ( diagram_bounds );
189 0 : const double height = geometry_rectangle_get_height ( diagram_bounds );
190 0 : const double gap = pencil_size_get_standard_object_border( pencil_size );
191 0 : const double f_tab_size = pencil_size_get_font_tab_size( pencil_size );
192 :
193 : /* calculate label_box */
194 0 : const double text_left = left + 2.0 * gap + f_tab_size;
195 0 : const double text_top = top + 2.0 * gap;
196 0 : const geometry_dimensions_t label_dim_proposal
197 0 : = { .width = width, .height = pencil_size_get_standard_font_size( pencil_size ) };
198 : geometry_dimensions_t label_dim;
199 0 : draw_diagram_label_get_type_and_name_dimensions( &((*this_).draw_diagram_label),
200 : the_diagram,
201 : profile,
202 : &label_dim_proposal,
203 : pencil_size,
204 : font_layout,
205 : &label_dim
206 : );
207 0 : const double text_width = geometry_dimensions_get_width( &label_dim );
208 0 : const double text_height = geometry_dimensions_get_height( &label_dim );
209 : geometry_rectangle_t label_box;
210 0 : geometry_rectangle_init( &label_box, text_left, text_top, text_width, text_height );
211 :
212 : /* calculate space */
213 0 : const double space_left = left + 2.0 * gap;
214 0 : const double space_top = top + 4.0 * gap + text_height;
215 0 : const double space_width = width - 4.0 * gap;
216 0 : const double space_height = height - 6.0 * gap - text_height;
217 : geometry_rectangle_t space;
218 0 : if ( ( space_width <= 0.0 ) || ( space_height <= 0.0 ) )
219 : {
220 0 : geometry_rectangle_init_empty( &space );
221 : }
222 : else
223 : {
224 0 : geometry_rectangle_init( &space, space_left, space_top, space_width, space_height );
225 : }
226 :
227 : /* set new metrics */
228 0 : layout_diagram_set_bounds( io_layout_diagram, diagram_bounds );
229 0 : layout_diagram_set_draw_area( io_layout_diagram, &space );
230 0 : layout_diagram_set_label_box( io_layout_diagram, &label_box );
231 :
232 0 : geometry_rectangle_destroy( &space );
233 0 : geometry_rectangle_destroy( &label_box );
234 0 : U8_TRACE_END();
235 0 : }
236 :
237 :
238 : /*
239 : Copyright 2017-2024 Andreas Warnke
240 :
241 : Licensed under the Apache License, Version 2.0 (the "License");
242 : you may not use this file except in compliance with the License.
243 : You may obtain a copy of the License at
244 :
245 : http://www.apache.org/licenses/LICENSE-2.0
246 :
247 : Unless required by applicable law or agreed to in writing, software
248 : distributed under the License is distributed on an "AS IS" BASIS,
249 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
250 : See the License for the specific language governing permissions and
251 : limitations under the License.
252 : */
|