Update current version of litehtml. Fix a crash when document contains no fonts
[claws.git] / src / plugins / litehtml_viewer / litehtml / el_image.cpp
1 #include "html.h"
2 #include "el_image.h"
3 #include "document.h"
4
5 litehtml::el_image::el_image(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc)
6 {
7         m_display = display_inline_block;
8 }
9
10 litehtml::el_image::~el_image( void )
11 {
12
13 }
14
15 void litehtml::el_image::get_content_size( size& sz, int max_width )
16 {
17         get_document()->container()->get_image_size(m_src.c_str(), 0, sz);
18 }
19
20 int litehtml::el_image::line_height() const
21 {
22         return height();
23 }
24
25 bool litehtml::el_image::is_replaced() const
26 {
27         return true;
28 }
29
30 int litehtml::el_image::render( int x, int y, int max_width, bool second_pass )
31 {
32         int parent_width = max_width;
33
34         calc_outlines(parent_width);
35
36         m_pos.move_to(x, y);
37
38         document::ptr doc = get_document();
39
40         litehtml::size sz;
41         doc->container()->get_image_size(m_src.c_str(), 0, sz);
42
43         m_pos.width             = sz.width;
44         m_pos.height    = sz.height;
45
46         if(m_css_height.is_predefined() && m_css_width.is_predefined())
47         {
48                 m_pos.height    = sz.height;
49                 m_pos.width             = sz.width;
50
51                 // check for max-height
52                 if(!m_css_max_width.is_predefined())
53                 {
54                         int max_width = doc->cvt_units(m_css_max_width, m_font_size, parent_width);
55                         if(m_pos.width > max_width)
56                         {
57                                 m_pos.width = max_width;
58                         }
59                         if(sz.width)
60                         {
61                                 m_pos.height = (int) ((float) m_pos.width * (float) sz.height / (float)sz.width);
62                         } else
63                         {
64                                 m_pos.height = sz.height;
65                         }
66                 }
67
68                 // check for max-height
69                 if(!m_css_max_height.is_predefined())
70                 {
71                         int max_height = doc->cvt_units(m_css_max_height, m_font_size);
72                         if(m_pos.height > max_height)
73                         {
74                                 m_pos.height = max_height;
75                         }
76                         if(sz.height)
77                         {
78                                 m_pos.width = (int) (m_pos.height * (float)sz.width / (float)sz.height);
79                         } else
80                         {
81                                 m_pos.width = sz.width;
82                         }
83                 }
84         } else if(!m_css_height.is_predefined() && m_css_width.is_predefined())
85         {
86                 if (!get_predefined_height(m_pos.height))
87                 {
88                         m_pos.height = (int)m_css_height.val();
89                 }
90
91                 // check for max-height
92                 if(!m_css_max_height.is_predefined())
93                 {
94                         int max_height = doc->cvt_units(m_css_max_height, m_font_size);
95                         if(m_pos.height > max_height)
96                         {
97                                 m_pos.height = max_height;
98                         }
99                 }
100
101                 if(sz.height)
102                 {
103                         m_pos.width = (int) (m_pos.height * (float)sz.width / (float)sz.height);
104                 } else
105                 {
106                         m_pos.width = sz.width;
107                 }
108         } else if(m_css_height.is_predefined() && !m_css_width.is_predefined())
109         {
110                 m_pos.width = (int) m_css_width.calc_percent(parent_width);
111
112                 // check for max-width
113                 if(!m_css_max_width.is_predefined())
114                 {
115                         int max_width = doc->cvt_units(m_css_max_width, m_font_size, parent_width);
116                         if(m_pos.width > max_width)
117                         {
118                                 m_pos.width = max_width;
119                         }
120                 }
121
122                 if(sz.width)
123                 {
124                         m_pos.height = (int) ((float) m_pos.width * (float) sz.height / (float)sz.width);
125                 } else
126                 {
127                         m_pos.height = sz.height;
128                 }
129         } else
130         {
131                 m_pos.width             = (int) m_css_width.calc_percent(parent_width);
132                 m_pos.height    = 0;
133                 if (!get_predefined_height(m_pos.height))
134                 {
135                         m_pos.height = (int)m_css_height.val();
136                 }
137
138                 // check for max-height
139                 if(!m_css_max_height.is_predefined())
140                 {
141                         int max_height = doc->cvt_units(m_css_max_height, m_font_size);
142                         if(m_pos.height > max_height)
143                         {
144                                 m_pos.height = max_height;
145                         }
146                 }
147
148                 // check for max-height
149                 if(!m_css_max_width.is_predefined())
150                 {
151                         int max_width = doc->cvt_units(m_css_max_width, m_font_size, parent_width);
152                         if(m_pos.width > max_width)
153                         {
154                                 m_pos.width = max_width;
155                         }
156                 }
157         }
158
159         calc_auto_margins(parent_width);
160
161         m_pos.x += content_margins_left();
162         m_pos.y += content_margins_top();
163
164         return m_pos.width + content_margins_left() + content_margins_right();
165 }
166
167 void litehtml::el_image::parse_attributes()
168 {
169         m_src = get_attr(_t("src"), _t(""));
170
171         const tchar_t* attr_height = get_attr(_t("height"));
172         if(attr_height)
173         {
174                 m_style.add_property(_t("height"), attr_height, 0, false);
175         }
176         const tchar_t* attr_width = get_attr(_t("width"));
177         if(attr_width)
178         {
179                 m_style.add_property(_t("width"), attr_width, 0, false);
180         }
181 }
182
183 void litehtml::el_image::draw( uint_ptr hdc, int x, int y, const position* clip )
184 {
185         position pos = m_pos;
186         pos.x += x;
187         pos.y += y;
188
189         position el_pos = pos;
190         el_pos += m_padding;
191         el_pos += m_borders;
192
193         // draw standard background here
194         if (el_pos.does_intersect(clip))
195         {
196                 const background* bg = get_background();
197                 if (bg)
198                 {
199                         background_paint bg_paint;
200                         init_background_paint(pos, bg_paint, bg);
201
202                         get_document()->container()->draw_background(hdc, bg_paint);
203                 }
204         }
205
206         // draw image as background
207         if(pos.does_intersect(clip))
208         {
209                 if (pos.width > 0 && pos.height > 0) {
210                         background_paint bg;
211                         bg.image                                = m_src;
212                         bg.clip_box                             = pos;
213                         bg.origin_box                   = pos;
214                         bg.border_box                   = pos;
215                         bg.border_box                   += m_padding;
216                         bg.border_box                   += m_borders;
217                         bg.repeat                               = background_repeat_no_repeat;
218                         bg.image_size.width             = pos.width;
219                         bg.image_size.height    = pos.height;
220                         bg.border_radius                = m_css_borders.radius.calc_percents(bg.border_box.width, bg.border_box.height);
221                         bg.position_x                   = pos.x;
222                         bg.position_y                   = pos.y;
223                         get_document()->container()->draw_background(hdc, bg);
224                 }
225         }
226
227         // draw borders
228         if (el_pos.does_intersect(clip))
229         {
230                 position border_box = pos;
231                 border_box += m_padding;
232                 border_box += m_borders;
233
234                 borders bdr = m_css_borders;
235                 bdr.radius = m_css_borders.radius.calc_percents(border_box.width, border_box.height);
236
237                 get_document()->container()->draw_borders(hdc, bdr, border_box, have_parent() ? false : true);
238         }
239 }
240
241 void litehtml::el_image::parse_styles( bool is_reparse /*= false*/ )
242 {
243         html_tag::parse_styles(is_reparse);
244
245         if(!m_src.empty())
246         {
247                 if(!m_css_height.is_predefined() && !m_css_width.is_predefined())
248                 {
249                         get_document()->container()->load_image(m_src.c_str(), 0, true);
250                 } else
251                 {
252                         get_document()->container()->load_image(m_src.c_str(), 0, false);
253                 }
254         }
255 }