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_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; } }
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; } }
void wdAddArc(WD_PATHSINK* pSink, float cx, float cy, float fSweepAngle) { float ax = pSink->ptEnd.x; float ay = pSink->ptEnd.y; float xdiff = ax - cx; float ydiff = ay - cy; float r; float base_angle; r = sqrtf(xdiff * xdiff + ydiff * ydiff); /* Avoid undefined case for atan2f(). */ if(r < 0.001f) return; base_angle = atan2f(ydiff, xdiff) * (180.0f / WD_PI); if(d2d_enabled()) { dummy_ID2D1GeometrySink* s = (dummy_ID2D1GeometrySink*) pSink->pData; dummy_D2D1_ARC_SEGMENT arc_seg; d2d_setup_arc_segment(&arc_seg, cx, cy, r, r, base_angle, fSweepAngle); dummy_ID2D1GeometrySink_AddArc(s, &arc_seg); pSink->ptEnd.x = arc_seg.point.x; pSink->ptEnd.y = arc_seg.point.y; } else { float d = 2.0f * r; float sweep_rads = (base_angle + fSweepAngle) * (WD_PI / 180.0f); gdix_vtable->fn_AddPathArc(pSink->pData, cx - r, cy - r, d, d, base_angle, fSweepAngle); pSink->ptEnd.x = cx + r * cosf(sweep_rads); pSink->ptEnd.y = cy + r * sinf(sweep_rads); } }
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; } }
void wdDestroyCanvas(WD_HCANVAS hCanvas) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; /* Check for common logical errors. */ if(c->clip_layer != NULL || (c->flags & D2D_CANVASFLAG_RECTCLIP)) WD_TRACE("wdDestroyCanvas: Logical error: Canvas has dangling clip."); if(c->gdi_interop != NULL) WD_TRACE("wdDestroyCanvas: Logical error: Unpaired wdStartGdi()/wdEndGdi()."); dummy_ID2D1RenderTarget_Release(c->target); free(c); } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; gdix_vtable->fn_DeleteStringFormat(c->string_format); gdix_vtable->fn_DeletePen(c->pen); gdix_vtable->fn_DeleteGraphics(c->graphics); if(c->real_dc != NULL) { HBITMAP mem_bmp; mem_bmp = SelectObject(c->dc, c->orig_bmp); DeleteObject(mem_bmp); DeleteObject(c->dc); } free(c); } }
void wdDestroyCachedImage(WD_HCACHEDIMAGE hCachedImage) { if(d2d_enabled()) { ID2D1Bitmap_Release((ID2D1Bitmap*) hCachedImage); } else { gdix_vtable->fn_DeleteCachedBitmap((dummy_GpCachedBitmap*) hCachedImage); } }
void wdDestroyPath(WD_HPATH hPath) { if(d2d_enabled()) { dummy_ID2D1PathGeometry_Release((dummy_ID2D1PathGeometry*) hPath); } else { gdix_vtable->fn_DeletePath((dummy_GpPath*) hPath); } }
void wdDestroyBrush(WD_HBRUSH hBrush) { if(d2d_enabled()) { ID2D1Brush_Release((ID2D1Brush*) hBrush); } else { gdix_vtable->fn_DeleteBrush((void*) hBrush); } }
void wdEndFigure(WD_PATHSINK* pSink, BOOL bCloseFigure) { if(d2d_enabled()) { dummy_ID2D1GeometrySink_EndFigure((dummy_ID2D1GeometrySink*) pSink->pData, (bCloseFigure ? dummy_D2D1_FIGURE_END_CLOSED : dummy_D2D1_FIGURE_END_OPEN)); } else { if(bCloseFigure) gdix_vtable->fn_ClosePathFigure(pSink->pData); } }
void wdClosePathSink(WD_PATHSINK* pSink) { if(d2d_enabled()) { dummy_ID2D1GeometrySink* s = (dummy_ID2D1GeometrySink*) pSink->pData; dummy_ID2D1GeometrySink_Close(s); dummy_ID2D1GeometrySink_Release(s); } else { /* noop */ } }
void wdBeginPaint(WD_HCANVAS hCanvas) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; dummy_ID2D1RenderTarget_BeginDraw(c->target); } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; SetLayout(c->dc, 0); } }
void wdResetWorld(WD_HCANVAS hCanvas) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; d2d_reset_transform(c); } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; gdix_reset_transform(c); } }
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; } }
void wdSetSolidBrushColor(WD_HBRUSH hBrush, WD_COLOR color) { if(d2d_enabled()) { D2D_COLOR_F clr; d2d_init_color(&clr, color); ID2D1SolidColorBrush_SetColor((ID2D1SolidColorBrush*) hBrush, &clr); } else { dummy_GpSolidFill* b = (dummy_GpSolidFill*) hBrush; gdix_vtable->fn_SetSolidFillColor(b, (dummy_ARGB) color); } }
void wdClear(WD_HCANVAS hCanvas, WD_COLOR color) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; dummy_D2D1_COLOR_F clr; d2d_init_color(&clr, color); dummy_ID2D1RenderTarget_Clear(c->target, &clr); } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; gdix_vtable->fn_GraphicsClear(c->graphics, color); } }
void wdBeginFigure(WD_PATHSINK* pSink, float x, float y) { if(d2d_enabled()) { dummy_ID2D1GeometrySink* s = (dummy_ID2D1GeometrySink*) pSink->pData; dummy_D2D1_POINT_2F pt = { x, y }; dummy_ID2D1GeometrySink_BeginFigure(s, pt, dummy_D2D1_FIGURE_BEGIN_FILLED); } else { gdix_vtable->fn_StartPathFigure(pSink->pData); } pSink->ptEnd.x = x; pSink->ptEnd.y = y; }
void wdAddLine(WD_PATHSINK* pSink, float x, float y) { if(d2d_enabled()) { dummy_ID2D1GeometrySink* s = (dummy_ID2D1GeometrySink*) pSink->pData; dummy_D2D1_POINT_2F pt = { x, y }; dummy_ID2D1GeometrySink_AddLine(s, pt); } else { gdix_vtable->fn_AddPathLine(pSink->pData, pSink->ptEnd.x, pSink->ptEnd.y, x, y); } pSink->ptEnd.x = x; pSink->ptEnd.y = y; }
void wdTranslateWorld(WD_HCANVAS hCanvas, float dx, float dy) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; dummy_D2D1_MATRIX_3X2_F m; dummy_ID2D1RenderTarget_GetTransform(c->target, &m); m._31 += dx; m._32 += dy; dummy_ID2D1RenderTarget_SetTransform(c->target, &m); } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; gdix_vtable->fn_TranslateWorldTransform(c->graphics, dx, dy, dummy_MatrixOrderAppend); } }
void wdEndGdi(WD_HCANVAS hCanvas, HDC hDC) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; dummy_ID2D1GdiInteropRenderTarget_ReleaseDC(c->gdi_interop, NULL); dummy_ID2D1GdiInteropRenderTarget_Release(c->gdi_interop); c->gdi_interop = NULL; } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; if(c->rtl) SetLayout(hDC, 0); gdix_vtable->fn_ReleaseDC(c->graphics, hDC); } }
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; } }
void wdRotateWorld(WD_HCANVAS hCanvas, float cx, float cy, float fAngle) { if(d2d_enabled()) { d2d_canvas_t* c = (d2d_canvas_t*) hCanvas; dummy_D2D1_MATRIX_3X2_F m; float a_rads = fAngle * (WD_PI / 180.0f); float a_sin = sinf(a_rads); float a_cos = cosf(a_rads); m._11 = a_cos; m._12 = a_sin; m._21 = -a_sin; m._22 = a_cos; m._31 = cx - cx*a_cos + cy*a_sin; m._32 = cy - cx*a_sin - cy*a_cos; d2d_apply_transform(c, &m); } else { gdix_canvas_t* c = (gdix_canvas_t*) hCanvas; gdix_vtable->fn_TranslateWorldTransform(c->graphics, cx, cy, dummy_MatrixOrderPrepend); gdix_vtable->fn_RotateWorldTransform(c->graphics, fAngle, dummy_MatrixOrderPrepend); gdix_vtable->fn_TranslateWorldTransform(c->graphics, -cx, -cy, dummy_MatrixOrderPrepend); } }
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; } }
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 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; } }