Exemplo n.º 1
0
    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;
}