896 lines
23 KiB
C++
896 lines
23 KiB
C++
#include "container_linux.h"
|
|
#include <cmath>
|
|
|
|
#ifndef M_PI
|
|
# define M_PI 3.14159265358979323846
|
|
#endif
|
|
|
|
container_linux::container_linux()
|
|
{
|
|
m_temp_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 2, 2);
|
|
m_temp_cr = cairo_create(m_temp_surface);
|
|
}
|
|
|
|
container_linux::~container_linux()
|
|
{
|
|
clear_images();
|
|
cairo_surface_destroy(m_temp_surface);
|
|
cairo_destroy(m_temp_cr);
|
|
}
|
|
|
|
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 )
|
|
{
|
|
PangoFontDescription *desc = pango_font_description_from_string (faceName);
|
|
pango_font_description_set_absolute_size(desc, size * PANGO_SCALE);
|
|
if(italic == litehtml::fontStyleItalic )
|
|
{
|
|
pango_font_description_set_style(desc, PANGO_STYLE_ITALIC);
|
|
} else
|
|
{
|
|
pango_font_description_set_style(desc, PANGO_STYLE_NORMAL);
|
|
}
|
|
PangoWeight fnt_weight;
|
|
if(weight >= 0 && weight < 150) fnt_weight = PANGO_WEIGHT_THIN;
|
|
else if(weight >= 150 && weight < 250) fnt_weight = PANGO_WEIGHT_ULTRALIGHT;
|
|
else if(weight >= 250 && weight < 350) fnt_weight = PANGO_WEIGHT_LIGHT;
|
|
else if(weight >= 350 && weight < 450) fnt_weight = PANGO_WEIGHT_NORMAL;
|
|
else if(weight >= 450 && weight < 550) fnt_weight = PANGO_WEIGHT_MEDIUM;
|
|
else if(weight >= 550 && weight < 650) fnt_weight = PANGO_WEIGHT_SEMIBOLD;
|
|
else if(weight >= 650 && weight < 750) fnt_weight = PANGO_WEIGHT_BOLD;
|
|
else if(weight >= 750 && weight < 850) fnt_weight = PANGO_WEIGHT_ULTRABOLD;
|
|
else fnt_weight = PANGO_WEIGHT_HEAVY;
|
|
|
|
pango_font_description_set_weight(desc, fnt_weight);
|
|
|
|
cairo_font* ret = nullptr;
|
|
|
|
if(fm)
|
|
{
|
|
cairo_save(m_temp_cr);
|
|
PangoLayout *layout = pango_cairo_create_layout(m_temp_cr);
|
|
PangoContext *context = pango_layout_get_context(layout);
|
|
PangoLanguage *language = pango_language_get_default();
|
|
pango_layout_set_font_description(layout, desc);
|
|
PangoFontMetrics *metrics = pango_context_get_metrics(context, desc, language);
|
|
|
|
fm->ascent = PANGO_PIXELS((double)pango_font_metrics_get_ascent(metrics));
|
|
fm->descent = PANGO_PIXELS((double)pango_font_metrics_get_descent(metrics));
|
|
fm->height = fm->ascent + fm->descent;
|
|
fm->x_height = fm->height;
|
|
|
|
pango_layout_set_text(layout, "x", 1);
|
|
|
|
int x_width, x_height;
|
|
pango_layout_get_pixel_size(layout, &x_width, &x_height);
|
|
|
|
fm->x_height = x_height;
|
|
|
|
cairo_restore(m_temp_cr);
|
|
|
|
g_object_unref(layout);
|
|
pango_font_metrics_unref(metrics);
|
|
|
|
ret = new cairo_font;
|
|
ret->font = desc;
|
|
ret->size = size;
|
|
ret->strikeout = (decoration & litehtml::font_decoration_linethrough) != 0;
|
|
ret->underline = (decoration & litehtml::font_decoration_underline) != 0;
|
|
ret->ascent = fm->ascent;
|
|
ret->descent = fm->descent;
|
|
|
|
ret->underline_thickness = pango_font_metrics_get_underline_thickness(metrics);
|
|
ret->underline_position = -pango_font_metrics_get_underline_position(metrics);
|
|
pango_quantize_line_geometry(&ret->underline_thickness, &ret->underline_position);
|
|
ret->underline_thickness = PANGO_PIXELS(ret->underline_thickness);
|
|
ret->underline_position = -1;//PANGO_PIXELS(ret->underline_position);
|
|
|
|
ret->strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness(metrics);
|
|
ret->strikethrough_position = pango_font_metrics_get_strikethrough_position(metrics);
|
|
pango_quantize_line_geometry(&ret->strikethrough_thickness, &ret->strikethrough_position);
|
|
ret->strikethrough_thickness = PANGO_PIXELS(ret->strikethrough_thickness);
|
|
ret->strikethrough_position = PANGO_PIXELS(ret->strikethrough_position);
|
|
}
|
|
|
|
return (litehtml::uint_ptr) ret;
|
|
}
|
|
|
|
void container_linux::delete_font( litehtml::uint_ptr hFont )
|
|
{
|
|
auto* fnt = (cairo_font*) hFont;
|
|
if(fnt)
|
|
{
|
|
pango_font_description_free(fnt->font);
|
|
delete fnt;
|
|
}
|
|
}
|
|
|
|
int container_linux::text_width( const litehtml::tchar_t* text, litehtml::uint_ptr hFont )
|
|
{
|
|
auto* fnt = (cairo_font*) hFont;
|
|
|
|
cairo_save(m_temp_cr);
|
|
|
|
PangoLayout *layout = pango_cairo_create_layout(m_temp_cr);
|
|
pango_layout_set_font_description(layout, fnt->font);
|
|
|
|
pango_layout_set_text(layout, text, -1);
|
|
pango_cairo_update_layout (m_temp_cr, layout);
|
|
|
|
int x_width, x_height;
|
|
pango_layout_get_pixel_size(layout, &x_width, &x_height);
|
|
|
|
cairo_restore(m_temp_cr);
|
|
|
|
return (int) x_width;
|
|
}
|
|
|
|
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 )
|
|
{
|
|
auto* fnt = (cairo_font*) hFont;
|
|
auto* cr = (cairo_t*) hdc;
|
|
cairo_save(cr);
|
|
|
|
apply_clip(cr);
|
|
|
|
set_color(cr, color);
|
|
|
|
PangoLayout *layout = pango_cairo_create_layout(cr);
|
|
pango_layout_set_font_description (layout, fnt->font);
|
|
pango_layout_set_text (layout, text, -1);
|
|
|
|
int baseline = PANGO_PIXELS(pango_layout_get_baseline(layout));
|
|
|
|
PangoRectangle ink_rect, logical_rect;
|
|
pango_layout_get_pixel_extents(layout, &ink_rect, &logical_rect);
|
|
|
|
int text_baseline = pos.height - fnt->descent;
|
|
|
|
int x = pos.left() + logical_rect.x;
|
|
int y = pos.top() + logical_rect.y + text_baseline - baseline;
|
|
|
|
cairo_move_to(cr, x, y);
|
|
pango_cairo_update_layout (cr, layout);
|
|
pango_cairo_show_layout (cr, layout);
|
|
|
|
int tw = 0;
|
|
|
|
if(fnt->underline || fnt->strikeout)
|
|
{
|
|
tw = text_width(text, hFont);
|
|
}
|
|
|
|
if(fnt->underline)
|
|
{
|
|
cairo_set_line_width(cr, fnt->underline_thickness);
|
|
cairo_move_to(cr, x, pos.top() + text_baseline - fnt->underline_position + 0.5);
|
|
cairo_line_to(cr, x + tw, pos.top() + text_baseline - fnt->underline_position + 0.5);
|
|
cairo_stroke(cr);
|
|
}
|
|
if(fnt->strikeout)
|
|
{
|
|
cairo_set_line_width(cr, fnt->strikethrough_thickness);
|
|
cairo_move_to(cr, x, pos.top() + text_baseline - fnt->strikethrough_position - 0.5);
|
|
cairo_line_to(cr, x + tw, pos.top() + text_baseline - fnt->strikethrough_position - 0.5);
|
|
cairo_stroke(cr);
|
|
}
|
|
|
|
cairo_restore(cr);
|
|
|
|
g_object_unref(layout);
|
|
}
|
|
|
|
int container_linux::pt_to_px( int pt ) const
|
|
{
|
|
GdkScreen* screen = gdk_screen_get_default();
|
|
double dpi = gdk_screen_get_resolution(screen);
|
|
|
|
return (int) ((double) pt * dpi / 72.0);
|
|
}
|
|
|
|
int container_linux::get_default_font_size() const
|
|
{
|
|
return pt_to_px(12);
|
|
}
|
|
|
|
void container_linux::draw_list_marker( litehtml::uint_ptr hdc, const litehtml::list_marker& marker )
|
|
{
|
|
if(!marker.image.empty())
|
|
{
|
|
/*litehtml::tstring url;
|
|
make_url(marker.image.c_str(), marker.baseurl, url);
|
|
|
|
lock_images_cache();
|
|
images_map::iterator img_i = m_images.find(url.c_str());
|
|
if(img_i != m_images.end())
|
|
{
|
|
if(img_i->second)
|
|
{
|
|
draw_txdib((cairo_t*) hdc, img_i->second, marker.pos.x, marker.pos.y, marker.pos.width, marker.pos.height);
|
|
}
|
|
}
|
|
unlock_images_cache();*/
|
|
} else
|
|
{
|
|
switch(marker.marker_type)
|
|
{
|
|
case litehtml::list_style_type_circle:
|
|
{
|
|
draw_ellipse((cairo_t*) hdc, marker.pos.x, marker.pos.y, marker.pos.width, marker.pos.height, marker.color, 1);
|
|
}
|
|
break;
|
|
case litehtml::list_style_type_disc:
|
|
{
|
|
fill_ellipse((cairo_t*) hdc, marker.pos.x, marker.pos.y, marker.pos.width, marker.pos.height, marker.color);
|
|
}
|
|
break;
|
|
case litehtml::list_style_type_square:
|
|
if(hdc)
|
|
{
|
|
auto* cr = (cairo_t*) hdc;
|
|
cairo_save(cr);
|
|
|
|
cairo_new_path(cr);
|
|
cairo_rectangle(cr, marker.pos.x, marker.pos.y, marker.pos.width, marker.pos.height);
|
|
|
|
set_color(cr, marker.color);
|
|
cairo_fill(cr);
|
|
cairo_restore(cr);
|
|
}
|
|
break;
|
|
default:
|
|
/*do nothing*/
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void container_linux::load_image( const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, bool redraw_on_ready )
|
|
{
|
|
litehtml::tstring url;
|
|
make_url(src, baseurl, url);
|
|
if(m_images.find(url) == m_images.end())
|
|
{
|
|
try
|
|
{
|
|
Glib::RefPtr<Gdk::Pixbuf> img = get_image(url.c_str(), true);
|
|
if(img)
|
|
{
|
|
m_images[url.c_str()] = img;
|
|
}
|
|
} catch(...)
|
|
{
|
|
m_images[url.c_str()] = Glib::RefPtr<Gdk::Pixbuf>(nullptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
void container_linux::get_image_size( const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, litehtml::size& sz )
|
|
{
|
|
litehtml::tstring url;
|
|
make_url(src, baseurl, url);
|
|
|
|
auto img = m_images.find(url);
|
|
if(img != m_images.end())
|
|
{
|
|
if(img->second)
|
|
{
|
|
sz.width = img->second->get_width();
|
|
sz.height = img->second->get_height();
|
|
} else
|
|
{
|
|
sz.width = 0;
|
|
sz.height = 0;
|
|
}
|
|
} else
|
|
{
|
|
sz.width = 0;
|
|
sz.height = 0;
|
|
}
|
|
}
|
|
|
|
void container_linux::draw_background( litehtml::uint_ptr hdc, const litehtml::background_paint& bg )
|
|
{
|
|
auto* cr = (cairo_t*) hdc;
|
|
cairo_save(cr);
|
|
apply_clip(cr);
|
|
|
|
rounded_rectangle(cr, bg.border_box, bg.border_radius);
|
|
cairo_clip(cr);
|
|
|
|
cairo_rectangle(cr, bg.clip_box.x, bg.clip_box.y, bg.clip_box.width, bg.clip_box.height);
|
|
cairo_clip(cr);
|
|
|
|
if(bg.color.alpha)
|
|
{
|
|
set_color(cr, bg.color);
|
|
cairo_paint(cr);
|
|
}
|
|
|
|
litehtml::tstring url;
|
|
make_url(bg.image.c_str(), bg.baseurl.c_str(), url);
|
|
|
|
//lock_images_cache();
|
|
auto img_i = m_images.find(url);
|
|
if(img_i != m_images.end() && img_i->second)
|
|
{
|
|
Glib::RefPtr<Gdk::Pixbuf> bgbmp = img_i->second;
|
|
|
|
Glib::RefPtr<Gdk::Pixbuf> new_img;
|
|
if(bg.image_size.width != bgbmp->get_width() || bg.image_size.height != bgbmp->get_height())
|
|
{
|
|
new_img = bgbmp->scale_simple(bg.image_size.width, bg.image_size.height, Gdk::INTERP_BILINEAR);
|
|
bgbmp = new_img;
|
|
}
|
|
|
|
cairo_surface_t* img = surface_from_pixbuf(bgbmp);
|
|
cairo_pattern_t *pattern = cairo_pattern_create_for_surface(img);
|
|
cairo_matrix_t flib_m;
|
|
cairo_matrix_init_identity(&flib_m);
|
|
cairo_matrix_translate(&flib_m, -bg.position_x, -bg.position_y);
|
|
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
|
cairo_pattern_set_matrix (pattern, &flib_m);
|
|
|
|
switch(bg.repeat)
|
|
{
|
|
case litehtml::background_repeat_no_repeat:
|
|
draw_pixbuf(cr, bgbmp, bg.position_x, bg.position_y, bgbmp->get_width(), bgbmp->get_height());
|
|
break;
|
|
|
|
case litehtml::background_repeat_repeat_x:
|
|
cairo_set_source(cr, pattern);
|
|
cairo_rectangle(cr, bg.clip_box.left(), bg.position_y, bg.clip_box.width, bgbmp->get_height());
|
|
cairo_fill(cr);
|
|
break;
|
|
|
|
case litehtml::background_repeat_repeat_y:
|
|
cairo_set_source(cr, pattern);
|
|
cairo_rectangle(cr, bg.position_x, bg.clip_box.top(), bgbmp->get_width(), bg.clip_box.height);
|
|
cairo_fill(cr);
|
|
break;
|
|
|
|
case litehtml::background_repeat_repeat:
|
|
cairo_set_source(cr, pattern);
|
|
cairo_rectangle(cr, bg.clip_box.left(), bg.clip_box.top(), bg.clip_box.width, bg.clip_box.height);
|
|
cairo_fill(cr);
|
|
break;
|
|
}
|
|
|
|
cairo_pattern_destroy(pattern);
|
|
cairo_surface_destroy(img);
|
|
|
|
}
|
|
// unlock_images_cache();
|
|
cairo_restore(cr);
|
|
}
|
|
|
|
void container_linux::make_url(const litehtml::tchar_t* url, const litehtml::tchar_t* basepath, litehtml::tstring& out)
|
|
{
|
|
out = url;
|
|
}
|
|
|
|
void container_linux::add_path_arc(cairo_t* cr, double x, double y, double rx, double ry, double a1, double a2, bool neg)
|
|
{
|
|
if(rx > 0 && ry > 0)
|
|
{
|
|
|
|
cairo_save(cr);
|
|
|
|
cairo_translate(cr, x, y);
|
|
cairo_scale(cr, 1, ry / rx);
|
|
cairo_translate(cr, -x, -y);
|
|
|
|
if(neg)
|
|
{
|
|
cairo_arc_negative(cr, x, y, rx, a1, a2);
|
|
} else
|
|
{
|
|
cairo_arc(cr, x, y, rx, a1, a2);
|
|
}
|
|
|
|
cairo_restore(cr);
|
|
} else
|
|
{
|
|
cairo_move_to(cr, x, y);
|
|
}
|
|
}
|
|
|
|
void container_linux::draw_borders(litehtml::uint_ptr hdc, const litehtml::borders& borders, const litehtml::position& draw_pos, bool root)
|
|
{
|
|
auto* cr = (cairo_t*) hdc;
|
|
cairo_save(cr);
|
|
apply_clip(cr);
|
|
|
|
cairo_new_path(cr);
|
|
|
|
int bdr_top = 0;
|
|
int bdr_bottom = 0;
|
|
int bdr_left = 0;
|
|
int bdr_right = 0;
|
|
|
|
if(borders.top.width != 0 && borders.top.style > litehtml::border_style_hidden)
|
|
{
|
|
bdr_top = (int) borders.top.width;
|
|
}
|
|
if(borders.bottom.width != 0 && borders.bottom.style > litehtml::border_style_hidden)
|
|
{
|
|
bdr_bottom = (int) borders.bottom.width;
|
|
}
|
|
if(borders.left.width != 0 && borders.left.style > litehtml::border_style_hidden)
|
|
{
|
|
bdr_left = (int) borders.left.width;
|
|
}
|
|
if(borders.right.width != 0 && borders.right.style > litehtml::border_style_hidden)
|
|
{
|
|
bdr_right = (int) borders.right.width;
|
|
}
|
|
|
|
// draw right border
|
|
if(bdr_right)
|
|
{
|
|
set_color(cr, borders.right.color);
|
|
|
|
double r_top = borders.radius.top_right_x;
|
|
double r_bottom = borders.radius.bottom_right_x;
|
|
|
|
if(r_top)
|
|
{
|
|
double end_angle = 2 * M_PI;
|
|
double start_angle = end_angle - M_PI / 2.0 / ((double) bdr_top / (double) bdr_right + 1);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.right() - r_top,
|
|
draw_pos.top() + r_top,
|
|
r_top - bdr_right,
|
|
r_top - bdr_right + (bdr_right - bdr_top),
|
|
end_angle,
|
|
start_angle, true);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.right() - r_top,
|
|
draw_pos.top() + r_top,
|
|
r_top,
|
|
r_top,
|
|
start_angle,
|
|
end_angle, false);
|
|
} else
|
|
{
|
|
cairo_move_to(cr, draw_pos.right() - bdr_right, draw_pos.top() + bdr_top);
|
|
cairo_line_to(cr, draw_pos.right(), draw_pos.top());
|
|
}
|
|
|
|
if(r_bottom)
|
|
{
|
|
cairo_line_to(cr, draw_pos.right(), draw_pos.bottom() - r_bottom);
|
|
|
|
double start_angle = 0;
|
|
double end_angle = start_angle + M_PI / 2.0 / ((double) bdr_bottom / (double) bdr_right + 1);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.right() - r_bottom,
|
|
draw_pos.bottom() - r_bottom,
|
|
r_bottom,
|
|
r_bottom,
|
|
start_angle,
|
|
end_angle, false);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.right() - r_bottom,
|
|
draw_pos.bottom() - r_bottom,
|
|
r_bottom - bdr_right,
|
|
r_bottom - bdr_right + (bdr_right - bdr_bottom),
|
|
end_angle,
|
|
start_angle, true);
|
|
} else
|
|
{
|
|
cairo_line_to(cr, draw_pos.right(), draw_pos.bottom());
|
|
cairo_line_to(cr, draw_pos.right() - bdr_right, draw_pos.bottom() - bdr_bottom);
|
|
}
|
|
|
|
cairo_fill(cr);
|
|
}
|
|
|
|
// draw bottom border
|
|
if(bdr_bottom)
|
|
{
|
|
set_color(cr, borders.bottom.color);
|
|
|
|
double r_left = borders.radius.bottom_left_x;
|
|
double r_right = borders.radius.bottom_right_x;
|
|
|
|
if(r_left)
|
|
{
|
|
double start_angle = M_PI / 2.0;
|
|
double end_angle = start_angle + M_PI / 2.0 / ((double) bdr_left / (double) bdr_bottom + 1);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.left() + r_left,
|
|
draw_pos.bottom() - r_left,
|
|
r_left - bdr_bottom + (bdr_bottom - bdr_left),
|
|
r_left - bdr_bottom,
|
|
start_angle,
|
|
end_angle, false);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.left() + r_left,
|
|
draw_pos.bottom() - r_left,
|
|
r_left,
|
|
r_left,
|
|
end_angle,
|
|
start_angle, true);
|
|
} else
|
|
{
|
|
cairo_move_to(cr, draw_pos.left(), draw_pos.bottom());
|
|
cairo_line_to(cr, draw_pos.left() + bdr_left, draw_pos.bottom() - bdr_bottom);
|
|
}
|
|
|
|
if(r_right)
|
|
{
|
|
cairo_line_to(cr, draw_pos.right() - r_right, draw_pos.bottom());
|
|
|
|
double end_angle = M_PI / 2.0;
|
|
double start_angle = end_angle - M_PI / 2.0 / ((double) bdr_right / (double) bdr_bottom + 1);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.right() - r_right,
|
|
draw_pos.bottom() - r_right,
|
|
r_right,
|
|
r_right,
|
|
end_angle,
|
|
start_angle, true);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.right() - r_right,
|
|
draw_pos.bottom() - r_right,
|
|
r_right - bdr_bottom + (bdr_bottom - bdr_right),
|
|
r_right - bdr_bottom,
|
|
start_angle,
|
|
end_angle, false);
|
|
} else
|
|
{
|
|
cairo_line_to(cr, draw_pos.right() - bdr_right, draw_pos.bottom() - bdr_bottom);
|
|
cairo_line_to(cr, draw_pos.right(), draw_pos.bottom());
|
|
}
|
|
|
|
cairo_fill(cr);
|
|
}
|
|
|
|
// draw top border
|
|
if(bdr_top)
|
|
{
|
|
set_color(cr, borders.top.color);
|
|
|
|
double r_left = borders.radius.top_left_x;
|
|
double r_right = borders.radius.top_right_x;
|
|
|
|
if(r_left)
|
|
{
|
|
double end_angle = M_PI * 3.0 / 2.0;
|
|
double start_angle = end_angle - M_PI / 2.0 / ((double) bdr_left / (double) bdr_top + 1);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.left() + r_left,
|
|
draw_pos.top() + r_left,
|
|
r_left,
|
|
r_left,
|
|
end_angle,
|
|
start_angle, true);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.left() + r_left,
|
|
draw_pos.top() + r_left,
|
|
r_left - bdr_top + (bdr_top - bdr_left),
|
|
r_left - bdr_top,
|
|
start_angle,
|
|
end_angle, false);
|
|
} else
|
|
{
|
|
cairo_move_to(cr, draw_pos.left(), draw_pos.top());
|
|
cairo_line_to(cr, draw_pos.left() + bdr_left, draw_pos.top() + bdr_top);
|
|
}
|
|
|
|
if(r_right)
|
|
{
|
|
cairo_line_to(cr, draw_pos.right() - r_right, draw_pos.top() + bdr_top);
|
|
|
|
double start_angle = M_PI * 3.0 / 2.0;
|
|
double end_angle = start_angle + M_PI / 2.0 / ((double) bdr_right / (double) bdr_top + 1);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.right() - r_right,
|
|
draw_pos.top() + r_right,
|
|
r_right - bdr_top + (bdr_top - bdr_right),
|
|
r_right - bdr_top,
|
|
start_angle,
|
|
end_angle, false);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.right() - r_right,
|
|
draw_pos.top() + r_right,
|
|
r_right,
|
|
r_right,
|
|
end_angle,
|
|
start_angle, true);
|
|
} else
|
|
{
|
|
cairo_line_to(cr, draw_pos.right() - bdr_right, draw_pos.top() + bdr_top);
|
|
cairo_line_to(cr, draw_pos.right(), draw_pos.top());
|
|
}
|
|
|
|
cairo_fill(cr);
|
|
}
|
|
|
|
// draw left border
|
|
if(bdr_left)
|
|
{
|
|
set_color(cr, borders.left.color);
|
|
|
|
double r_top = borders.radius.top_left_x;
|
|
double r_bottom = borders.radius.bottom_left_x;
|
|
|
|
if(r_top)
|
|
{
|
|
double start_angle = M_PI;
|
|
double end_angle = start_angle + M_PI / 2.0 / ((double) bdr_top / (double) bdr_left + 1);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.left() + r_top,
|
|
draw_pos.top() + r_top,
|
|
r_top - bdr_left,
|
|
r_top - bdr_left + (bdr_left - bdr_top),
|
|
start_angle,
|
|
end_angle, false);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.left() + r_top,
|
|
draw_pos.top() + r_top,
|
|
r_top,
|
|
r_top,
|
|
end_angle,
|
|
start_angle, true);
|
|
} else
|
|
{
|
|
cairo_move_to(cr, draw_pos.left() + bdr_left, draw_pos.top() + bdr_top);
|
|
cairo_line_to(cr, draw_pos.left(), draw_pos.top());
|
|
}
|
|
|
|
if(r_bottom)
|
|
{
|
|
cairo_line_to(cr, draw_pos.left(), draw_pos.bottom() - r_bottom);
|
|
|
|
double end_angle = M_PI;
|
|
double start_angle = end_angle - M_PI / 2.0 / ((double) bdr_bottom / (double) bdr_left + 1);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.left() + r_bottom,
|
|
draw_pos.bottom() - r_bottom,
|
|
r_bottom,
|
|
r_bottom,
|
|
end_angle,
|
|
start_angle, true);
|
|
|
|
add_path_arc(cr,
|
|
draw_pos.left() + r_bottom,
|
|
draw_pos.bottom() - r_bottom,
|
|
r_bottom - bdr_left,
|
|
r_bottom - bdr_left + (bdr_left - bdr_bottom),
|
|
start_angle,
|
|
end_angle, false);
|
|
} else
|
|
{
|
|
cairo_line_to(cr, draw_pos.left(), draw_pos.bottom());
|
|
cairo_line_to(cr, draw_pos.left() + bdr_left, draw_pos.bottom() - bdr_bottom);
|
|
}
|
|
|
|
cairo_fill(cr);
|
|
}
|
|
cairo_restore(cr);
|
|
}
|
|
|
|
void container_linux::transform_text(litehtml::tstring& text, litehtml::text_transform tt)
|
|
{
|
|
|
|
}
|
|
|
|
void container_linux::set_clip( const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius, bool valid_x, bool valid_y )
|
|
{
|
|
litehtml::position clip_pos = pos;
|
|
litehtml::position client_pos;
|
|
get_client_rect(client_pos);
|
|
if(!valid_x)
|
|
{
|
|
clip_pos.x = client_pos.x;
|
|
clip_pos.width = client_pos.width;
|
|
}
|
|
if(!valid_y)
|
|
{
|
|
clip_pos.y = client_pos.y;
|
|
clip_pos.height = client_pos.height;
|
|
}
|
|
m_clips.emplace_back(clip_pos, bdr_radius);
|
|
}
|
|
|
|
void container_linux::del_clip()
|
|
{
|
|
if(!m_clips.empty())
|
|
{
|
|
m_clips.pop_back();
|
|
}
|
|
}
|
|
|
|
void container_linux::apply_clip( cairo_t* cr )
|
|
{
|
|
for(const auto& clip_box : m_clips)
|
|
{
|
|
rounded_rectangle(cr, clip_box.box, clip_box.radius);
|
|
cairo_clip(cr);
|
|
}
|
|
}
|
|
|
|
void container_linux::draw_ellipse( cairo_t* cr, int x, int y, int width, int height, const litehtml::web_color& color, int line_width )
|
|
{
|
|
if(!cr || !width || !height) return;
|
|
cairo_save(cr);
|
|
|
|
apply_clip(cr);
|
|
|
|
cairo_new_path(cr);
|
|
|
|
cairo_translate (cr, x + width / 2.0, y + height / 2.0);
|
|
cairo_scale (cr, width / 2.0, height / 2.0);
|
|
cairo_arc (cr, 0, 0, 1, 0, 2 * M_PI);
|
|
|
|
set_color(cr, color);
|
|
cairo_set_line_width(cr, line_width);
|
|
cairo_stroke(cr);
|
|
|
|
cairo_restore(cr);
|
|
}
|
|
|
|
void container_linux::fill_ellipse( cairo_t* cr, int x, int y, int width, int height, const litehtml::web_color& color )
|
|
{
|
|
if(!cr || !width || !height) return;
|
|
cairo_save(cr);
|
|
|
|
apply_clip(cr);
|
|
|
|
cairo_new_path(cr);
|
|
|
|
cairo_translate (cr, x + width / 2.0, y + height / 2.0);
|
|
cairo_scale (cr, width / 2.0, height / 2.0);
|
|
cairo_arc (cr, 0, 0, 1, 0, 2 * M_PI);
|
|
|
|
set_color(cr, color);
|
|
cairo_fill(cr);
|
|
|
|
cairo_restore(cr);
|
|
}
|
|
|
|
void container_linux::clear_images()
|
|
{
|
|
/* for(images_map::iterator i = m_images.begin(); i != m_images.end(); i++)
|
|
{
|
|
if(i->second)
|
|
{
|
|
delete i->second;
|
|
}
|
|
}
|
|
m_images.clear();
|
|
*/
|
|
}
|
|
|
|
const litehtml::tchar_t* container_linux::get_default_font_name() const
|
|
{
|
|
return "Times New Roman";
|
|
}
|
|
|
|
std::shared_ptr<litehtml::element> container_linux::create_element(const litehtml::tchar_t *tag_name,
|
|
const litehtml::string_map &attributes,
|
|
const std::shared_ptr<litehtml::document> &doc)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
void container_linux::rounded_rectangle( cairo_t* cr, const litehtml::position &pos, const litehtml::border_radiuses &radius )
|
|
{
|
|
cairo_new_path(cr);
|
|
if(radius.top_left_x)
|
|
{
|
|
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);
|
|
} else
|
|
{
|
|
cairo_move_to(cr, pos.left(), pos.top());
|
|
}
|
|
|
|
cairo_line_to(cr, pos.right() - radius.top_right_x, pos.top());
|
|
|
|
if(radius.top_right_x)
|
|
{
|
|
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);
|
|
}
|
|
|
|
cairo_line_to(cr, pos.right(), pos.bottom() - radius.bottom_right_x);
|
|
|
|
if(radius.bottom_right_x)
|
|
{
|
|
cairo_arc(cr, pos.right() - radius.bottom_right_x, pos.bottom() - radius.bottom_right_x, radius.bottom_right_x, 0, M_PI / 2.0);
|
|
}
|
|
|
|
cairo_line_to(cr, pos.left() - radius.bottom_left_x, pos.bottom());
|
|
|
|
if(radius.bottom_left_x)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
void container_linux::draw_pixbuf(cairo_t* cr, const Glib::RefPtr<Gdk::Pixbuf>& bmp, int x, int y, int cx, int cy)
|
|
{
|
|
cairo_save(cr);
|
|
|
|
{
|
|
Cairo::RefPtr<Cairo::Context> crobj(new Cairo::Context(cr, false));
|
|
|
|
cairo_matrix_t flib_m;
|
|
cairo_matrix_init(&flib_m, 1, 0, 0, -1, 0, 0);
|
|
|
|
if(cx != bmp->get_width() || cy != bmp->get_height())
|
|
{
|
|
Glib::RefPtr<Gdk::Pixbuf> new_img = bmp->scale_simple(cx, cy, Gdk::INTERP_BILINEAR);
|
|
Gdk::Cairo::set_source_pixbuf(crobj, new_img, x, y);
|
|
crobj->paint();
|
|
} else
|
|
{
|
|
Gdk::Cairo::set_source_pixbuf(crobj, bmp, x, y);
|
|
crobj->paint();
|
|
}
|
|
}
|
|
|
|
cairo_restore(cr);
|
|
}
|
|
|
|
cairo_surface_t* container_linux::surface_from_pixbuf(const Glib::RefPtr<Gdk::Pixbuf>& bmp)
|
|
{
|
|
cairo_surface_t* ret;
|
|
|
|
if(bmp->get_has_alpha())
|
|
{
|
|
ret = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bmp->get_width(), bmp->get_height());
|
|
} else
|
|
{
|
|
ret = cairo_image_surface_create(CAIRO_FORMAT_RGB24, bmp->get_width(), bmp->get_height());
|
|
}
|
|
|
|
Cairo::RefPtr<Cairo::Surface> surface(new Cairo::Surface(ret, false));
|
|
Cairo::RefPtr<Cairo::Context> ctx = Cairo::Context::create(surface);
|
|
Gdk::Cairo::set_source_pixbuf(ctx, bmp, 0.0, 0.0);
|
|
ctx->paint();
|
|
|
|
return ret;
|
|
}
|
|
|
|
void container_linux::get_media_features(litehtml::media_features& media) const
|
|
{
|
|
litehtml::position client;
|
|
get_client_rect(client);
|
|
media.type = litehtml::media_type_screen;
|
|
media.width = client.width;
|
|
media.height = client.height;
|
|
media.device_width = Gdk::screen_width();
|
|
media.device_height = Gdk::screen_height();
|
|
media.color = 8;
|
|
media.monochrome = 0;
|
|
media.color_index = 256;
|
|
media.resolution = 96;
|
|
}
|
|
|
|
void container_linux::get_language(litehtml::tstring& language, litehtml::tstring& culture) const
|
|
{
|
|
language = _t("en");
|
|
culture = _t("");
|
|
}
|
|
|
|
void container_linux::link(const std::shared_ptr<litehtml::document> &ptr, const litehtml::element::ptr& el)
|
|
{
|
|
|
|
}
|