HDC wdStartGdi(WD_HCANVAS hCanvas, BOOL bKeepContents) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; dummy_ID2D1GdiInteropRenderTarget* gdi_interop; dummy_D2D1_DC_INITIALIZE_MODE init_mode; HRESULT hr; HDC dc; hr = dummy_ID2D1RenderTarget_QueryInterface(c->target, &dummy_IID_ID2D1GdiInteropRenderTarget, (void**) &gdi_interop); if(FAILED(hr)) { WD_TRACE_HR("wdStartGdi: ID2D1RenderTarget::" "QueryInterface(IID_ID2D1GdiInteropRenderTarget) failed."); return NULL; } init_mode = (bKeepContents ? dummy_D2D1_DC_INITIALIZE_MODE_COPY : dummy_D2D1_DC_INITIALIZE_MODE_CLEAR); hr = dummy_ID2D1GdiInteropRenderTarget_GetDC(gdi_interop, init_mode, &dc); if(FAILED(hr)) { WD_TRACE_HR("wdStartGdi: ID2D1GdiInteropRenderTarget::GetDC() failed."); dummy_ID2D1GdiInteropRenderTarget_Release(gdi_interop); return NULL; } c->gdi_interop = gdi_interop; if(c->flags & D2D_CANVASFLAG_RTL) SetLayout(dc, LAYOUT_RTL); return dc; } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; int status; HDC dc; status = gdix_vtable->fn_GetDC(c->graphics, &dc); if(status != 0) { WD_TRACE_ERR_("wdStartGdi: GdipGetDC() failed.", status); return NULL; } SetLayout(dc, c->dc_layout); if(c->dc_layout & LAYOUT_RTL) SetViewportOrgEx(dc, c->x + c->cx - (c->width-1), -c->y, NULL); return dc; } }
WD_HPATH wdCreatePath(WD_HCANVAS hCanvas) { if(d2d_enabled()) { dummy_ID2D1PathGeometry* g; HRESULT hr; wd_lock(); hr = dummy_ID2D1Factory_CreatePathGeometry(d2d_factory, &g); wd_unlock(); if(FAILED(hr)) { WD_TRACE_HR("wdCreatePath: " "ID2D1Factory::CreatePathGeometry() failed."); return NULL; } return (WD_HPATH) g; } else { dummy_GpPath* p; int status; status = gdix_vtable->fn_CreatePath(dummy_FillModeAlternate, &p); if(status != 0) { WD_TRACE("wdCreatePath: GdipCreatePath() failed. [%d]", status); return NULL; } return (WD_HPATH) p; } }
BOOL wdEndPaint(WD_HCANVAS hCanvas) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; HRESULT hr; d2d_reset_clip(c); hr = dummy_ID2D1RenderTarget_EndDraw(c->target, NULL, NULL); if(FAILED(hr)) { if(hr != D2DERR_RECREATE_TARGET) WD_TRACE_HR("wdEndPaint: ID2D1RenderTarget::EndDraw() failed."); return FALSE; } return TRUE; } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; /* If double-buffering, blit the memory DC to the display DC. */ if(c->real_dc != NULL) BitBlt(c->real_dc, c->x, c->y, c->cx, c->cy, c->dc, 0, 0, SRCCOPY); SetLayout(c->real_dc, c->dc_layout); /* For GDI+, disable caching. */ return FALSE; } }
WD_HBRUSH wdCreateSolidBrush(WD_HCANVAS hCanvas, WD_COLOR color) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; ID2D1SolidColorBrush* b; D2D_COLOR_F clr; HRESULT hr; d2d_init_color(&clr, color); hr = ID2D1RenderTarget_CreateSolidColorBrush( c->target, &clr, NULL, &b); if(FAILED(hr)) { WD_TRACE_HR("wdCreateSolidBrush: " "ID2D1RenderTarget::CreateSolidColorBrush() failed."); return NULL; } return (WD_HBRUSH) b; } else { dummy_GpSolidFill* b; int status; status = gdix_vtable->fn_CreateSolidFill(color, &b); if(status != 0) { WD_TRACE("wdCreateSolidBrush: " "GdipCreateSolidFill() failed. [%d]", status); return NULL; } return (WD_HBRUSH) b; } }
WD_HCACHEDIMAGE wdCreateCachedImage(WD_HCANVAS hCanvas, WD_HIMAGE hImage) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; ID2D1Bitmap* b; HRESULT hr; hr = ID2D1RenderTarget_CreateBitmapFromWicBitmap(c->target, (IWICBitmapSource*) hImage, NULL, &b); if(FAILED(hr)) { WD_TRACE_HR("wdCreateCachedImage: " "ID2D1RenderTarget::CreateBitmapFromWicBitmap() failed."); return NULL; } return (WD_HCACHEDIMAGE) b; } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; dummy_GpCachedBitmap* cb; int status; status = gdix_vtable->fn_CreateCachedBitmap((dummy_GpImage*) hImage, c->graphics, &cb); if(status != 0) { WD_TRACE("wdCreateCachedImage: " "GdipCreateCachedBitmap() failed. [%d]", status); return NULL; } return (WD_HCACHEDIMAGE) cb; } }
BOOL wdResizeCanvas(WD_HCANVAS hCanvas, UINT uWidth, UINT uHeight) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; if(c->type == D2D_CANVASTYPE_HWND) { dummy_D2D1_SIZE_U size = { uWidth, uHeight }; HRESULT hr; hr = dummy_ID2D1HwndRenderTarget_Resize(c->hwnd_target, &size); if(FAILED(hr)) { WD_TRACE_HR("wdResizeCanvas: " "ID2D1HwndRenderTarget_Resize() failed."); return FALSE; } /* In RTL mode, we have to update the transformation matrix * accordingly. */ if(c->flags & D2D_CANVASFLAG_RTL) { dummy_D2D1_MATRIX_3X2_F m; dummy_ID2D1RenderTarget_GetTransform(c->target, &m); m._31 = m._11 * (float)(uWidth - c->width); m._32 = m._12 * (float)(uWidth - c->width); dummy_ID2D1RenderTarget_SetTransform(c->target, &m); c->width = uWidth; } return TRUE; } else { /* Operation not supported. */ WD_TRACE("wdResizeCanvas: Not supported (not ID2D1HwndRenderTarget)."); return FALSE; } } else { /* Actually we should never be here as GDI+ back-end never allows * caching of the canvas so there is no need to ever resize it. */ WD_TRACE("wdResizeCanvas: Not supported (GDI+ back-end)."); return FALSE; } }
BOOL wdOpenPathSink(WD_PATHSINK* pSink, WD_HPATH hPath) { if(d2d_enabled()) { dummy_ID2D1PathGeometry* g = (dummy_ID2D1PathGeometry*) hPath; dummy_ID2D1GeometrySink* s; HRESULT hr; hr = dummy_ID2D1PathGeometry_Open(g, &s); if(FAILED(hr)) { WD_TRACE_HR("wdOpenPathSink: ID2D1PathGeometry::Open() failed."); return FALSE; } pSink->pData = (void*) s; return TRUE; } else { /* GDI+ doesn't have any concept of path sink as Direct2D does, it * operates directly with the path object. */ pSink->pData = (void*) hPath; return TRUE; } }
WD_HCANVAS wdCreateCanvasWithHDC(HDC hDC, const RECT* pRect, DWORD dwFlags) { if(d2d_enabled()) { dummy_D2D1_RENDER_TARGET_PROPERTIES props = { dummy_D2D1_RENDER_TARGET_TYPE_DEFAULT, { dummy_DXGI_FORMAT_B8G8R8A8_UNORM, dummy_D2D1_ALPHA_MODE_PREMULTIPLIED }, 0.0f, 0.0f, ((dwFlags & WD_CANVAS_NOGDICOMPAT) ? 0 : dummy_D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE), dummy_D2D1_FEATURE_LEVEL_DEFAULT }; d2d_canvas_t* c; dummy_ID2D1DCRenderTarget* target; HRESULT hr; wd_lock(); hr = dummy_ID2D1Factory_CreateDCRenderTarget(d2d_factory, &props, &target); wd_unlock(); if(FAILED(hr)) { WD_TRACE_HR("wdCreateCanvasWithHDC: " "ID2D1Factory::CreateDCRenderTarget() failed."); goto err_CreateDCRenderTarget; } hr = dummy_ID2D1DCRenderTarget_BindDC(target, hDC, pRect); if(FAILED(hr)) { WD_TRACE_HR("wdCreateCanvasWithHDC: " "ID2D1Factory::BindDC() failed."); goto err_BindDC; } c = d2d_canvas_alloc((dummy_ID2D1RenderTarget*)target, D2D_CANVASTYPE_DC, pRect->right - pRect->left, (dwFlags & WD_CANVAS_LAYOUTRTL)); if(c == NULL) { WD_TRACE("wdCreateCanvasWithHDC: d2d_canvas_alloc() failed."); goto err_d2d_canvas_alloc; } /* make sure text anti-aliasing is clear type */ dummy_ID2D1RenderTarget_SetTextAntialiasMode(c->target, dummy_D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); return (WD_HCANVAS) c; err_d2d_canvas_alloc: err_BindDC: dummy_ID2D1RenderTarget_Release((dummy_ID2D1RenderTarget*)target); err_CreateDCRenderTarget: return NULL; } else { BOOL use_doublebuffer = (dwFlags & WD_CANVAS_DOUBLEBUFFER); gdix_canvas_t* c; c = gdix_canvas_alloc(hDC, (use_doublebuffer ? pRect : NULL), pRect->right - pRect->left, (dwFlags & WD_CANVAS_LAYOUTRTL)); if(c == NULL) { WD_TRACE("wdCreateCanvasWithHDC: gdix_canvas_alloc() failed."); return NULL; } return (WD_HCANVAS) c; } }
void wdSetClip(WD_HCANVAS hCanvas, const WD_RECT* pRect, const WD_HPATH hPath) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; d2d_reset_clip(c); if(hPath != NULL) { dummy_ID2D1PathGeometry* g = (dummy_ID2D1PathGeometry*) hPath; dummy_D2D1_LAYER_PARAMETERS layer_params; HRESULT hr; hr = dummy_ID2D1RenderTarget_CreateLayer(c->target, NULL, &c->clip_layer); if(FAILED(hr)) { WD_TRACE_HR("wdSetClip: ID2D1RenderTarget::CreateLayer() failed."); return; } if(pRect != NULL) { layer_params.contentBounds.left = pRect->x0; layer_params.contentBounds.top = pRect->y0; layer_params.contentBounds.right = pRect->x1; layer_params.contentBounds.bottom = pRect->y1; } else { layer_params.contentBounds.left = FLT_MIN; layer_params.contentBounds.top = FLT_MIN; layer_params.contentBounds.right = FLT_MAX; layer_params.contentBounds.bottom = FLT_MAX; } layer_params.geometricMask = (dummy_ID2D1Geometry*) g; layer_params.maskAntialiasMode = dummy_D2D1_ANTIALIAS_MODE_PER_PRIMITIVE; layer_params.maskTransform._11 = 1.0f; layer_params.maskTransform._12 = 0.0f; layer_params.maskTransform._21 = 0.0f; layer_params.maskTransform._22 = 1.0f; layer_params.maskTransform._31 = 0.0f; layer_params.maskTransform._32 = 0.0f; layer_params.opacity = 1.0f; layer_params.opacityBrush = NULL; layer_params.layerOptions = dummy_D2D1_LAYER_OPTIONS_NONE; dummy_ID2D1RenderTarget_PushLayer(c->target, &layer_params, c->clip_layer); } else if(pRect != NULL) { dummy_ID2D1RenderTarget_PushAxisAlignedClip(c->target, (const dummy_D2D1_RECT_F*) pRect, dummy_D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); c->flags |= D2D_CANVASFLAG_RECTCLIP; } } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; int mode; if(pRect == NULL && hPath == NULL) { gdix_vtable->fn_ResetClip(c->graphics); return; } mode = dummy_CombineModeReplace; if(pRect != NULL) { gdix_vtable->fn_SetClipRect(c->graphics, pRect->x0, pRect->y0, pRect->x1, pRect->y1, mode); mode = dummy_CombineModeIntersect; } if(hPath != NULL) gdix_vtable->fn_SetClipPath(c->graphics, (void*) hPath, mode); } }
WD_HCANVAS wdCreateCanvasWithPaintStruct(HWND hWnd, PAINTSTRUCT* pPS, DWORD dwFlags) { RECT rect; GetClientRect(hWnd, &rect); if(d2d_enabled()) { dummy_D2D1_RENDER_TARGET_PROPERTIES props = { dummy_D2D1_RENDER_TARGET_TYPE_DEFAULT, { dummy_DXGI_FORMAT_B8G8R8A8_UNORM, dummy_D2D1_ALPHA_MODE_PREMULTIPLIED }, 0.0f, 0.0f, ((dwFlags & WD_CANVAS_NOGDICOMPAT) ? 0 : dummy_D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE), dummy_D2D1_FEATURE_LEVEL_DEFAULT }; dummy_D2D1_HWND_RENDER_TARGET_PROPERTIES props2; d2d_canvas_t* c; dummy_ID2D1HwndRenderTarget* target; HRESULT hr; props2.hwnd = hWnd; props2.pixelSize.width = rect.right - rect.left; props2.pixelSize.height = rect.bottom - rect.top; props2.presentOptions = dummy_D2D1_PRESENT_OPTIONS_NONE; wd_lock(); /* Note ID2D1HwndRenderTarget is implicitly double-buffered. */ hr = dummy_ID2D1Factory_CreateHwndRenderTarget(d2d_factory, &props, &props2, &target); wd_unlock(); if(FAILED(hr)) { WD_TRACE_HR("wdCreateCanvasWithPaintStruct: " "ID2D1Factory::CreateHwndRenderTarget() failed."); return NULL; } c = d2d_canvas_alloc((dummy_ID2D1RenderTarget*)target, D2D_CANVASTYPE_HWND, rect.right, (dwFlags & WD_CANVAS_LAYOUTRTL)); if(c == NULL) { WD_TRACE("wdCreateCanvasWithPaintStruct: d2d_canvas_alloc() failed."); dummy_ID2D1RenderTarget_Release((dummy_ID2D1RenderTarget*)target); return NULL; } /* make sure text anti-aliasing is clear type */ dummy_ID2D1RenderTarget_SetTextAntialiasMode(c->target, dummy_D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); return (WD_HCANVAS) c; } else { BOOL use_doublebuffer = (dwFlags & WD_CANVAS_DOUBLEBUFFER); gdix_canvas_t* c; c = gdix_canvas_alloc(pPS->hdc, (use_doublebuffer ? &pPS->rcPaint : NULL), rect.right, (dwFlags & WD_CANVAS_LAYOUTRTL)); if(c == NULL) { WD_TRACE("wdCreateCanvasWithPaintStruct: gdix_canvas_alloc() failed."); return NULL; } return (WD_HCANVAS) c; } }