Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/litehtml/url.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class url {
return !fragment_.empty();
}

static string encode(const string& str);
static string decode(const string& str);

protected:
string str_;

Expand Down
108 changes: 80 additions & 28 deletions src/url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@

#include <sstream>
#include <algorithm>

#include "codepoint.h"
#include "url_path.h"
#include <iomanip>

namespace litehtml {

Expand Down Expand Up @@ -94,35 +94,87 @@ url::url(const string& str)
path_ = tmp;
}

url::url(const string& scheme,
const string& authority,
const string& path,
const string& query,
const string& fragment)
: scheme_(scheme)
, authority_(authority)
, path_(path)
, query_(query)
, fragment_(fragment)
url::url(const string& scheme, const string& authority, const string& path, const string& query,
const string& fragment) :
scheme_(scheme),
authority_(authority),
path_(path),
query_(query),
fragment_(fragment)
{
std::stringstream tss;
std::stringstream tss;

if(!scheme_.empty())
{
tss << scheme_ << ":";
}
if(!authority_.empty())
{
tss << "//" << authority_;
}
if(!path_.empty())
{
tss << path_;
}
if(!query_.empty())
{
tss << "?" << query_;
}
if(!fragment_.empty())
{
tss << "#" << fragment_;
}
str_ = tss.str();
}

if (!scheme_.empty()) {
tss << scheme_ << ":";
}
if (!authority_.empty()) {
tss << "//" << authority_;
}
if (!path_.empty()) {
tss << path_;
}
if (!query_.empty()) {
tss << "?" << query_;
}
if (!fragment_.empty()) {
tss << "#" << fragment_;
}
str_ = tss.str();
string url::encode(const string& str)
{
std::ostringstream encoded;
encoded << std::hex << std::uppercase;

for(unsigned char c : str)
{
if(isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
{
encoded << c;
} else
{
encoded << '%' << std::setw(2) << int((unsigned char) c);
}
}

return encoded.str();
}

string url::decode(const string& str)
{
string decoded;
size_t i = 0;

while(i < str.size())
{
char c = str[i];
if(c == '%')
{
if(i + 2 >= str.size())
{
break;
}

// Decode the percent-encoded character
char hex[3] = {str[i + 1], str[i + 2], '\0'};
c = static_cast<char>(std::strtol(hex, nullptr, 16));
i += 2; // Skip the next two characters
} else if(c == '+')
{
// Replace '+' with space
c = ' ';
}
decoded += c;
i++;
}

return decoded;
}

url resolve(const url& b, const url& r)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
/// Note, the actual position of the draw buffer can be rounded according to the scale factor.
/// Use get_left() and get_top() to know the actual position.
///
/// @param page webpage to be redraw if the position was changed
/// @param cb_draw the callback for drawing the page
/// @param left new horizontal position
/// @param top new vertical position
void litebrowser::draw_buffer::on_scroll(std::shared_ptr<litebrowser::web_page> page, int left, int top)
/// @param fixed_boxes fixed boxes to be redrawn
void litebrowser::draw_buffer::on_scroll(const draw_page_function_t& cb_draw, int left, int top, const litehtml::position::vector& fixed_boxes)
{
if(m_width <= 0 || m_height <= 0 || !m_draw_buffer)
return;
Expand All @@ -26,7 +27,7 @@ void litebrowser::draw_buffer::on_scroll(std::shared_ptr<litebrowser::web_page>
{
m_left = left;
m_top = top;
redraw(page);
redraw(cb_draw);
} else
{
int shift_x = m_left - left;
Expand Down Expand Up @@ -58,43 +59,42 @@ void litebrowser::draw_buffer::on_scroll(std::shared_ptr<litebrowser::web_page>

if(rec_clean.x > m_left)
{
redraw_area(page, m_left, rec_clean.y, rec_clean.x - m_left, rec_clean.height);
redraw_area(cb_draw, m_left, rec_clean.y, rec_clean.x - m_left, rec_clean.height);
}
if(clean_right < right)
{
redraw_area(page, clean_right, rec_clean.y, right - clean_right, rec_clean.height);
redraw_area(cb_draw, clean_right, rec_clean.y, right - clean_right, rec_clean.height);
}

if(rec_clean.y > m_top)
{
redraw_area(page, m_left, m_top, m_width, rec_clean.y - m_top);
redraw_area(cb_draw, m_left, m_top, m_width, rec_clean.y - m_top);
}
if(clean_bottom < bottom)
{
redraw_area(page, m_left, clean_bottom, m_width, bottom - clean_bottom);
redraw_area(cb_draw, m_left, clean_bottom, m_width, bottom - clean_bottom);
}
litehtml::position::vector fixed_boxes = page->get_fixed_boxes();

for(const auto& box : fixed_boxes)
{
redraw_area(page, m_left + box.left(), m_top + box.top(), box.width, box.height);
redraw_area(page, m_left + box.left() + shift_x, m_top + box.top() + shift_y, box.width, box.height);
redraw_area(cb_draw, m_left + box.left(), m_top + box.top(), box.width, box.height);
redraw_area(cb_draw, m_left + box.left() + shift_x, m_top + box.top() + shift_y, box.width, box.height);
}
}
}
}

/// @brief Reraw the defined area of the buffer
/// @brief Redraw the defined area of the buffer
///
/// All coordinated are not scaled. Actual rectangle could be different according to the scale factor,
/// All coordinated are not scaled. The actual rectangle could be different, according to the scale factor,
/// but it must always cover the requested.
///
/// @param page webpage to be redraw
/// @param cb_draw the callback for drawing the page
/// @param x left position of the area
/// @param y top position of the area
/// @param width width of the area
/// @param height height of the area
void litebrowser::draw_buffer::redraw_area(std::shared_ptr<litebrowser::web_page> page, int x, int y, int width,
int height)
void litebrowser::draw_buffer::redraw_area(const draw_page_function_t& cb_draw, int x, int y, int width, int height)
{
if(m_draw_buffer)
{
Expand Down Expand Up @@ -134,10 +134,7 @@ void litebrowser::draw_buffer::redraw_area(std::shared_ptr<litebrowser::web_page
cairo_scale(cr, m_scale_factor, m_scale_factor);

// Draw page
if(page)
{
page->draw((litehtml::uint_ptr) cr, -m_left, -m_top, &pos);
}
cb_draw(cr, -m_left, -m_top, &pos);

cairo_destroy(cr);
}
Expand Down
48 changes: 26 additions & 22 deletions support/webpage/draw_buffer.h → support/draw_buffer/draw_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@
#define LITEBROWSER_DRAW_BUFFER_H

#include <cairo.h>
#include <functional>
#include <cmath>
#include <memory>
#include "web_page.h"
#include "litehtml/types.h"

namespace litebrowser
{
/// @brief Draw Buffer Class
///
/// This class performs the draw operations into the cairo surface.
/// The application draws everything to the buffer, then buffer are
/// drawn on widged or window.
/// The application draws everything to the buffer, then buffer is
/// drawn on widget or window.
class draw_buffer
{
cairo_surface_t* m_draw_buffer = nullptr;
Expand All @@ -23,6 +25,8 @@ namespace litebrowser
int m_min_int_position = 1;
public:

using draw_page_function_t = std::function<void(cairo_t* cr, int x, int y, const litehtml::position* clip)>;

~draw_buffer()
{
if(m_draw_buffer)
Expand Down Expand Up @@ -50,9 +54,9 @@ namespace litebrowser
double get_scale_factor() const { return m_scale_factor; }

/// @brief Set scale factor for draw buffer
/// @param page the webpage to be redraw if required
/// @param cb_draw the callback for drawing the page
/// @param scale the scale factor to be applied
void set_scale_factor(std::shared_ptr<litebrowser::web_page> page, double scale)
void set_scale_factor(const draw_page_function_t& cb_draw, double scale)
{
if(m_scale_factor != scale)
{
Expand All @@ -68,16 +72,16 @@ namespace litebrowser
}
m_draw_buffer = nullptr;
create_draw_buffer(m_width, m_height);
redraw(page);
redraw(cb_draw);
}
}

/// @brief Create cairo surface for draw buffer
/// @param width surface width (not scaled)
/// @param height surface height (not scaled)
/// @param scale_factor scale factor
/// @return poiter to the cairo surface
cairo_surface_t* make_surface(int width, int height, double scale_factor)
/// @return pointer to the cairo surface
static cairo_surface_t* make_surface(int width, int height, double scale_factor)
{
return cairo_image_surface_create(CAIRO_FORMAT_RGB24,
std::ceil((double) width * scale_factor),
Expand Down Expand Up @@ -109,14 +113,14 @@ namespace litebrowser
}

/// @brief Call this function when widget size changed
/// @param page webpage to be redraw if buffer size changed
/// @param cb_draw the callback for drawing the page
/// @param width new draw buffer width
/// @param height new draw buffer height
void on_size_allocate(std::shared_ptr<litebrowser::web_page> page, int width, int height)
void on_size_allocate(const draw_page_function_t& cb_draw, int width, int height)
{
if(create_draw_buffer(width, height))
{
redraw(page);
redraw(cb_draw);
}
}

Expand All @@ -125,32 +129,33 @@ namespace litebrowser
/// Note, the actual position of the draw buffer can be rounded according to the scale factor.
/// Use get_left() and get_top() to know the actual position.
///
/// @param page webpage to be redraw if the position was changed
/// @param cb_draw the callback for drawing the page
/// @param left new horizontal position
/// @param top new vertical position
void on_scroll(std::shared_ptr<litebrowser::web_page> page, int left, int top);
/// @param fixed_boxes fixed boxes to be redrawn
void on_scroll(const draw_page_function_t& cb_draw, int left, int top, const litehtml::position::vector& fixed_boxes);

/// @brief Reraw the defined area of the buffer
/// @brief Redraw the defined area of the buffer
///
/// All coordinated are not scaled. Actual rectangle could be different according to the scale factor,
/// All coordinated are not scaled. The actual rectangle could be different, according to the scale factor,
/// but it must always cover the requested.
///
/// @param page webpage to be redraw
/// @param cb_draw the callback for drawing the page
/// @param x left position of the area
/// @param y top position of the area
/// @param width width of the area
/// @param height height of the area
void redraw_area(std::shared_ptr<litebrowser::web_page> page, int x, int y, int width, int height);
void redraw_area(const draw_page_function_t& cb_draw, int x, int y, int width, int height);

/// @brief Redraw entire buffer
/// @param page webpage to be redraw
void redraw(std::shared_ptr<litebrowser::web_page> page)
/// @param cb_draw the callback for drawing the page
void redraw(const draw_page_function_t& cb_draw)
{
redraw_area(page, m_left, m_top, m_width, m_height);
redraw_area(cb_draw, m_left, m_top, m_width, m_height);
}

private:
inline int fix_position(int pos)
[[nodiscard]] int fix_position(int pos) const
{
return (pos / m_min_int_position) * m_min_int_position;
}
Expand All @@ -172,7 +177,6 @@ namespace litebrowser
int denominator = 100;

int common_divisor = get_common_divisor(numerator, denominator);
numerator /= common_divisor;
return denominator / common_divisor;
}
};
Expand Down
Loading