예제 #1
0
void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
{
	if (!BeginTargetDraw()) return;

	Gdiplus::Color color;
	brush.GetColor(&color);

	Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
	HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
	if (SUCCEEDED(hr))
	{
		TextFormatD2D& formatD2D = (TextFormatD2D&)format;
		const bool right = formatD2D.GetHorizontalAlignment() == Gfx::HorizontalAlignment::Right;

		formatD2D.CreateLayout(str, strLen, rect.Width, rect.Height);

		m_Target->DrawTextLayout(
			D2D1::Point2F(right ? rect.X - 2 : rect.X + 2.0f, rect.Y - 1.0f),
			formatD2D.m_TextLayout.Get(),
			solidBrush.Get());
	}
}
예제 #2
0
void CanvasD2D::DrawMaskedBitmap(Gdiplus::Bitmap* bitmap, Gdiplus::Bitmap* maskBitmap, const Gdiplus::Rect& dstRect,
	const Gdiplus::Rect& srcRect, const Gdiplus::Rect& srcRect2)
{
	if (!BeginTargetDraw()) return;

	auto rDst = ToRectF(dstRect);
	auto rSrc = ToRectF(srcRect);

	Util::WICBitmapLockGDIP* bitmapLock = new Util::WICBitmapLockGDIP();
	Gdiplus::Rect lockRect(srcRect2);
	Gdiplus::Status status = bitmap->LockBits(
		&lockRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, bitmapLock->GetBitmapData());
	if (status == Gdiplus::Ok)
	{
		D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(
			D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED));
		Microsoft::WRL::ComPtr<ID2D1Bitmap> d2dBitmap;
		HRESULT hr = m_Target->CreateSharedBitmap(
			__uuidof(IWICBitmapLock), bitmapLock, &props, d2dBitmap.GetAddressOf());
		if (SUCCEEDED(hr))
		{
			// Create bitmap brush from original |bitmap|.
			Microsoft::WRL::ComPtr<ID2D1BitmapBrush> brush;
			D2D1_BITMAP_BRUSH_PROPERTIES propertiesXClampYClamp = D2D1::BitmapBrushProperties(
				D2D1_EXTEND_MODE_CLAMP,
				D2D1_EXTEND_MODE_CLAMP,
				D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);

			// "Move" and "scale" the |bitmap| to match the destination.
			D2D1_MATRIX_3X2_F translate = D2D1::Matrix3x2F::Translation(rDst.left, rDst.top);
			D2D1_MATRIX_3X2_F scale = D2D1::Matrix3x2F::Scale(
				D2D1::SizeF((rDst.right - rDst.left) / (float)srcRect2.Width, (rDst.bottom - rDst.top) / (float)srcRect2.Height));
			D2D1_BRUSH_PROPERTIES brushProps = D2D1::BrushProperties(1.0F, scale * translate);

			hr = m_Target->CreateBitmapBrush(
				d2dBitmap.Get(),
				propertiesXClampYClamp,
				brushProps,
				brush.GetAddressOf());

			// Load the |maskBitmap| and use the bitmap brush to "fill" its contents.
			// Note: The image must be aliased when applying the opacity mask.
			if (SUCCEEDED(hr))
			{
				Util::WICBitmapLockGDIP* maskBitmapLock = new Util::WICBitmapLockGDIP();
				Gdiplus::Rect maskLockRect(0, 0, maskBitmap->GetWidth(), maskBitmap->GetHeight());
				status = maskBitmap->LockBits(
					&maskLockRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, maskBitmapLock->GetBitmapData());
				if (status == Gdiplus::Ok)
				{
					D2D1_BITMAP_PROPERTIES maskProps = D2D1::BitmapProperties(
						D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED));
					Microsoft::WRL::ComPtr<ID2D1Bitmap> d2dMaskBitmap;
					hr = m_Target->CreateSharedBitmap(
						__uuidof(IWICBitmapLock), maskBitmapLock, &props, d2dMaskBitmap.GetAddressOf());
					if (SUCCEEDED(hr))
					{
						m_Target->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); // required
						m_Target->FillOpacityMask(
							d2dMaskBitmap.Get(),
							brush.Get(),
							D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
							&rDst,
							&rSrc);
						m_Target->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
					}

					maskBitmap->UnlockBits(bitmapLock->GetBitmapData());
				}

				maskBitmapLock->Release();
			}
		}

		bitmap->UnlockBits(bitmapLock->GetBitmapData());
	}

	bitmapLock->Release();
}
예제 #3
0
void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect,
	const Gdiplus::SolidBrush& brush, bool applyInlineFormatting)
{
	if (!BeginTargetDraw()) return;

	Gdiplus::Color color;
	brush.GetColor(&color);

	Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
	HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
	if (FAILED(hr)) return;

	TextFormatD2D& formatD2D = (TextFormatD2D&)format;
	if (!formatD2D.CreateLayout(
		m_Target.Get(), str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return;

	D2D1_POINT_2F drawPosition;
	drawPosition.x = [&]()
	{
		if (!m_AccurateText)
		{
			const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f;
			switch (formatD2D.GetHorizontalAlignment())
			{
			case HorizontalAlignment::Left: return rect.X + xOffset;
			case HorizontalAlignment::Right: return rect.X - xOffset;
			}
		}

		return rect.X;
	} ();

	drawPosition.y = [&]()
	{
		// GDI+ compatibility.
		float yPos = rect.Y - formatD2D.m_LineGap;
		switch (formatD2D.GetVerticalAlignment())
		{
		case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break;
		case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break;
		}

		return yPos;
	} ();

	if (formatD2D.m_Trimming)
	{
		D2D1_RECT_F clipRect = ToRectF(rect);

		if (m_CanUseAxisAlignClip)
		{
			m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
		}
		else
		{
			const D2D1_LAYER_PARAMETERS layerParams =
				D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED);
			m_Target->PushLayer(layerParams, nullptr);
		}
	}

	// When different "effects" are used with inline coloring options, we need to
	// remove the previous inline coloring, then reapply them (if needed) - instead
	// of destroying/recreating the text layout.
	formatD2D.ResetInlineColoring(solidBrush.Get(), strLen);
	if (applyInlineFormatting)
	{
		formatD2D.ApplyInlineColoring(m_Target.Get(), &drawPosition);
	}

	m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());

	if (applyInlineFormatting)
	{
		// Inline gradients require the drawing position, so in case that position
		// changes, we need a way to reset it after drawing time so on the next
		// iteration it will know the correct position.
		formatD2D.ResetGradientPosition(&drawPosition);
	}

	if (formatD2D.m_Trimming)
	{
		if (m_CanUseAxisAlignClip)
		{
			m_Target->PopAxisAlignedClip();
		}
		else
		{
			m_Target->PopLayer();
		}
	}
}
예제 #4
0
void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
{
    if (!BeginTargetDraw()) return;

    Gdiplus::Color color;
    brush.GetColor(&color);

    Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
    HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
    if (FAILED(hr)) return;

    TextFormatD2D& formatD2D = (TextFormatD2D&)format;
    if (!formatD2D.CreateLayout(
                str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return;

    D2D1_POINT_2F drawPosition;
    drawPosition.x = [&]()
    {
        if (!m_AccurateText)
        {
            const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f;
            switch (formatD2D.GetHorizontalAlignment())
            {
            case HorizontalAlignment::Left:
                return rect.X + xOffset;
            case HorizontalAlignment::Right:
                return rect.X - xOffset;
            }
        }

        return rect.X;
    } ();

    drawPosition.y = [&]()
    {
        // GDI+ compatibility.
        float yPos = rect.Y - formatD2D.m_LineGap;
        switch (formatD2D.GetVerticalAlignment())
        {
        case VerticalAlignment::Bottom:
            yPos -= formatD2D.m_ExtraHeight;
            break;
        case VerticalAlignment::Center:
            yPos -= formatD2D.m_ExtraHeight / 2;
            break;
        }

        return yPos;
    } ();

    if (formatD2D.m_Trimming)
    {
        D2D1_RECT_F clipRect = ToRectF(rect);

        if (m_CanUseAxisAlignClip)
        {
            m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
        }
        else
        {
            const D2D1_LAYER_PARAMETERS layerParams =
                D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED);
            m_Target->PushLayer(layerParams, nullptr);
        }
    }

    m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());

    if (formatD2D.m_Trimming)
    {
        if (m_CanUseAxisAlignClip)
        {
            m_Target->PopAxisAlignedClip();
        }
        else
        {
            m_Target->PopLayer();
        }
    }
}