summaryrefslogtreecommitdiff
path: root/libs/litehtml/containers/windows/win32/win32_container.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/litehtml/containers/windows/win32/win32_container.cpp')
-rw-r--r--libs/litehtml/containers/windows/win32/win32_container.cpp426
1 files changed, 426 insertions, 0 deletions
diff --git a/libs/litehtml/containers/windows/win32/win32_container.cpp b/libs/litehtml/containers/windows/win32/win32_container.cpp
new file mode 100644
index 0000000000..520b1ed234
--- /dev/null
+++ b/libs/litehtml/containers/windows/win32/win32_container.cpp
@@ -0,0 +1,426 @@
+#include "win32_container.h"
+
+win32_container::win32_container()
+{
+ m_hClipRgn = NULL;
+ m_tmp_hdc = GetDC(NULL);
+ InitializeCriticalSection(&m_img_sync);
+
+ EnumFonts(m_tmp_hdc, NULL, EnumFontsProc, (LPARAM)this);
+ m_installed_fonts.insert(L"monospace");
+ m_installed_fonts.insert(L"serif");
+ m_installed_fonts.insert(L"sans-serif");
+ m_installed_fonts.insert(L"fantasy");
+ m_installed_fonts.insert(L"cursive");
+}
+
+win32_container::~win32_container()
+{
+ DeleteCriticalSection(&m_img_sync);
+ if(m_hClipRgn)
+ {
+ DeleteObject(m_hClipRgn);
+ }
+ ReleaseDC(NULL, m_tmp_hdc);
+}
+
+int CALLBACK win32_container::EnumFontsProc(const LOGFONT* lplf, const TEXTMETRIC* lptm, DWORD dwType, LPARAM lpData)
+{
+ win32_container* container = (win32_container*)lpData;
+ container->m_installed_fonts.insert(lplf->lfFaceName);
+ return 1;
+}
+
+static LPCWSTR get_exact_font_name(LPCWSTR facename)
+{
+ if (!lstrcmpi(facename, L"monospace")) return L"Courier New";
+ else if (!lstrcmpi(facename, L"serif")) return L"Times New Roman";
+ else if (!lstrcmpi(facename, L"sans-serif")) return L"Arial";
+ else if (!lstrcmpi(facename, L"fantasy")) return L"Impact";
+ else if (!lstrcmpi(facename, L"cursive")) return L"Comic Sans MS";
+ else return facename;
+}
+
+static void trim_quotes(litehtml::string& str)
+{
+ if (str.front() == '"' || str.front() == '\'')
+ str.erase(0, 1);
+
+ if (str.back() == '"' || str.back() == '\'')
+ str.erase(str.length() - 1, 1);
+}
+
+litehtml::uint_ptr win32_container::create_font( const char* font_list, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm )
+{
+ std::wstring font_name;
+ litehtml::string_vector fonts;
+ litehtml::split_string(font_list, fonts, ",");
+ bool found = false;
+ for (auto& name : fonts)
+ {
+ litehtml::trim(name);
+ trim_quotes(name);
+ std::wstring wname = (const wchar_t*)litehtml_to_wchar(name.c_str());
+ if (m_installed_fonts.count(wname))
+ {
+ font_name = wname;
+ found = true;
+ break;
+ }
+ }
+ if (!found) font_name = litehtml_to_wchar(get_default_font_name());
+ font_name = get_exact_font_name(font_name.c_str());
+
+ LOGFONT lf = {};
+ wcscpy_s(lf.lfFaceName, LF_FACESIZE, font_name.c_str());
+
+ lf.lfHeight = -size;
+ lf.lfWeight = weight;
+ lf.lfItalic = (italic == litehtml::font_style_italic) ? TRUE : FALSE;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfStrikeOut = (decoration & litehtml::font_decoration_linethrough) ? TRUE : FALSE;
+ lf.lfUnderline = (decoration & litehtml::font_decoration_underline) ? TRUE : FALSE;
+ HFONT hFont = CreateFontIndirect(&lf);
+
+ if (fm)
+ {
+ SelectObject(m_tmp_hdc, hFont);
+ TEXTMETRIC tm = {};
+ GetTextMetrics(m_tmp_hdc, &tm);
+ fm->ascent = tm.tmAscent;
+ fm->descent = tm.tmDescent;
+ fm->height = tm.tmHeight;
+ fm->x_height = tm.tmHeight / 2; // this is an estimate; call GetGlyphOutline to get the real value
+ fm->draw_spaces = italic || decoration;
+ }
+
+ return (uint_ptr) hFont;
+}
+
+void win32_container::delete_font( uint_ptr hFont )
+{
+ DeleteObject((HFONT) hFont);
+}
+
+const char* win32_container::get_default_font_name() const
+{
+ return "Times New Roman";
+}
+
+int win32_container::get_default_font_size() const
+{
+ return 16;
+}
+
+int win32_container::text_width( const char* text, uint_ptr hFont )
+{
+ SIZE size = {};
+ SelectObject(m_tmp_hdc, (HFONT)hFont);
+ std::wstring wtext = (const wchar_t*)litehtml_to_wchar(text);
+ GetTextExtentPoint32(m_tmp_hdc, wtext.c_str(), (int)wtext.size(), &size);
+ return size.cx;
+}
+
+void win32_container::draw_text( uint_ptr hdc, const char* text, uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos )
+{
+ apply_clip((HDC) hdc);
+
+ HFONT oldFont = (HFONT) SelectObject((HDC) hdc, (HFONT) hFont);
+
+ SetBkMode((HDC) hdc, TRANSPARENT);
+
+ SetTextColor((HDC) hdc, RGB(color.red, color.green, color.blue));
+
+ RECT rcText = { pos.left(), pos.top(), pos.right(), pos.bottom() };
+ DrawText((HDC) hdc, litehtml_to_wchar(text), -1, &rcText, DT_SINGLELINE | DT_NOPREFIX | DT_BOTTOM | DT_NOCLIP);
+
+ SelectObject((HDC) hdc, oldFont);
+
+ release_clip((HDC) hdc);
+}
+
+int win32_container::pt_to_px( int pt ) const
+{
+ return MulDiv(pt, GetDeviceCaps(m_tmp_hdc, LOGPIXELSY), 72);
+}
+
+void win32_container::draw_list_marker(uint_ptr hdc, const litehtml::list_marker& marker)
+{
+ apply_clip((HDC)hdc);
+
+ int top_margin = marker.pos.height / 3;
+ if (top_margin < 4)
+ top_margin = 0;
+
+ int draw_x = marker.pos.x;
+ int draw_y = marker.pos.y + top_margin;
+ int draw_width = marker.pos.height - top_margin * 2;
+ int draw_height = marker.pos.height - top_margin * 2;
+
+ switch (marker.marker_type)
+ {
+ case litehtml::list_style_type_circle:
+ {
+ draw_ellipse((HDC)hdc, draw_x, draw_y, draw_width, draw_height, marker.color, 1);
+ }
+ break;
+ case litehtml::list_style_type_disc:
+ {
+ fill_ellipse((HDC)hdc, draw_x, draw_y, draw_width, draw_height, marker.color);
+ }
+ break;
+ case litehtml::list_style_type_square:
+ {
+ fill_rect((HDC)hdc, draw_x, draw_y, draw_width, draw_height, marker.color);
+ }
+ break;
+ }
+ release_clip((HDC)hdc);
+}
+
+void win32_container::make_url_utf8(const char* url, const char* basepath, std::wstring& out)
+{
+ make_url(litehtml::utf8_to_wchar(url), litehtml::utf8_to_wchar(basepath), out);
+}
+
+void win32_container::load_image( const char* src, const char* baseurl, bool redraw_on_ready )
+{
+ std::wstring url;
+ make_url_utf8(src, baseurl, url);
+
+ lock_images_cache();
+ if (m_images.count(url) == 0)
+ {
+ unlock_images_cache();
+ uint_ptr img = get_image(url.c_str(), redraw_on_ready);
+ add_image(url.c_str(), img);
+ }
+ else
+ {
+ unlock_images_cache();
+ }
+}
+
+void win32_container::add_image(LPCWSTR url, uint_ptr img)
+{
+ lock_images_cache();
+ m_images[url] = img;
+ unlock_images_cache();
+}
+
+void win32_container::get_image_size( const char* src, const char* baseurl, litehtml::size& sz )
+{
+ std::wstring url;
+ make_url_utf8(src, baseurl, url);
+
+ sz.width = 0;
+ sz.height = 0;
+
+ lock_images_cache();
+ images_map::iterator img = m_images.find(url);
+ if(img != m_images.end() && img->second)
+ {
+ get_img_size(img->second, sz);
+ }
+ unlock_images_cache();
+}
+
+void win32_container::clear_images()
+{
+ lock_images_cache();
+ for(auto& img : m_images)
+ {
+ if(img.second)
+ {
+ free_image(img.second);
+ }
+ }
+ m_images.clear();
+ unlock_images_cache();
+}
+
+void win32_container::lock_images_cache()
+{
+ EnterCriticalSection(&m_img_sync);
+}
+
+void win32_container::unlock_images_cache()
+{
+ LeaveCriticalSection(&m_img_sync);
+}
+
+void win32_container::draw_background( uint_ptr _hdc, const std::vector<litehtml::background_paint>& bg )
+{
+ HDC hdc = (HDC)_hdc;
+ apply_clip(hdc);
+
+ auto border_box = bg.back().border_box;
+ auto color = bg.back().color;
+ fill_rect(hdc, border_box.x, border_box.y, border_box.width, border_box.height, color);
+
+ for (int i = (int)bg.size() - 1; i >= 0; i--)
+ {
+ std::wstring url;
+ make_url_utf8(bg[i].image.c_str(), bg[i].baseurl.c_str(), url);
+
+ lock_images_cache();
+ images_map::iterator img = m_images.find(url);
+ if (img != m_images.end() && img->second)
+ {
+ draw_img_bg(hdc, img->second, bg[i]);
+ }
+ unlock_images_cache();
+ }
+
+ release_clip(hdc);
+}
+
+void win32_container::set_clip( const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius )
+{
+ m_clips.push_back(pos);
+}
+
+void win32_container::del_clip()
+{
+ if(!m_clips.empty())
+ {
+ m_clips.pop_back();
+ }
+}
+
+void win32_container::apply_clip(HDC hdc)
+{
+ if(m_hClipRgn)
+ {
+ DeleteObject(m_hClipRgn);
+ m_hClipRgn = NULL;
+ }
+
+ if(!m_clips.empty())
+ {
+ POINT ptView = {0, 0};
+ GetWindowOrgEx(hdc, &ptView);
+
+ litehtml::position clip_pos = m_clips.back();
+ m_hClipRgn = CreateRectRgn(clip_pos.left() - ptView.x, clip_pos.top() - ptView.y, clip_pos.right() - ptView.x, clip_pos.bottom() - ptView.y);
+ SelectClipRgn(hdc, m_hClipRgn);
+ }
+}
+
+void win32_container::release_clip(HDC hdc)
+{
+ SelectClipRgn(hdc, NULL);
+
+ if(m_hClipRgn)
+ {
+ DeleteObject(m_hClipRgn);
+ m_hClipRgn = NULL;
+ }
+}
+
+litehtml::element::ptr win32_container::create_element(const char* tag_name, const litehtml::string_map& attributes, const litehtml::document::ptr& doc)
+{
+ return 0;
+}
+
+void win32_container::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.color = 8;
+ media.monochrome = 0;
+ media.color_index = 256;
+ media.resolution = GetDeviceCaps(m_tmp_hdc, LOGPIXELSX);
+ media.device_width = GetDeviceCaps(m_tmp_hdc, HORZRES);
+ media.device_height = GetDeviceCaps(m_tmp_hdc, VERTRES);
+}
+
+void win32_container::get_language(litehtml::string& language, litehtml::string& culture) const
+{
+ language = "en";
+ culture = "";
+}
+
+void win32_container::transform_text(litehtml::string& text, litehtml::text_transform tt)
+{
+ if (text.empty()) return;
+
+ LPWSTR txt = _wcsdup(litehtml_to_wchar(text.c_str()));
+ switch (tt)
+ {
+ case litehtml::text_transform_capitalize:
+ CharUpperBuff(txt, 1);
+ break;
+ case litehtml::text_transform_uppercase:
+ CharUpperBuff(txt, lstrlen(txt));
+ break;
+ case litehtml::text_transform_lowercase:
+ CharLowerBuff(txt, lstrlen(txt));
+ break;
+ }
+ text = litehtml_from_wchar(txt);
+ free(txt);
+}
+
+void win32_container::link(const litehtml::document::ptr& doc, const litehtml::element::ptr& el)
+{
+}
+
+litehtml::string win32_container::resolve_color(const litehtml::string& color) const
+{
+ struct custom_color
+ {
+ const char* name;
+ int color_index;
+ };
+
+ static custom_color colors[] = {
+ { "ActiveBorder", COLOR_ACTIVEBORDER },
+ { "ActiveCaption", COLOR_ACTIVECAPTION },
+ { "AppWorkspace", COLOR_APPWORKSPACE },
+ { "Background", COLOR_BACKGROUND },
+ { "ButtonFace", COLOR_BTNFACE },
+ { "ButtonHighlight", COLOR_BTNHIGHLIGHT },
+ { "ButtonShadow", COLOR_BTNSHADOW },
+ { "ButtonText", COLOR_BTNTEXT },
+ { "CaptionText", COLOR_CAPTIONTEXT },
+ { "GrayText", COLOR_GRAYTEXT },
+ { "Highlight", COLOR_HIGHLIGHT },
+ { "HighlightText", COLOR_HIGHLIGHTTEXT },
+ { "InactiveBorder", COLOR_INACTIVEBORDER },
+ { "InactiveCaption", COLOR_INACTIVECAPTION },
+ { "InactiveCaptionText", COLOR_INACTIVECAPTIONTEXT },
+ { "InfoBackground", COLOR_INFOBK },
+ { "InfoText", COLOR_INFOTEXT },
+ { "Menu", COLOR_MENU },
+ { "MenuText", COLOR_MENUTEXT },
+ { "Scrollbar", COLOR_SCROLLBAR },
+ { "ThreeDDarkShadow", COLOR_3DDKSHADOW },
+ { "ThreeDFace", COLOR_3DFACE },
+ { "ThreeDHighlight", COLOR_3DHILIGHT },
+ { "ThreeDLightShadow", COLOR_3DLIGHT },
+ { "ThreeDShadow", COLOR_3DSHADOW },
+ { "Window", COLOR_WINDOW },
+ { "WindowFrame", COLOR_WINDOWFRAME },
+ { "WindowText", COLOR_WINDOWTEXT }
+ };
+
+ for (auto& clr : colors)
+ {
+ if (!litehtml::t_strcasecmp(color.c_str(), clr.name))
+ {
+ char str_clr[20];
+ DWORD rgb_color = GetSysColor(clr.color_index);
+ t_snprintf(str_clr, 20, "#%02X%02X%02X", GetRValue(rgb_color), GetGValue(rgb_color), GetBValue(rgb_color));
+ return std::move(litehtml::string(str_clr));
+ }
+ }
+ return std::move(litehtml::string());
+}