Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 64be8fe

Browse filesBrowse files
committed
Move draw buffer class out of html_widget.h
1 parent e8dc2ed commit 64be8fe
Copy full SHA for 64be8fe

File tree

Expand file treeCollapse file tree

5 files changed

+329
-292
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+329
-292
lines changed

‎CMakeLists.txt

Copy file name to clipboardExpand all lines: CMakeLists.txt
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ set(SOURCE ${LITEBROWSER_PATH}/main.cpp
2626
${LITEBROWSER_PATH}/widget/html_widget.cpp
2727
${LITEBROWSER_PATH}/browser_wnd.cpp
2828
${LITEBROWSER_PATH}/webpage/web_history.cpp
29+
${LITEBROWSER_PATH}/webpage/draw_buffer.cpp
2930
${LITEBROWSER_PATH}/webpage/http_request.cpp
3031
${LITEBROWSER_PATH}/webpage/web_page.cpp
3132
${LITEBROWSER_PATH}/webpage/http_requests_pool.cpp
@@ -41,6 +42,7 @@ set(HEADERS ${LITEBROWSER_PATH}/browser_wnd.h
4142
${LITEBROWSER_PATH}/webpage/web_page.h
4243
${LITEBROWSER_PATH}/webpage/html_host.h
4344
${LITEBROWSER_PATH}/webpage/http_requests_pool.h
45+
${LITEBROWSER_PATH}/webpage/draw_buffer.h
4446
${LITEBROWSER_PATH}/html_dumper.h
4547
${CONTAINER_PATH}/container_cairo.h
4648
${CONTAINER_PATH}/cairo_borders.h

‎litehtml

Copy file name to clipboard

‎src/webpage/draw_buffer.cpp

Copy file name to clipboard
+142Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#include "draw_buffer.h"
2+
3+
/// @brief Scrolls draw buffer to the position (left, top).
4+
///
5+
/// Note, the actual position of the draw buffer can be rounded according to the scale factor.
6+
/// Use get_left() and get_top() to know the actual position.
7+
///
8+
/// @param page webpage to be redraw if the position was changed
9+
/// @param left new horizontal position
10+
/// @param top new vertical position
11+
void litebrowser::draw_buffer::on_scroll(std::shared_ptr<litebrowser::web_page> page, int left, int top)
12+
{
13+
if(m_width <= 0 || m_height <= 0 || !m_draw_buffer) return;
14+
15+
top = fix_position(top);
16+
left = fix_position(left);
17+
18+
if(m_left != left || m_top != top)
19+
{
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
23+
if(rec_clean.empty() || rec_new == rec_current)
24+
{
25+
m_left = left;
26+
m_top = top;
27+
redraw(page);
28+
} else
29+
{
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+
33+
auto new_surface = make_surface(m_width, m_height, m_scale_factor);
34+
cairo_t* cr = cairo_create(new_surface);
35+
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);
39+
cairo_clip(cr);
40+
cairo_set_source_surface(cr, m_draw_buffer, surface_shift_x, surface_shift_y);
41+
cairo_paint(cr);
42+
cairo_destroy(cr);
43+
cairo_surface_destroy(m_draw_buffer);
44+
m_draw_buffer = new_surface;
45+
46+
m_left = left;
47+
m_top = top;
48+
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);
52+
int clean_bottom = fix_position(rec_clean.y + rec_clean.height);
53+
54+
if(rec_clean.x > m_left)
55+
{
56+
redraw_area(page, m_left,
57+
rec_clean.y,
58+
rec_clean.x - m_left,
59+
rec_clean.height);
60+
}
61+
if(clean_right < right)
62+
{
63+
redraw_area(page, clean_right,
64+
rec_clean.y,
65+
right - clean_right,
66+
rec_clean.height);
67+
}
68+
69+
if(rec_clean.y > m_top)
70+
{
71+
redraw_area(page, m_left,
72+
m_top,
73+
m_width,
74+
rec_clean.y - m_top);
75+
}
76+
if(clean_bottom < bottom)
77+
{
78+
redraw_area(page, m_left,
79+
clean_bottom,
80+
m_width,
81+
bottom - clean_bottom);
82+
}
83+
}
84+
}
85+
}
86+
87+
/// @brief Reraw the defined area of the buffer
88+
///
89+
/// All coordinated are not scaled. Actual rectangle could be different according to the scale factor,
90+
/// but it must always cover the requested.
91+
///
92+
/// @param page webpage to be redraw
93+
/// @param x left position of the area
94+
/// @param y top position of the area
95+
/// @param width width of the area
96+
/// @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)
98+
{
99+
if(m_draw_buffer)
100+
{
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);
121+
122+
// Apply clip with scaled position to avoid artifacts
123+
cairo_rectangle(cr, s_x, s_y, s_width, s_height);
124+
cairo_clip(cr);
125+
126+
// Clear rectangle with scaled position
127+
cairo_rectangle(cr, s_x, s_y, s_width, s_height);
128+
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
129+
cairo_fill(cr);
130+
131+
// Apply scale for drawing
132+
cairo_scale(cr, m_scale_factor, m_scale_factor);
133+
134+
// Draw page
135+
if(page)
136+
{
137+
page->draw((litehtml::uint_ptr) cr, -m_left, -m_top, &pos);
138+
}
139+
140+
cairo_destroy(cr);
141+
}
142+
}

‎src/webpage/draw_buffer.h

Copy file name to clipboard
+182Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#ifndef LITEBROWSER_DRAW_BUFFER_H
2+
#define LITEBROWSER_DRAW_BUFFER_H
3+
4+
#include <cairo.h>
5+
#include <memory>
6+
#include "web_page.h"
7+
8+
namespace litebrowser
9+
{
10+
/// @brief Draw Buffer Class
11+
///
12+
/// This class performs the draw operations into the cairo surface.
13+
/// The application draws everything to the buffer, then buffer are
14+
/// drawn on widged or window.
15+
class draw_buffer
16+
{
17+
cairo_surface_t* m_draw_buffer = nullptr;
18+
int m_width = 0;
19+
int m_height = 0;
20+
int m_top = 0;
21+
int m_left = 0;
22+
double m_scale_factor = 1;
23+
int m_min_int_position = 1;
24+
public:
25+
26+
~draw_buffer()
27+
{
28+
if(m_draw_buffer)
29+
{
30+
cairo_surface_destroy(m_draw_buffer);
31+
}
32+
}
33+
34+
[[nodiscard]]
35+
int get_width() const { return m_width; }
36+
37+
[[nodiscard]]
38+
int get_height() const { return m_height; }
39+
40+
[[nodiscard]]
41+
int get_left() const { return m_left; }
42+
43+
[[nodiscard]]
44+
int get_top() const { return m_top; }
45+
46+
[[nodiscard]]
47+
cairo_surface_t* get_cairo_surface() const { return m_draw_buffer; }
48+
49+
[[nodiscard]]
50+
double get_scale_factor() const { return m_scale_factor; }
51+
52+
/// @brief Set scale factor for draw buffer
53+
/// @param page the webpage to be redraw if required
54+
/// @param scale the scale factor to be applied
55+
void set_scale_factor(std::shared_ptr<litebrowser::web_page> page, double scale)
56+
{
57+
if(m_scale_factor != scale)
58+
{
59+
m_scale_factor = scale;
60+
m_min_int_position = get_denominator(m_scale_factor);
61+
62+
m_top = fix_position(m_top);
63+
m_left = fix_position(m_left);
64+
65+
if(m_draw_buffer)
66+
{
67+
cairo_surface_destroy(m_draw_buffer);
68+
}
69+
m_draw_buffer = nullptr;
70+
create_draw_buffer(m_width, m_height);
71+
redraw(page);
72+
}
73+
}
74+
75+
/// @brief Create cairo surface for draw buffer
76+
/// @param width surface width (not scaled)
77+
/// @param height surface height (not scaled)
78+
/// @param scale_factor scale factor
79+
/// @return poiter to the cairo surface
80+
cairo_surface_t* make_surface(int width, int height, double scale_factor)
81+
{
82+
return cairo_image_surface_create(CAIRO_FORMAT_RGB24,
83+
std::ceil((double) width * scale_factor),
84+
std::ceil((double) height * scale_factor));
85+
}
86+
87+
/// @brief Creates new buffer with specified size
88+
/// @param width draw buffer width (not scaled)
89+
/// @param height draw buffer height (not scaled)
90+
/// @return true if new draw buffer was created, false if the old buffer was used
91+
bool create_draw_buffer(int width, int height)
92+
{
93+
if(m_width != width || m_height != height || !m_draw_buffer)
94+
{
95+
m_width = width;
96+
m_height = height;
97+
if(m_draw_buffer)
98+
{
99+
cairo_surface_destroy(m_draw_buffer);
100+
}
101+
m_draw_buffer = nullptr;
102+
if(m_width > 0 && m_height > 0)
103+
{
104+
m_draw_buffer = make_surface(m_width, m_height, m_scale_factor);
105+
}
106+
return true;
107+
}
108+
return false;
109+
}
110+
111+
/// @brief Call this function when widget size changed
112+
/// @param page webpage to be redraw if buffer size changed
113+
/// @param width new draw buffer width
114+
/// @param height new draw buffer height
115+
void on_size_allocate(std::shared_ptr<litebrowser::web_page> page, int width, int height)
116+
{
117+
if(create_draw_buffer(width, height))
118+
{
119+
redraw(page);
120+
}
121+
}
122+
123+
/// @brief Scrolls draw buffer to the position (left, top).
124+
///
125+
/// Note, the actual position of the draw buffer can be rounded according to the scale factor.
126+
/// Use get_left() and get_top() to know the actual position.
127+
///
128+
/// @param page webpage to be redraw if the position was changed
129+
/// @param left new horizontal position
130+
/// @param top new vertical position
131+
void on_scroll(std::shared_ptr<litebrowser::web_page> page, int left, int top);
132+
133+
/// @brief Reraw the defined area of the buffer
134+
///
135+
/// All coordinated are not scaled. Actual rectangle could be different according to the scale factor,
136+
/// but it must always cover the requested.
137+
///
138+
/// @param page webpage to be redraw
139+
/// @param x left position of the area
140+
/// @param y top position of the area
141+
/// @param width width of the area
142+
/// @param height height of the area
143+
void redraw_area(std::shared_ptr<litebrowser::web_page> page, int x, int y, int width, int height);
144+
145+
/// @brief Redraw entire buffer
146+
/// @param page webpage to be redraw
147+
void redraw(std::shared_ptr<litebrowser::web_page> page)
148+
{
149+
redraw_area(page, m_left, m_top, m_width, m_height);
150+
}
151+
152+
private:
153+
inline int fix_position(int pos)
154+
{
155+
return (pos / m_min_int_position) * m_min_int_position;
156+
}
157+
158+
static int get_common_divisor(int a, int b)
159+
{
160+
while (b != 0)
161+
{
162+
int t = b;
163+
b = a % b;
164+
a = t;
165+
}
166+
return a;
167+
}
168+
169+
static int get_denominator(double decimal)
170+
{
171+
int numerator = (int)(decimal * 100);
172+
int denominator = 100;
173+
174+
int common_divisor = get_common_divisor(numerator, denominator);
175+
numerator /= common_divisor;
176+
return denominator / common_divisor;
177+
}
178+
};
179+
180+
}
181+
182+
#endif

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.