void DWriteContext::DrawText(HDC hdc, const WCHAR* text, int len, int x, int y, int w, int h, int cellWidth, COLORREF color) { HRESULT hr = S_OK; IDWriteBitmapRenderTarget *bmpRT = NULL; // Skip when any fonts are not set. if (mTextFormat == NULL) return; // Check possibility of zero divided error. if (cellWidth == 0 || mDpiScaleX == 0.0f || mDpiScaleY == 0.0f) return; if (SUCCEEDED(hr)) hr = mGdiInterop->CreateBitmapRenderTarget(hdc, w, h, &bmpRT); if (SUCCEEDED(hr)) { IDWriteTextLayout *textLayout = NULL; HDC memdc = bmpRT->GetMemoryDC(); BitBlt(memdc, 0, 0, w, h, hdc, x, y, SRCCOPY); hr = mDWriteFactory->CreateGdiCompatibleTextLayout( text, len, mTextFormat, PixelsToDipsX(w), PixelsToDipsY(h), mDpiScaleX, NULL, TRUE, &textLayout); if (SUCCEEDED(hr)) { DWRITE_TEXT_RANGE textRange = { 0, (UINT32)len }; textLayout->SetFontWeight(mFontWeight, textRange); textLayout->SetFontStyle(mFontStyle, textRange); } if (SUCCEEDED(hr)) { GdiTextRenderer *renderer = new GdiTextRenderer(bmpRT, mRenderingParams); GdiTextRendererContext data = { color, PixelsToDipsX(cellWidth), 0.0f }; textLayout->Draw(&data, renderer, 0, 0); SafeRelease(&renderer); } BitBlt(hdc, x, y, w, h, memdc, 0, 0, SRCCOPY); SafeRelease(&textLayout); } SafeRelease(&bmpRT); }
// MakeRectF // Converts left, top, right, bottom in pixels to a D2D rectangle in DIPs. D2D1_RECT_F MakeRectF(int left, int top, int right, int bottom) { D2D1_RECT_F result; result.left = PixelsToDipsX(left); result.top = PixelsToDipsY(top); result.right = PixelsToDipsX(right); result.bottom = PixelsToDipsY(bottom); return result; }
HRESULT DWriteRenderer::UpdateTextOrigin() { HRESULT hr = S_OK; if (textLayout_ != NULL) { // Get the text layout size. DWRITE_TEXT_METRICS metrics = {}; hr = textLayout_->GetMetrics(&metrics); // Center the text. textOriginX_ = (PixelsToDipsX(width_) - metrics.width) * 0.5f; textOriginY_ = (PixelsToDipsY(height_) - metrics.height) * 0.5f; } return hr; }
HRESULT D2DRenderer::UpdateTextOrigin() { HRESULT hr = S_OK; if (textLayout_ == NULL) return hr; // Get the text layout size. DWRITE_TEXT_METRICS metrics = {}; hr = textLayout_->GetMetrics(&metrics); // Center the text. textOrigin_ = D2D1::Point2F( (PixelsToDipsX(width_) - metrics.width) * 0.5f, (PixelsToDipsY(height_) - metrics.height) * 0.5f ); return hr; }
void SetTransform(HWND hwnd) { if (g_renderer != NULL) { // Compute the center of the client area in DIPs. RECT clientRect; GetClientRect(hwnd, &clientRect); float centerX = PixelsToDipsX(clientRect.right) * 0.5f;; float centerY = PixelsToDipsY(clientRect.bottom) * 0.5f; // Create a transform that rotates around the center point. DWRITE_MATRIX transform = MakeRotateTransform(float(g_degrees), centerX, centerY); // Add the current horizontal displacement. transform.dx += g_animationCurrentX; // Set the transform. g_renderer->SetTransform(transform); } }
HRESULT D2DRenderer::DrawMagnifier() { HRESULT hr = S_OK; if (!magnifier_.visible) return hr; // Get the bounding rectangles, in DIPs, of the magnifier and the focus area. D2D1_RECT_F magnifierRect = MakeRectF( magnifier_.magnifierPos.x, magnifier_.magnifierPos.y, magnifier_.magnifierPos.x + magnifier_.magnifierSize.cx, magnifier_.magnifierPos.y + magnifier_.magnifierSize.cy ); int const focusWidth = magnifier_.magnifierSize.cx / magnifier_.scale; int const focusHeight = magnifier_.magnifierSize.cy / magnifier_.scale; D2D1_RECT_F focusRect = MakeRectF( magnifier_.focusPos.x, magnifier_.focusPos.y, magnifier_.focusPos.x + focusWidth, magnifier_.focusPos.y + focusHeight ); // Branch depending on the magnifier type: // // * Vector means we scale up the text using a render transform. This is enabled only // for natural layout because GDI-compatible layouts are not resolution-independent. // // * Pixel means we render at normal size to an intermediate bitmap and then scale up // the pixels. This is the only other magnifier type implemented by the D2D renderer. // if (magnifier_.type == MagnifierInfo::Vector && measuringMode_ == DWRITE_MEASURING_MODE_NATURAL) { renderTarget_->FillRectangle(magnifierRect, backBrush_); // Clip to the magnifier rectangle. renderTarget_->PushAxisAlignedClip(magnifierRect, D2D1_ANTIALIAS_MODE_ALIASED); // Create a transform that translates and scales the focus rect to the magnifier rect. D2D1_MATRIX_3X2_F zoomTransform;; zoomTransform._11 = transform_.m11 * magnifier_.scale; zoomTransform._12 = transform_.m12 * magnifier_.scale; zoomTransform._21 = transform_.m21 * magnifier_.scale; zoomTransform._22 = transform_.m22 * magnifier_.scale; zoomTransform._31 = ((transform_.dx - focusRect.left) * magnifier_.scale) + magnifierRect.left; zoomTransform._32 = ((transform_.dy - focusRect.top) * magnifier_.scale) + magnifierRect.top; // Redraw the text layout using the zoom transform. renderTarget_->SetTransform(zoomTransform); renderTarget_->DrawTextLayout(textOrigin_, textLayout_, textBrush_); renderTarget_->SetTransform(g_identityMatrix); renderTarget_->PopAxisAlignedClip(); } else { // Create the bitmap render target if we haven't already. if (bitmapRenderTarget_ == NULL) { hr = renderTarget_->CreateCompatibleRenderTarget( D2D1::SizeF(PixelsToDipsX(focusWidth), PixelsToDipsY(focusHeight)), D2D1::SizeU(focusWidth, focusHeight), D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE), D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, &bitmapRenderTarget_ ); } if (SUCCEEDED(hr)) { if (renderingParams_ != NULL) { bitmapRenderTarget_->SetTextRenderingParams(renderingParams_); } D2D1_MATRIX_3X2_F bitmapTransform; memcpy(&bitmapTransform, &transform_, sizeof(bitmapTransform)); bitmapTransform._31 -= focusRect.left; bitmapTransform._32 -= focusRect.top; bitmapRenderTarget_->BeginDraw(); bitmapRenderTarget_->Clear(backColor_); bitmapRenderTarget_->SetTransform(bitmapTransform); bitmapRenderTarget_->DrawTextLayout(textOrigin_, textLayout_, textBrush_); hr = bitmapRenderTarget_->EndDraw(); } ID2D1Bitmap* bitmap = NULL; if (SUCCEEDED(hr)) { hr = bitmapRenderTarget_->GetBitmap(&bitmap); } if (SUCCEEDED(hr)) { renderTarget_->DrawBitmap( bitmap, magnifierRect, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR ); } SafeRelease(&bitmap); } renderTarget_->DrawRectangle(focusRect, borderBrush_, 2.0f); renderTarget_->DrawRectangle(magnifierRect, borderBrush_, 2.0f); return hr; }
HRESULT DWriteRenderer::PrepareMagnifier(HDC hdc) { HRESULT hr = S_OK; if (!magnifier_.visible) { SafeRelease(&magnifierTarget_); return hr; } // Determine the size and scale factor for the magnifier render target. In vector // mode we render using a scale transform. In all other modes we render at normal // size and then scale up the pixels afterwards. SIZE targetSize = magnifier_.magnifierSize; int targetScale = magnifier_.scale; if (magnifier_.type != MagnifierInfo::Vector) { targetSize.cx /= targetScale; targetSize.cy /= targetScale; targetScale = 1; } // Create a separate render target for the magnifier if we haven't already. if (SUCCEEDED(hr) && magnifierTarget_ == NULL) { IDWriteGdiInterop* gdiInterop = NULL; if (SUCCEEDED(hr)) { hr = g_dwriteFactory->GetGdiInterop(&gdiInterop); } if (SUCCEEDED(hr)) { hr = gdiInterop->CreateBitmapRenderTarget(hdc, targetSize.cx, targetSize.cy, &magnifierTarget_); } SafeRelease(&gdiInterop); } DWRITE_MATRIX zoomTransform;; if (SUCCEEDED(hr)) { // Clear the background. HDC hdcMagnifier = magnifierTarget_->GetMemoryDC(); SelectObject(hdcMagnifier, GetSysColorBrush(COLOR_WINDOW)); PatBlt(hdcMagnifier, 0, 0, magnifier_.magnifierSize.cx, magnifier_.magnifierSize.cy, PATCOPY); // Create a transform that translates and scales the focus rect to the origin of the magnifier target. float focusLeft = PixelsToDipsX(magnifier_.focusPos.x); float focusTop = PixelsToDipsY(magnifier_.focusPos.y); zoomTransform.m11 = transform_.m11 * targetScale; zoomTransform.m12 = transform_.m12 * targetScale; zoomTransform.m21 = transform_.m21 * targetScale; zoomTransform.m22 = transform_.m22 * targetScale; zoomTransform.dx = (transform_.dx - focusLeft) * targetScale; zoomTransform.dy = (transform_.dy - focusTop) * targetScale; } if (SUCCEEDED(hr)) { hr = magnifierTarget_->SetCurrentTransform(&zoomTransform); } return hr; }