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 <glib.h>
21 
22 #include "litehtml/litehtml.h"
23 
24 #include "lh_widget.h"
25 
create_font(const litehtml::tchar_t * faceName,int size,int weight,litehtml::font_style italic,unsigned int decoration,litehtml::font_metrics * fm)26 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 )
27 {
28 	PangoFontDescription *desc =
29 		pango_font_description_from_string(faceName);
30 
31 	pango_font_description_set_size(desc, size * PANGO_SCALE);
32 	pango_font_description_set_weight(desc, (PangoWeight)weight);
33 
34 	if (italic == litehtml::fontStyleItalic)
35 		pango_font_description_set_style(desc, PANGO_STYLE_ITALIC);
36 	else
37 		pango_font_description_set_style(desc, PANGO_STYLE_NORMAL);
38 
39 	if(fm != NULL) {
40 		PangoContext *context = gtk_widget_get_pango_context(m_drawing_area);
41 		PangoFontMetrics *metrics = pango_context_get_metrics(
42 				context, desc,
43 				pango_context_get_language(context));
44 		PangoLayout *x_layout;
45 		PangoRectangle rect;
46 
47 		x_layout = pango_layout_new(context);
48 		pango_layout_set_font_description(x_layout, desc);
49 		pango_layout_set_text(x_layout, "x", -1);
50 		pango_layout_get_pixel_extents(x_layout, NULL, &rect);
51 
52 		fm->ascent		= pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
53 		fm->descent		= pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
54 		fm->height		= fm->ascent + fm->descent;
55 		fm->x_height	= rect.height;
56 
57 		g_object_unref(x_layout);
58 		pango_font_metrics_unref(metrics);
59 	}
60 
61 	pango_font *ret = new pango_font;
62 	ret->font = desc;
63 	ret->strikethrough = (decoration & litehtml::font_decoration_linethrough) ? true : false;
64 	ret->underline = (decoration & litehtml::font_decoration_underline) ? true : false;
65 
66 	return (litehtml::uint_ptr) ret;
67 }
68 
delete_font(litehtml::uint_ptr hFont)69 void lh_widget::delete_font( litehtml::uint_ptr hFont )
70 {
71 	pango_font *fnt = (pango_font *)hFont;
72 
73 	if (fnt != NULL) {
74 		pango_font_description_free(fnt->font);
75 		delete fnt;
76 	}
77 }
78 
text_width(const litehtml::tchar_t * text,litehtml::uint_ptr hFont)79 int lh_widget::text_width( const litehtml::tchar_t* text, litehtml::uint_ptr hFont )
80 {
81 	pango_font *fnt = (pango_font *) hFont;
82 	PangoContext *context = gtk_widget_get_pango_context(m_drawing_area);
83 	PangoLayout *layout = pango_layout_new(context);
84 	PangoRectangle rect;
85 
86 	if (fnt)
87 		pango_layout_set_font_description(layout, fnt->font);
88 
89 	pango_layout_set_text(layout, text, -1);
90 	pango_layout_get_pixel_extents(layout, NULL, &rect);
91 
92 	g_object_unref(layout);
93 
94 	return rect.width;
95 }
96 
draw_text(litehtml::uint_ptr hdc,const litehtml::tchar_t * text,litehtml::uint_ptr hFont,litehtml::web_color color,const litehtml::position & pos)97 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 )
98 {
99 	pango_font *fnt = (pango_font *)hFont;
100 	cairo_t *cr = (cairo_t *)hdc;
101 	PangoLayout *layout = pango_cairo_create_layout(cr);
102 	PangoContext *context = pango_layout_get_context(layout);
103 	GdkScreen* screen = gdk_screen_get_default();
104 	double dpi = gdk_screen_get_resolution(screen);
105 
106 	pango_cairo_context_set_resolution(context, dpi);
107 
108 	if (fnt != NULL) {
109 		/* Set font */
110 		pango_layout_set_font_description(layout, fnt->font);
111 
112 		/* Set additional font attributes */
113 		if (fnt->underline || fnt->strikethrough) {
114 			PangoAttrList *attr_list = pango_attr_list_new();
115 			PangoUnderline ul;
116 
117 			if (fnt->underline )
118 				ul = PANGO_UNDERLINE_SINGLE;
119 			else
120 				ul = PANGO_UNDERLINE_NONE;
121 
122 			pango_attr_list_insert(attr_list,
123 					pango_attr_underline_new(ul));
124 			pango_attr_list_insert(attr_list,
125 					pango_attr_strikethrough_new(fnt->strikethrough));
126 
127 			pango_layout_set_attributes(layout, attr_list);
128 			pango_attr_list_unref(attr_list);
129 		}
130 	}
131 
132 	/* Set actual text content */
133 	pango_layout_set_text(layout, text, -1);
134 
135 	cairo_save(cr);
136 
137 	/* Draw the text where it's supposed to be */
138 	apply_clip(cr);
139 	set_color(cr, color);
140 	cairo_move_to(cr, pos.left(), pos.top());
141 	pango_cairo_show_layout(cr, layout);
142 
143 	/* Cleanup */
144 	g_object_unref(layout);
145 	cairo_restore(cr);
146 }
147