Skip to content

Commit 866f47a

Browse files
authored
Merge pull request #258 from stasoid/master
support multiple background images
2 parents 1a54416 + f7e10d0 commit 866f47a

25 files changed

+682
-440
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ if(NOT EXTERNAL_GUMBO)
1717
endif()
1818

1919
set(SOURCE_LITEHTML
20-
src/background.cpp
2120
src/codepoint.cpp
2221
src/css_length.cpp
2322
src/css_selector.cpp

containers/cairo/cairo_container.cpp

Lines changed: 57 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,14 @@ void cairo_container::draw_image( litehtml::uint_ptr hdc, const char* src, const
241241
cairo_restore(cr);
242242
}
243243

244-
void cairo_container::draw_background( litehtml::uint_ptr hdc, const litehtml::background_paint& bg )
244+
void cairo_container::draw_background( litehtml::uint_ptr hdc, const std::vector<litehtml::background_paint>& bgvec )
245245
{
246246
cairo_t* cr = (cairo_t*) hdc;
247247
cairo_save(cr);
248248
apply_clip(cr);
249249

250+
const auto& bg = bgvec.back();
251+
250252
rounded_rectangle(cr, bg.border_box, bg.border_radius);
251253
cairo_clip(cr);
252254

@@ -259,61 +261,70 @@ void cairo_container::draw_background( litehtml::uint_ptr hdc, const litehtml::b
259261
cairo_paint(cr);
260262
}
261263

262-
std::wstring url;
263-
make_url_utf8(bg.image.c_str(), bg.baseurl.c_str(), url);
264-
265-
lock_images_cache();
266-
images_map::iterator img_i = m_images.find(url.c_str());
267-
if(img_i != m_images.end() && img_i->second)
264+
for (int i = (int)bgvec.size() - 1; i >= 0; i--)
268265
{
269-
image_ptr bgbmp = img_i->second;
270-
271-
image_ptr new_img;
272-
if(bg.image_size.width != bgbmp->getWidth() || bg.image_size.height != bgbmp->getHeight())
273-
{
274-
new_img = image_ptr(new CTxDIB);
275-
bgbmp->resample(bg.image_size.width, bg.image_size.height, new_img.get());
276-
bgbmp = new_img;
277-
}
266+
const auto& bg = bgvec[i];
278267

268+
cairo_rectangle(cr, bg.clip_box.x, bg.clip_box.y, bg.clip_box.width, bg.clip_box.height);
269+
cairo_clip(cr);
279270

280-
cairo_surface_t* img = cairo_image_surface_create_for_data((unsigned char*) bgbmp->getBits(), CAIRO_FORMAT_ARGB32, bgbmp->getWidth(), bgbmp->getHeight(), bgbmp->getWidth() * 4);
281-
cairo_pattern_t *pattern = cairo_pattern_create_for_surface(img);
282-
cairo_matrix_t flib_m;
283-
cairo_matrix_init(&flib_m, 1, 0, 0, -1, 0, 0);
284-
cairo_matrix_translate(&flib_m, -bg.position_x, -bg.position_y);
285-
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
286-
cairo_pattern_set_matrix (pattern, &flib_m);
271+
std::wstring url;
272+
make_url_utf8(bg.image.c_str(), bg.baseurl.c_str(), url);
287273

288-
switch(bg.repeat)
274+
lock_images_cache();
275+
auto img_i = m_images.find(url);
276+
if (img_i != m_images.end() && img_i->second)
289277
{
290-
case litehtml::background_repeat_no_repeat:
291-
draw_txdib(cr, bgbmp.get(), bg.position_x, bg.position_y, bgbmp->getWidth(), bgbmp->getHeight());
292-
break;
278+
image_ptr bgbmp = img_i->second;
293279

294-
case litehtml::background_repeat_repeat_x:
295-
cairo_set_source(cr, pattern);
296-
cairo_rectangle(cr, bg.clip_box.left(), bg.position_y, bg.clip_box.width, bgbmp->getHeight());
297-
cairo_fill(cr);
298-
break;
280+
image_ptr new_img;
281+
if (bg.image_size.width != bgbmp->getWidth() || bg.image_size.height != bgbmp->getHeight())
282+
{
283+
new_img = image_ptr(new CTxDIB);
284+
bgbmp->resample(bg.image_size.width, bg.image_size.height, new_img.get());
285+
bgbmp = new_img;
286+
}
299287

300-
case litehtml::background_repeat_repeat_y:
301-
cairo_set_source(cr, pattern);
302-
cairo_rectangle(cr, bg.position_x, bg.clip_box.top(), bgbmp->getWidth(), bg.clip_box.height);
303-
cairo_fill(cr);
304-
break;
305288

306-
case litehtml::background_repeat_repeat:
307-
cairo_set_source(cr, pattern);
308-
cairo_rectangle(cr, bg.clip_box.left(), bg.clip_box.top(), bg.clip_box.width, bg.clip_box.height);
309-
cairo_fill(cr);
310-
break;
311-
}
289+
cairo_surface_t* img = cairo_image_surface_create_for_data((unsigned char*)bgbmp->getBits(), CAIRO_FORMAT_ARGB32, bgbmp->getWidth(), bgbmp->getHeight(), bgbmp->getWidth() * 4);
290+
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(img);
291+
cairo_matrix_t flib_m;
292+
cairo_matrix_init(&flib_m, 1, 0, 0, -1, 0, 0);
293+
cairo_matrix_translate(&flib_m, -bg.position_x, -bg.position_y);
294+
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
295+
cairo_pattern_set_matrix(pattern, &flib_m);
312296

313-
cairo_pattern_destroy(pattern);
314-
cairo_surface_destroy(img);
297+
switch (bg.repeat)
298+
{
299+
case litehtml::background_repeat_no_repeat:
300+
draw_txdib(cr, bgbmp.get(), bg.position_x, bg.position_y, bgbmp->getWidth(), bgbmp->getHeight());
301+
break;
302+
303+
case litehtml::background_repeat_repeat_x:
304+
cairo_set_source(cr, pattern);
305+
cairo_rectangle(cr, bg.clip_box.left(), bg.position_y, bg.clip_box.width, bgbmp->getHeight());
306+
cairo_fill(cr);
307+
break;
308+
309+
case litehtml::background_repeat_repeat_y:
310+
cairo_set_source(cr, pattern);
311+
cairo_rectangle(cr, bg.position_x, bg.clip_box.top(), bgbmp->getWidth(), bg.clip_box.height);
312+
cairo_fill(cr);
313+
break;
314+
315+
case litehtml::background_repeat_repeat:
316+
cairo_set_source(cr, pattern);
317+
cairo_rectangle(cr, bg.clip_box.left(), bg.clip_box.top(), bg.clip_box.width, bg.clip_box.height);
318+
cairo_fill(cr);
319+
break;
320+
}
321+
322+
cairo_pattern_destroy(pattern);
323+
cairo_surface_destroy(img);
324+
}
325+
unlock_images_cache();
315326
}
316-
unlock_images_cache();
327+
317328
cairo_restore(cr);
318329
}
319330

containers/cairo/cairo_container.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class cairo_container : public litehtml::document_container
6666
virtual void load_image(const char* src, const char* baseurl, bool redraw_on_ready) override;
6767
virtual void get_image_size(const char* src, const char* baseurl, litehtml::size& sz) override;
6868
virtual void draw_image(litehtml::uint_ptr hdc, const char* src, const char* baseurl, const litehtml::position& pos);
69-
virtual void draw_background(litehtml::uint_ptr hdc, const litehtml::background_paint& bg) override;
69+
virtual void draw_background(litehtml::uint_ptr hdc, const std::vector<litehtml::background_paint>& bg) override;
7070
virtual void draw_borders(litehtml::uint_ptr hdc, const litehtml::borders& borders, const litehtml::position& draw_pos, bool root) override;
7171

7272
virtual void transform_text(litehtml::string& text, litehtml::text_transform tt) override;

containers/linux/container_linux.cpp

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,14 @@ void container_linux::get_image_size( const char* src, const char* baseurl, lite
290290
}
291291
}
292292

293-
void container_linux::draw_background( litehtml::uint_ptr hdc, const litehtml::background_paint& bg )
293+
void container_linux::draw_background( litehtml::uint_ptr hdc, const std::vector<litehtml::background_paint>& bgvec )
294294
{
295295
auto* cr = (cairo_t*) hdc;
296296
cairo_save(cr);
297297
apply_clip(cr);
298298

299+
const auto& bg = bgvec.back();
300+
299301
rounded_rectangle(cr, bg.border_box, bg.border_radius);
300302
cairo_clip(cr);
301303

@@ -308,60 +310,68 @@ void container_linux::draw_background( litehtml::uint_ptr hdc, const litehtml::b
308310
cairo_paint(cr);
309311
}
310312

311-
litehtml::string url;
312-
make_url(bg.image.c_str(), bg.baseurl.c_str(), url);
313-
314-
//lock_images_cache();
315-
auto img_i = m_images.find(url);
316-
if(img_i != m_images.end() && img_i->second)
313+
for (int i = (int)bgvec.size() - 1; i >= 0; i--)
317314
{
318-
Glib::RefPtr<Gdk::Pixbuf> bgbmp = img_i->second;
315+
const auto& bg = bgvec[i];
319316

320-
Glib::RefPtr<Gdk::Pixbuf> new_img;
321-
if(bg.image_size.width != bgbmp->get_width() || bg.image_size.height != bgbmp->get_height())
322-
{
323-
new_img = bgbmp->scale_simple(bg.image_size.width, bg.image_size.height, Gdk::INTERP_BILINEAR);
324-
bgbmp = new_img;
325-
}
317+
cairo_rectangle(cr, bg.clip_box.x, bg.clip_box.y, bg.clip_box.width, bg.clip_box.height);
318+
cairo_clip(cr);
326319

327-
cairo_surface_t* img = surface_from_pixbuf(bgbmp);
328-
cairo_pattern_t *pattern = cairo_pattern_create_for_surface(img);
329-
cairo_matrix_t flib_m;
330-
cairo_matrix_init_identity(&flib_m);
331-
cairo_matrix_translate(&flib_m, -bg.position_x, -bg.position_y);
332-
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
333-
cairo_pattern_set_matrix (pattern, &flib_m);
320+
std::string url;
321+
make_url(bg.image.c_str(), bg.baseurl.c_str(), url);
334322

335-
switch(bg.repeat)
323+
//lock_images_cache();
324+
auto img_i = m_images.find(url);
325+
if(img_i != m_images.end() && img_i->second)
336326
{
337-
case litehtml::background_repeat_no_repeat:
338-
draw_pixbuf(cr, bgbmp, bg.position_x, bg.position_y, bgbmp->get_width(), bgbmp->get_height());
339-
break;
327+
Glib::RefPtr<Gdk::Pixbuf> bgbmp = img_i->second;
340328

341-
case litehtml::background_repeat_repeat_x:
342-
cairo_set_source(cr, pattern);
343-
cairo_rectangle(cr, bg.clip_box.left(), bg.position_y, bg.clip_box.width, bgbmp->get_height());
344-
cairo_fill(cr);
345-
break;
329+
Glib::RefPtr<Gdk::Pixbuf> new_img;
330+
if(bg.image_size.width != bgbmp->get_width() || bg.image_size.height != bgbmp->get_height())
331+
{
332+
new_img = bgbmp->scale_simple(bg.image_size.width, bg.image_size.height, Gdk::INTERP_BILINEAR);
333+
bgbmp = new_img;
334+
}
346335

347-
case litehtml::background_repeat_repeat_y:
348-
cairo_set_source(cr, pattern);
349-
cairo_rectangle(cr, bg.position_x, bg.clip_box.top(), bgbmp->get_width(), bg.clip_box.height);
350-
cairo_fill(cr);
351-
break;
336+
cairo_surface_t* img = surface_from_pixbuf(bgbmp);
337+
cairo_pattern_t *pattern = cairo_pattern_create_for_surface(img);
338+
cairo_matrix_t flib_m;
339+
cairo_matrix_init_identity(&flib_m);
340+
cairo_matrix_translate(&flib_m, -bg.position_x, -bg.position_y);
341+
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
342+
cairo_pattern_set_matrix (pattern, &flib_m);
352343

353-
case litehtml::background_repeat_repeat:
354-
cairo_set_source(cr, pattern);
355-
cairo_rectangle(cr, bg.clip_box.left(), bg.clip_box.top(), bg.clip_box.width, bg.clip_box.height);
356-
cairo_fill(cr);
357-
break;
358-
}
344+
switch(bg.repeat)
345+
{
346+
case litehtml::background_repeat_no_repeat:
347+
draw_pixbuf(cr, bgbmp, bg.position_x, bg.position_y, bgbmp->get_width(), bgbmp->get_height());
348+
break;
359349

360-
cairo_pattern_destroy(pattern);
361-
cairo_surface_destroy(img);
350+
case litehtml::background_repeat_repeat_x:
351+
cairo_set_source(cr, pattern);
352+
cairo_rectangle(cr, bg.clip_box.left(), bg.position_y, bg.clip_box.width, bgbmp->get_height());
353+
cairo_fill(cr);
354+
break;
355+
356+
case litehtml::background_repeat_repeat_y:
357+
cairo_set_source(cr, pattern);
358+
cairo_rectangle(cr, bg.position_x, bg.clip_box.top(), bgbmp->get_width(), bg.clip_box.height);
359+
cairo_fill(cr);
360+
break;
362361

362+
case litehtml::background_repeat_repeat:
363+
cairo_set_source(cr, pattern);
364+
cairo_rectangle(cr, bg.clip_box.left(), bg.clip_box.top(), bg.clip_box.width, bg.clip_box.height);
365+
cairo_fill(cr);
366+
break;
367+
}
368+
369+
cairo_pattern_destroy(pattern);
370+
cairo_surface_destroy(img);
371+
}
372+
//unlock_images_cache();
363373
}
364-
// unlock_images_cache();
374+
365375
cairo_restore(cr);
366376
}
367377

containers/linux/container_linux.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class container_linux : public litehtml::document_container
6767
const char* get_default_font_name() const override;
6868
void load_image(const char* src, const char* baseurl, bool redraw_on_ready) override;
6969
void get_image_size(const char* src, const char* baseurl, litehtml::size& sz) override;
70-
void draw_background(litehtml::uint_ptr hdc, const litehtml::background_paint& bg) override;
70+
void draw_background(litehtml::uint_ptr hdc, const std::vector<litehtml::background_paint>& bg) override;
7171
void draw_borders(litehtml::uint_ptr hdc, const litehtml::borders& borders, const litehtml::position& draw_pos, bool root) override;
7272
void draw_list_marker(litehtml::uint_ptr hdc, const litehtml::list_marker& marker) override;
7373
std::shared_ptr<litehtml::element> create_element(const char *tag_name,

containers/test/test_container.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ int test_container::pt_to_px(int pt) const { return pt * 96 / 72; }
4141
int test_container::get_default_font_size() const { return 16; }
4242
const char* test_container::get_default_font_name() const { return ""; }
4343

44-
void test_container::draw_background(uint_ptr hdc, const background_paint& bg)
44+
void test_container::draw_background(uint_ptr hdc, const std::vector<background_paint>& bg)
4545
{
4646
Bitmap* bmp = (Bitmap*)hdc;
47-
bmp->fill_rect(bg.border_box, bg.color);
47+
bmp->fill_rect(bg.back().border_box, bg.back().color);
4848
}
4949

5050
void test_container::draw_borders(uint_ptr hdc, const borders& borders, const position& pos, bool root)

containers/test/test_container.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class test_container : public document_container
1919
const char* get_default_font_name() const override;
2020
void load_image(const char* src, const char* baseurl, bool redraw_on_ready) override {}
2121
void get_image_size(const char* src, const char* baseurl, size& sz) override {}
22-
void draw_background(uint_ptr hdc, const background_paint& bg) override;
22+
void draw_background(uint_ptr hdc, const std::vector<background_paint>& bg) override;
2323
void draw_borders(uint_ptr hdc, const borders& borders, const position& draw_pos, bool root) override;
2424
void draw_list_marker(uint_ptr hdc, const list_marker& marker) override;
2525
element::ptr create_element(const char* tag_name,

containers/win32/win32_container.cpp

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -252,36 +252,28 @@ void win32_container::unlock_images_cache()
252252
LeaveCriticalSection(&m_img_sync);
253253
}
254254

255-
static void FillSolidRect(HDC hdc, LPCRECT lpRect, COLORREF clr)
256-
{
257-
COLORREF clrOld = SetBkColor(hdc, clr);
258-
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
259-
SetBkColor(hdc, clrOld);
260-
}
261-
262-
void win32_container::draw_background( uint_ptr _hdc, const litehtml::background_paint& bg )
255+
void win32_container::draw_background( uint_ptr _hdc, const std::vector<litehtml::background_paint>& bg )
263256
{
264257
HDC hdc = (HDC)_hdc;
265258
apply_clip(hdc);
266259

267-
RECT rect = { bg.border_box.left(), bg.border_box.top(), bg.border_box.right(), bg.border_box.bottom() };
268-
COLORREF color = RGB(bg.color.red, bg.color.green, bg.color.blue);
269-
// alpha channel for background color is not supported; alpha below some threshold is considered transparent, above it - opaque
270-
if (bg.color.alpha > 30)
271-
{
272-
FillSolidRect(hdc, &rect, color);
273-
}
274-
275-
std::wstring url;
276-
make_url_utf8(bg.image.c_str(), bg.baseurl.c_str(), url);
260+
auto border_box = bg.back().border_box;
261+
auto color = bg.back().color;
262+
fill_rect(hdc, border_box.x, border_box.y, border_box.width, border_box.height, color);
277263

278-
lock_images_cache();
279-
images_map::iterator img = m_images.find(url);
280-
if(img != m_images.end() && img->second)
264+
for (int i = (int)bg.size() - 1; i >= 0; i--)
281265
{
282-
draw_img_bg(hdc, img->second, bg);
266+
std::wstring url;
267+
make_url_utf8(bg[i].image.c_str(), bg[i].baseurl.c_str(), url);
268+
269+
lock_images_cache();
270+
images_map::iterator img = m_images.find(url);
271+
if (img != m_images.end() && img->second)
272+
{
273+
draw_img_bg(hdc, img->second, bg[i]);
274+
}
275+
unlock_images_cache();
283276
}
284-
unlock_images_cache();
285277

286278
release_clip(hdc);
287279
}

containers/win32/win32_container.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class win32_container : public litehtml::document_container
3434
void draw_list_marker(uint_ptr hdc, const litehtml::list_marker& marker) override;
3535
void load_image(const char* src, const char* baseurl, bool redraw_on_ready) override;
3636
void get_image_size(const char* src, const char* baseurl, litehtml::size& sz) override;
37-
void draw_background(uint_ptr hdc, const litehtml::background_paint& bg) override;
37+
void draw_background(uint_ptr hdc, const std::vector<litehtml::background_paint>& bg) override;
3838

3939
void set_clip(const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius, bool valid_x, bool valid_y) override;
4040
void del_clip() override;

0 commit comments

Comments
 (0)