Skip to content

Commit 70abcfd

Browse files
committed
fixed: elements with 'position:fixed' have issue with draw
* document_container::get_client_rect was renamed to get_viewport. * updated draw_buffer class to handle fixed elements on scroll
1 parent 1274232 commit 70abcfd

File tree

12 files changed

+134
-102
lines changed

12 files changed

+134
-102
lines changed

.clang-format

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ BraceWrapping:
3232
NamespaceIndentation: All
3333
AlignConsecutiveDeclarations:
3434
Enabled: true
35-
AcrossEmptyLines: true
35+
AcrossEmptyLines: false
3636
AcrossComments: false
3737
AlignConsecutiveAssignments:
3838
Enabled: true
@@ -54,7 +54,7 @@ InsertNewlineAtEOF: true
5454
BreakConstructorInitializers: AfterColon
5555
PackConstructorInitializers: Never
5656
AllowShortLambdasOnASingleLine: true
57-
AllowShortIfStatementsOnASingleLine: WithoutElse
57+
AllowShortIfStatementsOnASingleLine: Never
5858
AllowShortFunctionsOnASingleLine: Inline
5959
AlignArrayOfStructures: Left
6060
AllowShortBlocksOnASingleLine: true

containers/cairo/container_cairo.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -647,11 +647,11 @@ void container_cairo::draw_pixbuf(cairo_t* cr, cairo_surface_t* bmp, int x, int
647647

648648
void container_cairo::get_media_features(litehtml::media_features& media) const
649649
{
650-
litehtml::position client;
651-
get_client_rect(client);
650+
litehtml::position viewport;
651+
get_viewport(viewport);
652652
media.type = litehtml::media_type_screen;
653-
media.width = client.width;
654-
media.height = client.height;
653+
media.width = viewport.width;
654+
media.height = viewport.height;
655655
media.device_width = get_screen_width();
656656
media.device_height = get_screen_height();
657657
media.color = 8;

containers/cairo/render2png.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,12 @@ namespace html2png
156156
text = ss.str();
157157
}
158158

159-
void get_client_rect(litehtml::position &client) const override
159+
void get_viewport(litehtml::position& viewport) const override
160160
{
161-
client.width = m_converter->get_screen_width();
162-
client.height = m_converter->get_screen_height();
163-
client.x = 0;
164-
client.y = 0;
161+
viewport.width = m_converter->get_screen_width();
162+
viewport.height = m_converter->get_screen_height();
163+
viewport.x = 0;
164+
viewport.y = 0;
165165
}
166166

167167
const char* get_default_font_name() const override { return m_converter->get_default_font(); }

include/litehtml/document_container.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ namespace litehtml
6161
virtual void import_css(litehtml::string& text, const litehtml::string& url, litehtml::string& baseurl) = 0;
6262
virtual void set_clip(const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius) = 0;
6363
virtual void del_clip() = 0;
64-
virtual void get_client_rect(litehtml::position& client) const = 0;
64+
virtual void get_viewport(litehtml::position& viewport) const = 0;
6565
virtual litehtml::element::ptr create_element( const char* tag_name,
6666
const litehtml::string_map& attributes,
6767
const std::shared_ptr<litehtml::document>& doc) = 0;

src/document.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,12 +490,12 @@ int document::render( int max_width, render_type rt )
490490
int ret = 0;
491491
if(m_root && m_root_render)
492492
{
493-
position client_rc;
494-
m_container->get_client_rect(client_rc);
493+
position viewport;
494+
m_container->get_viewport(viewport);
495495
containing_block_context cb_context;
496496
cb_context.width = max_width;
497497
cb_context.width.type = containing_block_context::cbc_value_type_absolute;
498-
cb_context.height = client_rc.height;
498+
cb_context.height = viewport.height;
499499
cb_context.height.type = containing_block_context::cbc_value_type_absolute;
500500

501501
if(rt == render_fixed_only)

src/render_item.cpp

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "document.h"
33
#include <typeinfo>
44
#include "document_container.h"
5+
#include "types.h"
56

67
litehtml::render_item::render_item(std::shared_ptr<element> _src_el) :
78
m_element(std::move(_src_el)),
@@ -242,8 +243,8 @@ bool litehtml::render_item::fetch_positioned()
242243

243244
void litehtml::render_item::render_positioned(render_type rt)
244245
{
245-
position wnd_position;
246-
src_el()->get_document()->container()->get_client_rect(wnd_position);
246+
position view_port;
247+
src_el()->get_document()->container()->get_viewport(view_port);
247248

248249
element_position el_position;
249250
bool process;
@@ -274,8 +275,8 @@ void litehtml::render_item::render_positioned(render_type rt)
274275
containing_block_context containing_block_size;
275276
if(el_position == element_position_fixed || (is_root() && !src_el()->is_positioned()))
276277
{
277-
containing_block_size.height = wnd_position.height;
278-
containing_block_size.width = wnd_position.width;
278+
containing_block_size.height = view_port.height;
279+
containing_block_size.width = view_port.width;
279280
} else
280281
{
281282
containing_block_size.height = m_pos.height + m_padding.height();
@@ -647,8 +648,8 @@ void litehtml::render_item::render_positioned(render_type rt)
647648

648649
if(el_position == element_position_fixed)
649650
{
650-
position fixed_pos;
651-
el->get_redraw_box(fixed_pos);
651+
position fixed_pos = el->pos();
652+
el->get_redraw_box(fixed_pos);
652653
src_el()->get_document()->add_fixed_box(fixed_pos);
653654
}
654655
}
@@ -831,12 +832,10 @@ void litehtml::render_item::draw_children(uint_ptr hdc, int x, int y, const posi
831832
if (el->src_el()->is_positioned() && el->src_el()->css().get_z_index() == zindex)
832833
{
833834
if (el->src_el()->css().get_position() == element_position_fixed)
834-
{
835-
position browser_wnd;
836-
doc->container()->get_client_rect(browser_wnd);
837-
838-
el->src_el()->draw(hdc, browser_wnd.x, browser_wnd.y, clip, el);
839-
el->draw_stacking_context(hdc, browser_wnd.x, browser_wnd.y, clip, true);
835+
{
836+
// Fixed elements position is always relative to the (0,0)
837+
el->src_el()->draw(hdc, 0, 0, clip, el);
838+
el->draw_stacking_context(hdc, 0, 0, clip, true);
840839
}
841840
else
842841
{
@@ -1128,17 +1127,39 @@ void litehtml::render_item::get_rendering_boxes( position::vector& redraw_boxes)
11281127

11291128
if(src_el()->css().get_position() != element_position_fixed)
11301129
{
1131-
auto cur_el = parent();
1130+
auto cur_el = parent();
1131+
int add_x = 0;
1132+
int add_y = 0;
1133+
11321134
while(cur_el)
1133-
{
1134-
for(auto& box : redraw_boxes)
1135-
{
1136-
box.x += cur_el->m_pos.x;
1137-
box.y += cur_el->m_pos.y;
1138-
}
1135+
{
1136+
if(cur_el->css().get_position() == element_position_fixed)
1137+
{
1138+
position view_port;
1139+
src_el()->get_document()->container()->get_viewport(view_port);
1140+
add_x += cur_el->m_pos.x + view_port.left();
1141+
add_y += cur_el->m_pos.y + view_port.top();
1142+
break;
1143+
}
1144+
add_x += cur_el->m_pos.x;
1145+
add_y += cur_el->m_pos.y;
11391146
cur_el = cur_el->parent();
11401147
}
1141-
}
1148+
for(auto& box : redraw_boxes)
1149+
{
1150+
box.x += add_x;
1151+
box.y += add_y;
1152+
}
1153+
} else
1154+
{
1155+
position view_port;
1156+
src_el()->get_document()->container()->get_viewport(view_port);
1157+
for(auto& box : redraw_boxes)
1158+
{
1159+
box.x += view_port.left();
1160+
box.y += view_port.top();
1161+
}
1162+
}
11421163
}
11431164

11441165
void litehtml::render_item::dump(litehtml::dumper& cout)

support/gtkmm4/html_widget.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,12 @@ void html_widget::snapshot_vfunc(const Glib::RefPtr<Gtk::Snapshot>& snapshot)
129129
snapshot_child(*m_hscrollbar, snapshot);
130130
}
131131

132-
void html_widget::get_client_rect(litehtml::position& client) const
132+
void html_widget::get_viewport(litehtml::position& viewport) const
133133
{
134-
client.x = 0;
135-
client.y = 0;
136-
client.width = m_draw_buffer.get_width();
137-
client.height = m_draw_buffer.get_height();
134+
viewport.x = m_draw_buffer.get_left();
135+
viewport.y = m_draw_buffer.get_top();
136+
viewport.width = m_draw_buffer.get_width();
137+
viewport.height = m_draw_buffer.get_height();
138138
}
139139

140140
void html_widget::set_caption(const std::string& caption)
@@ -346,7 +346,7 @@ long html_widget::draw_measure(int number)
346346
if(page)
347347
{
348348
litehtml::position view_port;
349-
get_client_rect(view_port);
349+
get_viewport(view_port);
350350

351351
int width = view_port.width;
352352
int height = view_port.height;

support/gtkmm4/html_widget.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ class html_widget : public Gtk::Widget,
251251
void redraw_boxes(const litehtml::position::vector& boxes) override;
252252
int get_render_width() override;
253253
void scroll_to(int x, int y) override;
254-
void get_client_rect(litehtml::position& client) const override;
254+
void get_viewport(litehtml::position& viewport) const override;
255255
cairo_surface_t* load_image(const std::string& path) override;
256256

257257
void snapshot_vfunc(const Glib::RefPtr<Gtk::Snapshot>& snapshot) override;

support/webpage/draw_buffer.cpp

Lines changed: 58 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "draw_buffer.h"
2+
#include "litehtml/types.h"
23

34
/// @brief Scrolls draw buffer to the position (left, top).
45
///
@@ -10,75 +11,73 @@
1011
/// @param top new vertical position
1112
void litebrowser::draw_buffer::on_scroll(std::shared_ptr<litebrowser::web_page> page, int left, int top)
1213
{
13-
if(m_width <= 0 || m_height <= 0 || !m_draw_buffer) return;
14+
if(m_width <= 0 || m_height <= 0 || !m_draw_buffer)
15+
return;
1416

15-
top = fix_position(top);
17+
top = fix_position(top);
1618
left = fix_position(left);
1719

1820
if(m_left != left || m_top != top)
1921
{
20-
litehtml::position rec_current(m_left, m_top, m_width, m_height); // Current area
21-
litehtml::position rec_new(left, top, m_width, m_height); // New area
22-
litehtml::position rec_clean = rec_current.intersect(rec_new); // Clean area
22+
litehtml::position rec_current(m_left, m_top, m_width, m_height); // Current area
23+
litehtml::position rec_new(left, top, m_width, m_height); // New area
24+
litehtml::position rec_clean = rec_current.intersect(rec_new); // Clean area
2325
if(rec_clean.empty() || rec_new == rec_current)
2426
{
2527
m_left = left;
26-
m_top = top;
28+
m_top = top;
2729
redraw(page);
2830
} else
2931
{
30-
int surface_shift_x = (int) std::floor((double) (m_left - left) * m_scale_factor);
31-
int surface_shift_y = (int) std::floor((double) (m_top - top) * m_scale_factor);
32+
int shift_x = m_left - left;
33+
int shift_y = m_top - top;
3234

33-
auto new_surface = make_surface(m_width, m_height, m_scale_factor);
34-
cairo_t* cr = cairo_create(new_surface);
35+
int surface_shift_x = (int) std::floor((double) shift_x * m_scale_factor);
36+
int surface_shift_y = (int) std::floor((double) shift_y * m_scale_factor);
37+
38+
auto new_surface = make_surface(m_width, m_height, m_scale_factor);
39+
cairo_t* cr = cairo_create(new_surface);
3540
cairo_rectangle(cr, (rec_clean.x - left) * m_scale_factor - m_scale_factor,
36-
(rec_clean.y - top) * m_scale_factor - m_scale_factor,
37-
std::ceil((double) rec_clean.width * m_scale_factor) + 2.0 * m_scale_factor,
38-
std::ceil((double) rec_clean.height * m_scale_factor) + 2.0 * m_scale_factor);
41+
(rec_clean.y - top) * m_scale_factor - m_scale_factor,
42+
std::ceil((double) rec_clean.width * m_scale_factor) + 2.0 * m_scale_factor,
43+
std::ceil((double) rec_clean.height * m_scale_factor) + 2.0 * m_scale_factor);
3944
cairo_clip(cr);
4045
cairo_set_source_surface(cr, m_draw_buffer, surface_shift_x, surface_shift_y);
4146
cairo_paint(cr);
4247
cairo_destroy(cr);
4348
cairo_surface_destroy(m_draw_buffer);
44-
m_draw_buffer = new_surface;
49+
m_draw_buffer = new_surface;
4550

46-
m_left = left;
47-
m_top = top;
51+
m_left = left;
52+
m_top = top;
4853

49-
int right = fix_position(m_left + m_width);
50-
int bottom = fix_position(m_top + m_height);
51-
int clean_right = fix_position(rec_clean.x + rec_clean.width);
54+
int right = fix_position(m_left + m_width);
55+
int bottom = fix_position(m_top + m_height);
56+
int clean_right = fix_position(rec_clean.x + rec_clean.width);
5257
int clean_bottom = fix_position(rec_clean.y + rec_clean.height);
5358

5459
if(rec_clean.x > m_left)
5560
{
56-
redraw_area(page, m_left,
57-
rec_clean.y,
58-
rec_clean.x - m_left,
59-
rec_clean.height);
61+
redraw_area(page, m_left, rec_clean.y, rec_clean.x - m_left, rec_clean.height);
6062
}
6163
if(clean_right < right)
6264
{
63-
redraw_area(page, clean_right,
64-
rec_clean.y,
65-
right - clean_right,
66-
rec_clean.height);
65+
redraw_area(page, clean_right, rec_clean.y, right - clean_right, rec_clean.height);
6766
}
6867

6968
if(rec_clean.y > m_top)
7069
{
71-
redraw_area(page, m_left,
72-
m_top,
73-
m_width,
74-
rec_clean.y - m_top);
70+
redraw_area(page, m_left, m_top, m_width, rec_clean.y - m_top);
7571
}
7672
if(clean_bottom < bottom)
7773
{
78-
redraw_area(page, m_left,
79-
clean_bottom,
80-
m_width,
81-
bottom - clean_bottom);
74+
redraw_area(page, m_left, clean_bottom, m_width, bottom - clean_bottom);
75+
}
76+
litehtml::position::vector fixed_boxes = page->get_fixed_boxes();
77+
for(const auto& box : fixed_boxes)
78+
{
79+
redraw_area(page, m_left + box.left(), m_top + box.top(), box.width, box.height);
80+
redraw_area(page, m_left + box.left() + shift_x, m_top + box.top() + shift_y, box.width, box.height);
8281
}
8382
}
8483
}
@@ -94,30 +93,33 @@ void litebrowser::draw_buffer::on_scroll(std::shared_ptr<litebrowser::web_page>
9493
/// @param y top position of the area
9594
/// @param width width of the area
9695
/// @param height height of the area
97-
void litebrowser::draw_buffer::redraw_area(std::shared_ptr<litebrowser::web_page> page, int x, int y, int width, int height)
96+
void litebrowser::draw_buffer::redraw_area(std::shared_ptr<litebrowser::web_page> page, int x, int y, int width,
97+
int height)
9898
{
9999
if(m_draw_buffer)
100100
{
101-
int fixed_left = fix_position(x - m_left);
102-
int fixed_right = fix_position(x - m_left + width);
103-
int fixed_top = fix_position(y - m_top);
104-
int fixed_bottom = fix_position(y - m_top + height);
105-
106-
if(fixed_right < x + width) fixed_right += m_min_int_position;
107-
if(fixed_bottom < y + height) fixed_bottom += m_min_int_position;
108-
109-
int fixed_x = fixed_left;
110-
int fixed_y = fixed_top;
111-
int fixed_width = fixed_right - fixed_left;
112-
int fixed_height = fixed_bottom - fixed_top;
113-
114-
int s_x = (int) std::round((double) fixed_x * m_scale_factor);
115-
int s_y = (int) std::round((double) fixed_y * m_scale_factor);
116-
int s_width = (int) std::round((double) fixed_width * m_scale_factor);
117-
int s_height = (int) std::round((double) fixed_height * m_scale_factor);
118-
119-
litehtml::position pos {fixed_x, fixed_y, fixed_width, fixed_height};
120-
cairo_t* cr = cairo_create(m_draw_buffer);
101+
int fixed_left = fix_position(x - m_left);
102+
int fixed_right = fix_position(x - m_left + width);
103+
int fixed_top = fix_position(y - m_top);
104+
int fixed_bottom = fix_position(y - m_top + height);
105+
106+
if(fixed_right < x + width)
107+
fixed_right += m_min_int_position;
108+
if(fixed_bottom < y + height)
109+
fixed_bottom += m_min_int_position;
110+
111+
int fixed_x = fixed_left;
112+
int fixed_y = fixed_top;
113+
int fixed_width = fixed_right - fixed_left;
114+
int fixed_height = fixed_bottom - fixed_top;
115+
116+
int s_x = (int) std::round((double) fixed_x * m_scale_factor);
117+
int s_y = (int) std::round((double) fixed_y * m_scale_factor);
118+
int s_width = (int) std::round((double) fixed_width * m_scale_factor);
119+
int s_height = (int) std::round((double) fixed_height * m_scale_factor);
120+
121+
litehtml::position pos{fixed_x, fixed_y, fixed_width, fixed_height};
122+
cairo_t* cr = cairo_create(m_draw_buffer);
121123

122124
// Apply clip with scaled position to avoid artifacts
123125
cairo_rectangle(cr, s_x, s_y, s_width, s_height);

support/webpage/html_host.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace litebrowser
1414
virtual void open_url(const std::string& url) = 0;
1515
virtual void update_cursor() = 0;
1616
virtual void scroll_to(int x, int y) = 0;
17-
virtual void get_client_rect(litehtml::position& client) const = 0;
17+
virtual void get_viewport(litehtml::position& viewport) const = 0;
1818
virtual void redraw_boxes(const litehtml::position::vector& boxes) = 0;
1919
virtual int get_render_width() = 0;
2020
virtual double get_dpi() = 0;

0 commit comments

Comments
 (0)