1 #include "container_linux.h"
2 #define _USE_MATH_DEFINES
3 #include <math.h>
4 
5 #ifndef M_PI
6 #       define M_PI    3.14159265358979323846
7 #endif
8 
container_linux(void)9 container_linux::container_linux(void)
10 {
11 	m_temp_surface	= cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 2, 2);
12 	m_temp_cr		= cairo_create(m_temp_surface);
13 }
14 
~container_linux(void)15 container_linux::~container_linux(void)
16 {
17 	clear_images();
18 	cairo_surface_destroy(m_temp_surface);
19 	cairo_destroy(m_temp_cr);
20 }
21 
create_font(const litehtml::tchar_t * faceName,int size,int weight,litehtml::font_style italic,unsigned int decoration,litehtml::font_metrics * fm)22 litehtml::uint_ptr container_linux::create_font( const litehtml::tchar_t* faceName, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm )
23 {
24 	litehtml::string_vector fonts;
25 	litehtml::split_string(faceName, fonts, ",");
26 	litehtml::trim(fonts[0]);
27 
28 	cairo_font_face_t* fnt = 0;
29 
30 	FcPattern *pattern = FcPatternCreate();
31 	bool found = false;
32 	for(litehtml::string_vector::iterator i = fonts.begin(); i != fonts.end(); i++)
33 	{
34 		if(FcPatternAddString(pattern, FC_FAMILY, (unsigned char *) i->c_str()))
35 		{
36 			found = true;
37 			break;
38 		}
39 	}
40 	if(found)
41 	{
42 		if(italic == litehtml::fontStyleItalic )
43 		{
44 			FcPatternAddInteger (pattern, FC_SLANT, FC_SLANT_ITALIC);
45 		} else
46 		{
47 			FcPatternAddInteger (pattern, FC_SLANT, FC_SLANT_ROMAN);
48 		}
49 
50 		int fc_weight = FC_WEIGHT_NORMAL;
51 		if(weight >= 0 && weight < 150)			fc_weight = FC_WEIGHT_THIN;
52 		else if(weight >= 150 && weight < 250)	fc_weight = FC_WEIGHT_EXTRALIGHT;
53 		else if(weight >= 250 && weight < 350)	fc_weight = FC_WEIGHT_LIGHT;
54 		else if(weight >= 350 && weight < 450)	fc_weight = FC_WEIGHT_NORMAL;
55 		else if(weight >= 450 && weight < 550)	fc_weight = FC_WEIGHT_MEDIUM;
56 		else if(weight >= 550 && weight < 650)	fc_weight = FC_WEIGHT_SEMIBOLD;
57 		else if(weight >= 650 && weight < 750)	fc_weight = FC_WEIGHT_BOLD;
58 		else if(weight >= 750 && weight < 850)	fc_weight = FC_WEIGHT_EXTRABOLD;
59 		else if(weight >= 950)					fc_weight = FC_WEIGHT_BLACK;
60 
61 		FcPatternAddInteger (pattern, FC_WEIGHT, fc_weight);
62 
63 		fnt = cairo_ft_font_face_create_for_pattern(pattern);
64 	}
65 
66 	FcPatternDestroy(pattern);
67 
68 	cairo_font* ret = 0;
69 
70 	if(fm && fnt)
71 	{
72 		cairo_save(m_temp_cr);
73 
74 		cairo_set_font_face(m_temp_cr, fnt);
75 		cairo_set_font_size(m_temp_cr, size);
76 		cairo_font_extents_t ext;
77 		cairo_font_extents(m_temp_cr, &ext);
78 
79 		cairo_text_extents_t tex;
80 		cairo_text_extents(m_temp_cr, "x", &tex);
81 
82 		fm->ascent		= (int) ext.ascent;
83 		fm->descent		= (int) ext.descent;
84 		fm->height		= (int) (ext.ascent + ext.descent);
85 		fm->x_height	= (int) tex.height;
86 
87 		cairo_restore(m_temp_cr);
88 
89 		ret = new cairo_font;
90 		ret->font		= fnt;
91 		ret->size		= size;
92 		ret->strikeout 	= (decoration & litehtml::font_decoration_linethrough) ? true : false;
93 		ret->underline	= (decoration & litehtml::font_decoration_underline) ? true : false;
94 
95 	}
96 
97 	return (litehtml::uint_ptr) ret;
98 }
99 
delete_font(litehtml::uint_ptr hFont)100 void container_linux::delete_font( litehtml::uint_ptr hFont )
101 {
102 	cairo_font* fnt = (cairo_font*) hFont;
103 	if(fnt)
104 	{
105 		cairo_font_face_destroy(fnt->font);
106 		delete fnt;
107 	}
108 }
109 
text_width(const litehtml::tchar_t * text,litehtml::uint_ptr hFont)110 int container_linux::text_width( const litehtml::tchar_t* text, litehtml::uint_ptr hFont )
111 {
112 	cairo_font* fnt = (cairo_font*) hFont;
113 
114 	cairo_save(m_temp_cr);
115 
116 	cairo_set_font_size(m_temp_cr, fnt->size);
117 	cairo_set_font_face(m_temp_cr, fnt->font);
118 	cairo_text_extents_t ext;
119 	cairo_text_extents(m_temp_cr, text, &ext);
120 
121 	cairo_restore(m_temp_cr);
122 
123 	return (int) ext.x_advance;
124 }
125 
draw_text(litehtml::uint_ptr hdc,const litehtml::tchar_t * text,litehtml::uint_ptr hFont,litehtml::web_color color,const litehtml::position & pos)126 void container_linux::draw_text( litehtml::uint_ptr hdc, const litehtml::tchar_t* text, litehtml::uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos )
127 {
128 	cairo_font* fnt = (cairo_font*) hFont;
129 	cairo_t* cr		= (cairo_t*) hdc;
130 	cairo_save(cr);
131 
132 	apply_clip(cr);
133 
134 	cairo_set_font_face(cr, fnt->font);
135 	cairo_set_font_size(cr, fnt->size);
136 	cairo_font_extents_t ext;
137 	cairo_font_extents(cr, &ext);
138 
139 	int x = pos.left();
140 	int y = pos.bottom()	- ext.descent;
141 
142 	set_color(cr, color);
143 
144 	cairo_move_to(cr, x, y);
145 	cairo_show_text(cr, text);
146 
147 	int tw = 0;
148 
149 	if(fnt->underline || fnt->strikeout)
150 	{
151 		tw = text_width(text, hFont);
152 	}
153 
154 	if(fnt->underline)
155 	{
156 		cairo_set_line_width(cr, 1);
157 		cairo_move_to(cr, x, y + 1.5);
158 		cairo_line_to(cr, x + tw, y + 1.5);
159 		cairo_stroke(cr);
160 	}
161 	if(fnt->strikeout)
162 	{
163 		cairo_text_extents_t tex;
164 		cairo_text_extents(cr, "x", &tex);
165 
166 		int ln_y = y - tex.height / 2.0;
167 
168 		cairo_set_line_width(cr, 1);
169 		cairo_move_to(cr, x, (double) ln_y - 0.5);
170 		cairo_line_to(cr, x + tw, (double) ln_y - 0.5);
171 		cairo_stroke(cr);
172 	}
173 
174 	cairo_restore(cr);
175 }
176 
pt_to_px(int pt)177 int container_linux::pt_to_px( int pt )
178 {
179 	GdkScreen* screen = gdk_screen_get_default();
180 	double dpi = gdk_screen_get_resolution(screen);
181 
182 	return (int) ((double) pt * dpi / 72.0);
183 }
184 
get_default_font_size() const185 int container_linux::get_default_font_size() const
186 {
187 	return 16;
188 }
189 
draw_list_marker(litehtml::uint_ptr hdc,const litehtml::list_marker & marker)190 void container_linux::draw_list_marker( litehtml::uint_ptr hdc, const litehtml::list_marker& marker )
191 {
192 	if(!marker.image.empty())
193 	{
194 		/*litehtml::tstring url;
195 		make_url(marker.image.c_str(), marker.baseurl, url);
196 
197 		lock_images_cache();
198 		images_map::iterator img_i = m_images.find(url.c_str());
199 		if(img_i != m_images.end())
200 		{
201 			if(img_i->second)
202 			{
203 				draw_txdib((cairo_t*) hdc, img_i->second, marker.pos.x, marker.pos.y, marker.pos.width, marker.pos.height);
204 			}
205 		}
206 		unlock_images_cache();*/
207 	} else
208 	{
209 		switch(marker.marker_type)
210 		{
211 		case litehtml::list_style_type_circle:
212 			{
213 				draw_ellipse((cairo_t*) hdc, marker.pos.x, marker.pos.y, marker.pos.width, marker.pos.height, marker.color, 0.5);
214 			}
215 			break;
216 		case litehtml::list_style_type_disc:
217 			{
218 				fill_ellipse((cairo_t*) hdc, marker.pos.x, marker.pos.y, marker.pos.width, marker.pos.height, marker.color);
219 			}
220 			break;
221 		case litehtml::list_style_type_square:
222 			if(hdc)
223 			{
224 				cairo_t* cr = (cairo_t*) hdc;
225 				cairo_save(cr);
226 
227 				cairo_new_path(cr);
228 				cairo_rectangle(cr, marker.pos.x, marker.pos.y, marker.pos.width, marker.pos.height);
229 
230 				set_color(cr, marker.color);
231 				cairo_fill(cr);
232 				cairo_restore(cr);
233 			}
234 			break;
235 		default:
236 			/*do nothing*/
237 			break;
238 		}
239 	}
240 }
241 
load_image(const litehtml::tchar_t * src,const litehtml::tchar_t * baseurl,bool redraw_on_ready)242 void container_linux::load_image( const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, bool redraw_on_ready )
243 {
244 	litehtml::tstring url;
245 	make_url(src, baseurl, url);
246 	if(m_images.find(url.c_str()) == m_images.end())
247 	{
248 		try
249 		{
250 			Glib::RefPtr<Gdk::Pixbuf> img = get_image(url.c_str(), true);
251 			if(img)
252 			{
253 				m_images[url.c_str()] = img;
254 			}
255 		} catch(...)
256 		{
257 			int iii=0;
258 			iii++;
259 		}
260 	}
261 }
262 
get_image_size(const litehtml::tchar_t * src,const litehtml::tchar_t * baseurl,litehtml::size & sz)263 void container_linux::get_image_size( const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, litehtml::size& sz )
264 {
265 	litehtml::tstring url;
266 	make_url(src, baseurl, url);
267 
268 	images_map::iterator img = m_images.find(url.c_str());
269 	if(img != m_images.end())
270 	{
271 		sz.width	= img->second->get_width();
272 		sz.height	= img->second->get_height();
273 	} else
274 	{
275 		sz.width	= 0;
276 		sz.height	= 0;
277 	}
278 }
279 
draw_background(litehtml::uint_ptr hdc,const litehtml::background_paint & bg)280 void container_linux::draw_background( litehtml::uint_ptr hdc, const litehtml::background_paint& bg )
281 {
282 	cairo_t* cr = (cairo_t*) hdc;
283 	cairo_save(cr);
284 	apply_clip(cr);
285 
286 	rounded_rectangle(cr, bg.border_box, bg.border_radius);
287 	cairo_clip(cr);
288 
289 	cairo_rectangle(cr, bg.clip_box.x, bg.clip_box.y, bg.clip_box.width, bg.clip_box.height);
290 	cairo_clip(cr);
291 
292 	if(bg.color.alpha)
293 	{
294 		set_color(cr, bg.color);
295 		cairo_paint(cr);
296 	}
297 
298 	litehtml::tstring url;
299 	make_url(bg.image.c_str(), bg.baseurl.c_str(), url);
300 
301 	//lock_images_cache();
302 	images_map::iterator img_i = m_images.find(url.c_str());
303 	if(img_i != m_images.end() && img_i->second)
304 	{
305 		Glib::RefPtr<Gdk::Pixbuf> bgbmp = img_i->second;
306 
307 		Glib::RefPtr<Gdk::Pixbuf> new_img;
308 		if(bg.image_size.width != bgbmp->get_width() || bg.image_size.height != bgbmp->get_height())
309 		{
310 			new_img = bgbmp->scale_simple(bg.image_size.width, bg.image_size.height, Gdk::INTERP_BILINEAR);
311 			bgbmp = new_img;
312 		}
313 
314 		cairo_surface_t* img = surface_from_pixbuf(bgbmp);
315 		cairo_pattern_t *pattern = cairo_pattern_create_for_surface(img);
316 		cairo_matrix_t flib_m;
317 		cairo_matrix_init_identity(&flib_m);
318 		cairo_matrix_translate(&flib_m, -bg.position_x, -bg.position_y);
319 		cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
320 		cairo_pattern_set_matrix (pattern, &flib_m);
321 
322 		switch(bg.repeat)
323 		{
324 		case litehtml::background_repeat_no_repeat:
325 			draw_pixbuf(cr, bgbmp, bg.position_x, bg.position_y, bgbmp->get_width(), bgbmp->get_height());
326 			break;
327 
328 		case litehtml::background_repeat_repeat_x:
329 			cairo_set_source(cr, pattern);
330 			cairo_rectangle(cr, bg.clip_box.left(), bg.position_y, bg.clip_box.width, bgbmp->get_height());
331 			cairo_fill(cr);
332 			break;
333 
334 		case litehtml::background_repeat_repeat_y:
335 			cairo_set_source(cr, pattern);
336 			cairo_rectangle(cr, bg.position_x, bg.clip_box.top(), bgbmp->get_width(), bg.clip_box.height);
337 			cairo_fill(cr);
338 			break;
339 
340 		case litehtml::background_repeat_repeat:
341 			cairo_set_source(cr, pattern);
342 			cairo_rectangle(cr, bg.clip_box.left(), bg.clip_box.top(), bg.clip_box.width, bg.clip_box.height);
343 			cairo_fill(cr);
344 			break;
345 		}
346 
347 		cairo_pattern_destroy(pattern);
348 		cairo_surface_destroy(img);
349 
350 	}
351 //	unlock_images_cache();
352 	cairo_restore(cr);
353 }
354 
make_url(const litehtml::tchar_t * url,const litehtml::tchar_t * basepath,litehtml::tstring & out)355 void container_linux::make_url(const litehtml::tchar_t* url,	const litehtml::tchar_t* basepath, litehtml::tstring& out)
356 {
357 	out = url;
358 }
359 
add_path_arc(cairo_t * cr,double x,double y,double rx,double ry,double a1,double a2,bool neg)360 void container_linux::add_path_arc(cairo_t* cr, double x, double y, double rx, double ry, double a1, double a2, bool neg)
361 {
362 	if(rx > 0 && ry > 0)
363 	{
364 
365 		cairo_save(cr);
366 
367 		cairo_translate(cr, x, y);
368 		cairo_scale(cr, 1, ry / rx);
369 		cairo_translate(cr, -x, -y);
370 
371 		if(neg)
372 		{
373 			cairo_arc_negative(cr, x, y, rx, a1, a2);
374 		} else
375 		{
376 			cairo_arc(cr, x, y, rx, a1, a2);
377 		}
378 
379 		cairo_restore(cr);
380 	} else
381 	{
382 		cairo_move_to(cr, x, y);
383 	}
384 }
385 
draw_borders(litehtml::uint_ptr hdc,const litehtml::borders & borders,const litehtml::position & draw_pos,bool root)386 void container_linux::draw_borders(litehtml::uint_ptr hdc, const litehtml::borders& borders, const litehtml::position& draw_pos, bool root)
387 {
388 	cairo_t* cr = (cairo_t*) hdc;
389 	cairo_save(cr);
390 	apply_clip(cr);
391 
392 	cairo_new_path(cr);
393 
394 	int bdr_top		= 0;
395 	int bdr_bottom	= 0;
396 	int bdr_left	= 0;
397 	int bdr_right	= 0;
398 
399 	if(borders.top.width != 0 && borders.top.style > litehtml::border_style_hidden)
400 	{
401 		bdr_top = (int) borders.top.width;
402 	}
403 	if(borders.bottom.width != 0 && borders.bottom.style > litehtml::border_style_hidden)
404 	{
405 		bdr_bottom = (int) borders.bottom.width;
406 	}
407 	if(borders.left.width != 0 && borders.left.style > litehtml::border_style_hidden)
408 	{
409 		bdr_left = (int) borders.left.width;
410 	}
411 	if(borders.right.width != 0 && borders.right.style > litehtml::border_style_hidden)
412 	{
413 		bdr_right = (int) borders.right.width;
414 	}
415 
416 	// draw right border
417 	if(bdr_right)
418 	{
419 		set_color(cr, borders.right.color);
420 
421 		double r_top	= borders.radius.top_right_x;
422 		double r_bottom	= borders.radius.bottom_right_x;
423 
424 		if(r_top)
425 		{
426 			double end_angle	= 2 * M_PI;
427 			double start_angle	= end_angle - M_PI / 2.0  / ((double) bdr_top / (double) bdr_right + 1);
428 
429 			add_path_arc(cr,
430 				draw_pos.right() - r_top,
431 				draw_pos.top() + r_top,
432 				r_top - bdr_right,
433 				r_top - bdr_right + (bdr_right - bdr_top),
434 				end_angle,
435 				start_angle, true);
436 
437 			add_path_arc(cr,
438 				draw_pos.right() - r_top,
439 				draw_pos.top() + r_top,
440 				r_top,
441 				r_top,
442 				start_angle,
443 				end_angle, false);
444 		} else
445 		{
446 			cairo_move_to(cr, draw_pos.right() - bdr_right, draw_pos.top() + bdr_top);
447 			cairo_line_to(cr, draw_pos.right(), draw_pos.top());
448 		}
449 
450 		if(r_bottom)
451 		{
452 			cairo_line_to(cr, draw_pos.right(),	draw_pos.bottom() - r_bottom);
453 
454 			double start_angle	= 0;
455 			double end_angle	= start_angle + M_PI / 2.0  / ((double) bdr_bottom / (double) bdr_right + 1);
456 
457 			add_path_arc(cr,
458 				draw_pos.right() - r_bottom,
459 				draw_pos.bottom() - r_bottom,
460 				r_bottom,
461 				r_bottom,
462 				start_angle,
463 				end_angle, false);
464 
465 			add_path_arc(cr,
466 				draw_pos.right() - r_bottom,
467 				draw_pos.bottom() - r_bottom,
468 				r_bottom - bdr_right,
469 				r_bottom - bdr_right + (bdr_right - bdr_bottom),
470 				end_angle,
471 				start_angle, true);
472 		} else
473 		{
474 			cairo_line_to(cr, draw_pos.right(),	draw_pos.bottom());
475 			cairo_line_to(cr, draw_pos.right() - bdr_right,	draw_pos.bottom() - bdr_bottom);
476 		}
477 
478 		cairo_fill(cr);
479 	}
480 
481 	// draw bottom border
482 	if(bdr_bottom)
483 	{
484 		set_color(cr, borders.bottom.color);
485 
486 		double r_left	= borders.radius.bottom_left_x;
487 		double r_right	= borders.radius.bottom_right_x;
488 
489 		if(r_left)
490 		{
491 			double start_angle	= M_PI / 2.0;
492 			double end_angle	= start_angle + M_PI / 2.0  / ((double) bdr_left / (double) bdr_bottom + 1);
493 
494 			add_path_arc(cr,
495 				draw_pos.left() + r_left,
496 				draw_pos.bottom() - r_left,
497 				r_left - bdr_bottom + (bdr_bottom - bdr_left),
498 				r_left - bdr_bottom,
499 				start_angle,
500 				end_angle, false);
501 
502 			add_path_arc(cr,
503 				draw_pos.left() + r_left,
504 				draw_pos.bottom() - r_left,
505 				r_left,
506 				r_left,
507 				end_angle,
508 				start_angle, true);
509 		} else
510 		{
511 			cairo_move_to(cr, draw_pos.left(), draw_pos.bottom());
512 			cairo_line_to(cr, draw_pos.left() + bdr_left, draw_pos.bottom() - bdr_bottom);
513 		}
514 
515 		if(r_right)
516 		{
517 			cairo_line_to(cr, draw_pos.right() - r_right,	draw_pos.bottom());
518 
519 			double end_angle	= M_PI / 2.0;
520 			double start_angle	= end_angle - M_PI / 2.0  / ((double) bdr_right / (double) bdr_bottom + 1);
521 
522 			add_path_arc(cr,
523 				draw_pos.right() - r_right,
524 				draw_pos.bottom() - r_right,
525 				r_right,
526 				r_right,
527 				end_angle,
528 				start_angle, true);
529 
530 			add_path_arc(cr,
531 				draw_pos.right() - r_right,
532 				draw_pos.bottom() - r_right,
533 				r_right - bdr_bottom + (bdr_bottom - bdr_right),
534 				r_right - bdr_bottom,
535 				start_angle,
536 				end_angle, false);
537 		} else
538 		{
539 			cairo_line_to(cr, draw_pos.right() - bdr_right,	draw_pos.bottom() - bdr_bottom);
540 			cairo_line_to(cr, draw_pos.right(),	draw_pos.bottom());
541 		}
542 
543 		cairo_fill(cr);
544 	}
545 
546 	// draw top border
547 	if(bdr_top)
548 	{
549 		set_color(cr, borders.top.color);
550 
551 		double r_left	= borders.radius.top_left_x;
552 		double r_right	= borders.radius.top_right_x;
553 
554 		if(r_left)
555 		{
556 			double end_angle	= M_PI * 3.0 / 2.0;
557 			double start_angle	= end_angle - M_PI / 2.0  / ((double) bdr_left / (double) bdr_top + 1);
558 
559 			add_path_arc(cr,
560 				draw_pos.left() + r_left,
561 				draw_pos.top() + r_left,
562 				r_left,
563 				r_left,
564 				end_angle,
565 				start_angle, true);
566 
567 			add_path_arc(cr,
568 				draw_pos.left() + r_left,
569 				draw_pos.top() + r_left,
570 				r_left - bdr_top + (bdr_top - bdr_left),
571 				r_left - bdr_top,
572 				start_angle,
573 				end_angle, false);
574 		} else
575 		{
576 			cairo_move_to(cr, draw_pos.left(), draw_pos.top());
577 			cairo_line_to(cr, draw_pos.left() + bdr_left, draw_pos.top() + bdr_top);
578 		}
579 
580 		if(r_right)
581 		{
582 			cairo_line_to(cr, draw_pos.right() - r_right,	draw_pos.top() + bdr_top);
583 
584 			double start_angle	= M_PI * 3.0 / 2.0;
585 			double end_angle	= start_angle + M_PI / 2.0  / ((double) bdr_right / (double) bdr_top + 1);
586 
587 			add_path_arc(cr,
588 				draw_pos.right() - r_right,
589 				draw_pos.top() + r_right,
590 				r_right - bdr_top + (bdr_top - bdr_right),
591 				r_right - bdr_top,
592 				start_angle,
593 				end_angle, false);
594 
595 			add_path_arc(cr,
596 				draw_pos.right() - r_right,
597 				draw_pos.top() + r_right,
598 				r_right,
599 				r_right,
600 				end_angle,
601 				start_angle, true);
602 		} else
603 		{
604 			cairo_line_to(cr, draw_pos.right() - bdr_right,	draw_pos.top() + bdr_top);
605 			cairo_line_to(cr, draw_pos.right(),	draw_pos.top());
606 		}
607 
608 		cairo_fill(cr);
609 	}
610 
611 	// draw left border
612 	if(bdr_left)
613 	{
614 		set_color(cr, borders.left.color);
615 
616 		double r_top	= borders.radius.top_left_x;
617 		double r_bottom	= borders.radius.bottom_left_x;
618 
619 		if(r_top)
620 		{
621 			double start_angle	= M_PI;
622 			double end_angle	= start_angle + M_PI / 2.0  / ((double) bdr_top / (double) bdr_left + 1);
623 
624 			add_path_arc(cr,
625 				draw_pos.left() + r_top,
626 				draw_pos.top() + r_top,
627 				r_top - bdr_left,
628 				r_top - bdr_left + (bdr_left - bdr_top),
629 				start_angle,
630 				end_angle, false);
631 
632 			add_path_arc(cr,
633 				draw_pos.left() + r_top,
634 				draw_pos.top() + r_top,
635 				r_top,
636 				r_top,
637 				end_angle,
638 				start_angle, true);
639 		} else
640 		{
641 			cairo_move_to(cr, draw_pos.left() + bdr_left, draw_pos.top() + bdr_top);
642 			cairo_line_to(cr, draw_pos.left(), draw_pos.top());
643 		}
644 
645 		if(r_bottom)
646 		{
647 			cairo_line_to(cr, draw_pos.left(),	draw_pos.bottom() - r_bottom);
648 
649 			double end_angle	= M_PI;
650 			double start_angle	= end_angle - M_PI / 2.0  / ((double) bdr_bottom / (double) bdr_left + 1);
651 
652 			add_path_arc(cr,
653 				draw_pos.left() + r_bottom,
654 				draw_pos.bottom() - r_bottom,
655 				r_bottom,
656 				r_bottom,
657 				end_angle,
658 				start_angle, true);
659 
660 			add_path_arc(cr,
661 				draw_pos.left() + r_bottom,
662 				draw_pos.bottom() - r_bottom,
663 				r_bottom - bdr_left,
664 				r_bottom - bdr_left + (bdr_left - bdr_bottom),
665 				start_angle,
666 				end_angle, false);
667 		} else
668 		{
669 			cairo_line_to(cr, draw_pos.left(),	draw_pos.bottom());
670 			cairo_line_to(cr, draw_pos.left() + bdr_left,	draw_pos.bottom() - bdr_bottom);
671 		}
672 
673 		cairo_fill(cr);
674 	}
675 	cairo_restore(cr);
676 }
677 
transform_text(litehtml::tstring & text,litehtml::text_transform tt)678 void container_linux::transform_text(litehtml::tstring& text, litehtml::text_transform tt)
679 {
680 
681 }
682 
set_clip(const litehtml::position & pos,const litehtml::border_radiuses & bdr_radius,bool valid_x,bool valid_y)683 void container_linux::set_clip( const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius, bool valid_x, bool valid_y )
684 {
685 	litehtml::position clip_pos = pos;
686 	litehtml::position client_pos;
687 	get_client_rect(client_pos);
688 	if(!valid_x)
689 	{
690 		clip_pos.x		= client_pos.x;
691 		clip_pos.width	= client_pos.width;
692 	}
693 	if(!valid_y)
694 	{
695 		clip_pos.y		= client_pos.y;
696 		clip_pos.height	= client_pos.height;
697 	}
698 	m_clips.emplace_back(clip_pos, bdr_radius);
699 }
700 
del_clip()701 void container_linux::del_clip()
702 {
703 	if(!m_clips.empty())
704 	{
705 		m_clips.pop_back();
706 	}
707 }
708 
apply_clip(cairo_t * cr)709 void container_linux::apply_clip( cairo_t* cr )
710 {
711 	for(const auto& clip_box : m_clips)
712 	{
713 		rounded_rectangle(cr, clip_box.box, clip_box.radius);
714 		cairo_clip(cr);
715 	}
716 }
717 
draw_ellipse(cairo_t * cr,int x,int y,int width,int height,const litehtml::web_color & color,int line_width)718 void container_linux::draw_ellipse( cairo_t* cr, int x, int y, int width, int height, const litehtml::web_color& color, int line_width )
719 {
720 	if(!cr) return;
721 	cairo_save(cr);
722 
723 	apply_clip(cr);
724 
725 	cairo_new_path(cr);
726 
727 	cairo_translate (cr, x + width / 2.0, y + height / 2.0);
728 	cairo_scale (cr, width / 2.0, height / 2.0);
729 	cairo_arc (cr, 0, 0, 1, 0, 2 * M_PI);
730 
731 	set_color(cr, color);
732 	cairo_set_line_width(cr, line_width);
733 	cairo_stroke(cr);
734 
735 	cairo_restore(cr);
736 }
737 
fill_ellipse(cairo_t * cr,int x,int y,int width,int height,const litehtml::web_color & color)738 void container_linux::fill_ellipse( cairo_t* cr, int x, int y, int width, int height, const litehtml::web_color& color )
739 {
740 	if(!cr) return;
741 	cairo_save(cr);
742 
743 	apply_clip(cr);
744 
745 	cairo_new_path(cr);
746 
747 	cairo_translate (cr, x + width / 2.0, y + height / 2.0);
748 	cairo_scale (cr, width / 2.0, height / 2.0);
749 	cairo_arc (cr, 0, 0, 1, 0, 2 * M_PI);
750 
751 	set_color(cr, color);
752 	cairo_fill(cr);
753 
754 	cairo_restore(cr);
755 }
756 
clear_images()757 void container_linux::clear_images()
758 {
759 /*	for(images_map::iterator i = m_images.begin(); i != m_images.end(); i++)
760 	{
761 		if(i->second)
762 		{
763 			delete i->second;
764 		}
765 	}
766 	m_images.clear();
767 */
768 }
769 
get_default_font_name() const770 const litehtml::tchar_t* container_linux::get_default_font_name() const
771 {
772 	return "Times New Roman";
773 }
774 
create_element(const litehtml::tchar_t * tag_name,const litehtml::string_map & attributes,const std::shared_ptr<litehtml::document> & doc)775 std::shared_ptr<litehtml::element>	container_linux::create_element(const litehtml::tchar_t *tag_name,
776 																	  const litehtml::string_map &attributes,
777 																	  const std::shared_ptr<litehtml::document> &doc)
778 {
779 	return 0;
780 }
781 
rounded_rectangle(cairo_t * cr,const litehtml::position & pos,const litehtml::border_radiuses & radius)782 void container_linux::rounded_rectangle( cairo_t* cr, const litehtml::position &pos, const litehtml::border_radiuses &radius )
783 {
784 	cairo_new_path(cr);
785 	if(radius.top_left_x)
786 	{
787 		cairo_arc(cr, pos.left() + radius.top_left_x, pos.top() + radius.top_left_x, radius.top_left_x, M_PI, M_PI * 3.0 / 2.0);
788 	} else
789 	{
790 		cairo_move_to(cr, pos.left(), pos.top());
791 	}
792 
793 	cairo_line_to(cr, pos.right() - radius.top_right_x, pos.top());
794 
795 	if(radius.top_right_x)
796 	{
797 		cairo_arc(cr, pos.right() - radius.top_right_x, pos.top() + radius.top_right_x, radius.top_right_x, M_PI * 3.0 / 2.0, 2.0 * M_PI);
798 	}
799 
800 	cairo_line_to(cr, pos.right(), pos.bottom() - radius.bottom_right_x);
801 
802 	if(radius.bottom_right_x)
803 	{
804 		cairo_arc(cr, pos.right() - radius.bottom_right_x, pos.bottom() - radius.bottom_right_x, radius.bottom_right_x, 0, M_PI / 2.0);
805 	}
806 
807 	cairo_line_to(cr, pos.left() - radius.bottom_left_x, pos.bottom());
808 
809 	if(radius.bottom_left_x)
810 	{
811 		cairo_arc(cr, pos.left() + radius.bottom_left_x, pos.bottom() - radius.bottom_left_x, radius.bottom_left_x, M_PI / 2.0, M_PI);
812 	}
813 }
814 
draw_pixbuf(cairo_t * cr,const Glib::RefPtr<Gdk::Pixbuf> & bmp,int x,int y,int cx,int cy)815 void container_linux::draw_pixbuf(cairo_t* cr, const Glib::RefPtr<Gdk::Pixbuf>& bmp, int x,	int y, int cx, int cy)
816 {
817 	cairo_save(cr);
818 
819 	{
820 		Cairo::RefPtr<Cairo::Context> crobj(new Cairo::Context(cr, false));
821 
822 		cairo_matrix_t flib_m;
823 		cairo_matrix_init(&flib_m, 1, 0, 0, -1, 0, 0);
824 
825 		if(cx != bmp->get_width() || cy != bmp->get_height())
826 		{
827 			Glib::RefPtr<Gdk::Pixbuf> new_img = bmp->scale_simple(cx, cy, Gdk::INTERP_BILINEAR);;
828 			Gdk::Cairo::set_source_pixbuf(crobj, new_img, x, y);
829 			crobj->paint();
830 		} else
831 		{
832 			Gdk::Cairo::set_source_pixbuf(crobj, bmp, x, y);
833 			crobj->paint();
834 		}
835 	}
836 
837 	cairo_restore(cr);
838 }
839 
surface_from_pixbuf(const Glib::RefPtr<Gdk::Pixbuf> & bmp)840 cairo_surface_t* container_linux::surface_from_pixbuf(const Glib::RefPtr<Gdk::Pixbuf>& bmp)
841 {
842 	cairo_surface_t* ret = NULL;
843 
844 	if(bmp->get_has_alpha())
845 	{
846 		ret = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bmp->get_width(), bmp->get_height());
847 	} else
848 	{
849 		ret = cairo_image_surface_create(CAIRO_FORMAT_RGB24, bmp->get_width(), bmp->get_height());
850 	}
851 
852 	Cairo::RefPtr<Cairo::Surface> surface(new Cairo::Surface(ret, false));
853 	Cairo::RefPtr<Cairo::Context> ctx = Cairo::Context::create(surface);
854 	Gdk::Cairo::set_source_pixbuf(ctx, bmp, 0.0, 0.0);
855 	ctx->paint();
856 
857 	return ret;
858 }
859 
get_media_features(litehtml::media_features & media) const860 void container_linux::get_media_features(litehtml::media_features& media) const
861 {
862 	litehtml::position client;
863     get_client_rect(client);
864 	media.type			= litehtml::media_type_screen;
865 	media.width			= client.width;
866 	media.height		= client.height;
867 	media.device_width	= Gdk::screen_width();
868 	media.device_height	= Gdk::screen_height();
869 	media.color			= 8;
870 	media.monochrome	= 0;
871 	media.color_index	= 256;
872 	media.resolution	= 96;
873 }
874 
get_language(litehtml::tstring & language,litehtml::tstring & culture) const875 void container_linux::get_language(litehtml::tstring& language, litehtml::tstring& culture) const
876 {
877 	language = _t("en");
878 	culture = _t("");
879 }
880 
link(const std::shared_ptr<litehtml::document> & ptr,const litehtml::element::ptr & el)881 void container_linux::link(const std::shared_ptr<litehtml::document> &ptr, const litehtml::element::ptr& el)
882 {
883 
884 }
885