fix CID 1596595: Resource leaks, and CID 1596594: (CHECKED_RETURN)
[claws.git] / src / plugins / litehtml_viewer / lh_widget_text.cpp
1 /*
2  * Claws Mail -- A GTK+ based, lightweight, and fast e-mail client
3  * Copyright(C) 2019 the Claws Mail Team
4  *
5  * litehtml callbacks related to text rendering
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write tothe Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21
22 #include <glib.h>
23
24 #include "litehtml/litehtml.h"
25
26 #include "lh_widget.h"
27
28 litehtml::uint_ptr lh_widget::create_font( const litehtml::tchar_t* faceName, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm )
29 {
30         PangoFontDescription *desc =
31                 pango_font_description_from_string(faceName);
32
33         pango_font_description_set_size(desc, size * PANGO_SCALE);
34         pango_font_description_set_weight(desc, (PangoWeight)weight);
35
36         if (italic == litehtml::fontStyleItalic)
37                 pango_font_description_set_style(desc, PANGO_STYLE_ITALIC);
38         else
39                 pango_font_description_set_style(desc, PANGO_STYLE_NORMAL);
40
41         if(fm != NULL) {
42                 PangoContext *context = gtk_widget_get_pango_context(m_drawing_area);
43                 PangoFontMetrics *metrics = pango_context_get_metrics(
44                                 context, desc,
45                                 pango_context_get_language(context));
46                 PangoLayout *x_layout;
47                 PangoRectangle rect;
48
49                 x_layout = pango_layout_new(context);
50                 pango_layout_set_font_description(x_layout, desc);
51                 pango_layout_set_text(x_layout, "x", -1);
52                 pango_layout_get_pixel_extents(x_layout, NULL, &rect);
53
54                 fm->ascent              = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
55                 fm->descent             = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
56                 fm->height              = fm->ascent + fm->descent;
57                 fm->x_height    = rect.height;
58
59                 g_object_unref(x_layout);
60                 pango_font_metrics_unref(metrics);
61         }
62
63         pango_font *ret = new pango_font;
64         ret->font = desc;
65         ret->strikethrough = (decoration & litehtml::font_decoration_linethrough) ? true : false;
66         ret->underline = (decoration & litehtml::font_decoration_underline) ? true : false;
67
68         return (litehtml::uint_ptr) ret;
69 }
70
71 void lh_widget::delete_font( litehtml::uint_ptr hFont )
72 {
73         pango_font *fnt = (pango_font *)hFont;
74
75         if (fnt != NULL) {
76                 pango_font_description_free(fnt->font);
77                 delete fnt;
78         }
79 }
80
81 int lh_widget::text_width( const litehtml::tchar_t* text, litehtml::uint_ptr hFont )
82 {
83         pango_font *fnt = (pango_font *) hFont;
84         PangoContext *context = gtk_widget_get_pango_context(m_drawing_area);
85         PangoLayout *layout = pango_layout_new(context);
86         PangoRectangle rect;
87
88         if (fnt)
89                 pango_layout_set_font_description(layout, fnt->font);
90
91         pango_layout_set_text(layout, text, -1);
92         pango_layout_get_pixel_extents(layout, NULL, &rect);
93
94         g_object_unref(layout);
95
96         return rect.width;
97 }
98
99 void lh_widget::draw_text( litehtml::uint_ptr hdc, const litehtml::tchar_t* text, litehtml::uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos )
100 {
101         pango_font *fnt = (pango_font *)hFont;
102         cairo_t *cr = (cairo_t *)hdc;
103         PangoLayout *layout = pango_cairo_create_layout(cr);
104         PangoContext *context = pango_layout_get_context(layout);
105         GdkScreen* screen = gdk_screen_get_default();
106         double dpi = gdk_screen_get_resolution(screen);
107
108         pango_cairo_context_set_resolution(context, dpi);
109
110         if (fnt != NULL) {
111                 /* Set font */
112                 pango_layout_set_font_description(layout, fnt->font);
113
114                 /* Set additional font attributes */
115                 if (fnt->underline || fnt->strikethrough) {
116                         PangoAttrList *attr_list = pango_attr_list_new();
117                         PangoUnderline ul;
118
119                         if (fnt->underline )
120                                 ul = PANGO_UNDERLINE_SINGLE;
121                         else
122                                 ul = PANGO_UNDERLINE_NONE;
123
124                         pango_attr_list_insert(attr_list,
125                                         pango_attr_underline_new(ul));
126                         pango_attr_list_insert(attr_list,
127                                         pango_attr_strikethrough_new(fnt->strikethrough));
128
129                         pango_layout_set_attributes(layout, attr_list);
130                         pango_attr_list_unref(attr_list);
131                 }
132         }
133
134         /* Set actual text content */
135         pango_layout_set_text(layout, text, -1);
136
137         cairo_save(cr);
138
139         /* Draw the text where it's supposed to be */
140         apply_clip(cr);
141         set_color(cr, color);
142         cairo_move_to(cr, pos.left(), pos.top());
143         pango_cairo_show_layout(cr, layout);
144
145         /* Cleanup */
146         g_object_unref(layout);
147         cairo_restore(cr);
148 }