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