Scrollbas in chrome or firefox does not have handle. They are handless control, but they do share the same apperance and behavior as the system default scrollbar. From which, we can infer that these browsers use the windows theme API, such as DrawThemeBackground, to draw the scrollbar.
However APIs such as DrawThemeBackground are GDI, chrome/firefox use skia/cario to render the whole canvas. My problem is how does they combine this two kind of technology?
Pesudo code:
WM_PAINT:
prepare canvas;
draw the canvas with skia/cario;
bitblt to the dc;
draw the theme-related handless control;(???)
bitblt to the dc or directly draw to the dc;(???)
Do the procedure resemble the above one?
Firefox
Actually cairo has a function to get DC from a cairo surface. Sample code:
VOID OnPaint(HWND hwnd, HDC hdc)
{
RECT rc;
::GetClientRect(hwnd, &rc);
//draw one line
cairo_surface_t* surface = cairo_win32_surface_create(hdc);
cairo_t* cr = cairo_create(surface);
cairo_set_source_rgb(cr, 0xff, 0, 0);
cairo_set_line_width(cr, 1);
cairo_move_to(cr, 0, 0);
cairo_line_to(cr, rc.right, rc.bottom);
cairo_stroke(cr);
cairo_destroy(cr);
//draw the theme background
HDC hdcNew = cairo_win32_surface_get_dc(surface);
HTHEME hTheme = OpenThemeData(NULL, L"SCROLLBAR");
RECT rcArrow;
SetRect(&rcArrow, 30, 30, 45, 45);
DrawThemeBackground(hTheme, hdcNew, SBP_ARROWBTN, ABS_DOWNDISABLED, &rcArrow, NULL);
cairo_surface_destroy(surface);
}
gfxWindowsNativeDrawing::BeginNativeDrawing()
call HDC
gfxWindowsSurface::GetDCWithClip(gfxContext *ctx)
finally call cairo win32.
Chrome
Skia does not provide the transformation functionality from skia canvas to hdc, but the project chrome add a extension to skia and fulfill this functionality.
in skia/ext/bitmap_platform_device_win.cc:
HDC BitmapPlatformDevice::BitmapPlatformDeviceData::GetBitmapDC() {
}
which create a memory dc from the canvas internal bitmap.
So when paint, whether you need use native dc or the general cairo/skia canvas does not matter any more.
Sample code:
void TestChromeExt(HWND hwnd, HDC hdc)
{
RECT rc;
GetClientRect(hwnd, &rc);
skia::BitmapPlatformDevice* pBmpDevice = skia::BitmapPlatformDevice::Create(rc.right, rc.bottom, true);
skia::PlatformCanvas *pCanvas = new skia::PlatformCanvas(pBmpDevice);
pCanvas->clear(SK_ColorWHITE);
SkPaint paint;
paint.setColor(SK_ColorRED);
paint.setStrokeWidth(3);
paint.setStyle(SkPaint::kStroke_Style);
pCanvas->drawLine(0, 0, rc.right, rc.bottom, paint);
HDC memdc = skia::BeginPlatformPaint(pCanvas);
RECT rcArrow;
SetRect(&rcArrow, 100, 200, 120, 220);
DrawThemeBackground(OpenThemeData(NULL, L"SCROLLBAR"), memdc, SBP_ARROWBTN, ABS_DOWNDISABLED, &rcArrow, NULL);
skia::EndPlatformPaint(pCanvas);
skia::DrawToNativeContext(pCanvas, hdc, 0, 0, &rc);
}
For Windows, to ensure the native look and feel, when visual style is enabled, these browsers would use DrawThemeBackground
. However, when visual style is disabled( the classical mode is one) , they'll use DrawFrameControl
to draw the controls.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With