Direct2D中的仿射变换

在本文中,将探讨如何使用Direct2D中的矩阵进行仿射变换。在进行任何需要变换的绘图之前,必须先设置好变换。本文的前提是了解如何设置RenderTarget。如果对RenderTarget一无所知,请先阅读有关RenderTarget的文章,然后再阅读本文。

文本格式

要在Direct2D中显示文本,首先需要创建IDWriteTextFormat。IDWriteTextFormat是一个在CreateDeviceIndependentResources()中创建的设备无关资源,该函数由OnInitDialog()或可能拥有的任何初始化函数调用一次。设备无关资源在Direct2D目标丢失时不需要重新创建。IDWriteTextFormat及其创建函数CreateTextFormat()将在未来的文本绘制教程中详细探讨。

以下是C++代码示例:

ComPtr m_TextFormat; void CD2DAffineTransformDlg::CreateDeviceIndependentResources() { HR(FactorySingleton::GetDWriteFactory()-> CreateTextFormat(L"Arial Black", nullptr, DWRITE_FONT_WEIGHT_ULTRA_BOLD, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 40, L"", m_TextFormat.ReleaseAndGetAddressOf())); }

翻译

在本节中,文本将沿y轴向下移动50像素。在用平移矩阵设置SetTransform()之前,必须用IdentityMatrix()调用它,以重置之前设置的任何矩阵。平移矩阵是从Matrix3x2F::Translation()创建的。Matrix3x2F::Translation()的2个参数是要移动的X和Y坐标的量。然后m_FillBrush设置为Direct2D预定义的黑色。可以选择其他预定义或自定义颜色。要定义一个自定义颜色在SetColor()中使用,给ColorF()4个浮点数,按RGBA顺序。然后调用m_Target上的DrawTextW绘制文本。

以下是C++代码示例:

CRect rectClient; GetClientRect(&rectClient); auto rect = RectF(0.0f, 0.0f, rectClient.Width(), rectClient.Height()); m_Target->SetTransform(D2D1::IdentityMatrix()); D2D1::Matrix3x2F trans = D2D1::Matrix3x2F::Translation(0, 50); m_Target->SetTransform(trans); m_FillBrush->SetColor(ColorF(ColorF::Black)); m_Target->DrawTextW((LPCTSTR)m_Text, m_Text.GetLength(), m_TextFormat.Get(), ▭, m_FillBrush.Get());

倾斜

接下来,将看到如何进行倾斜,使文本看起来像斜体,然后进行相同的平移。上一部分的GetClientRect()代码没有显示,因为它们没有变化。变换是通过矩阵乘法链式进行的。可以看到,矩阵乘法的顺序非常重要。矩阵乘法的顺序必须与期望的变换顺序相反。例如,希望倾斜是第一个变换,然后在矩阵乘法中,倾斜矩阵必须是最后一个操作数。反之亦然对于平移矩阵。请注意,倾斜矩阵是从Matrix3x2F::Skew()创建的。Matrix3x2F::Skew()的第一个2个参数是沿x轴和y轴倾斜的角度(度),最后一个参数是倾斜的中心点。

以下是C++代码示例:

m_Target->SetTransform(D2D1::IdentityMatrix()); D2D1::Matrix3x2F trans = D2D1::Matrix3x2F::Translation(0, 50); D2D1::Matrix3x2F skew = D2D1::Matrix3x2F::Skew(-10.0f, 0.0f, Point2F(rectClient.Width() / 2, rectClient.Height() / 2)); m_Target->SetTransform(trans * skew); m_FillBrush->SetColor(ColorF(ColorF::Black)); m_Target->DrawTextW((LPCTSTR)m_Text, m_Text.GetLength(), m_TextFormat.Get(), ▭, m_FillBrush.Get());

旋转

在本节中,文本向上旋转-10度。倾斜和平移必须在旋转之前执行,因此矩阵乘法是trans * rotate * skew。旋转矩阵是从Matrix3x2F::Rotation()创建的,其第一个参数是角度。可选的中心点参数默认为0,0,如果省略的话。

以下是C++代码示例:

m_Target->SetTransform(D2D1::IdentityMatrix()); D2D1::Matrix3x2F trans = D2D1::Matrix3x2F::Translation(0, 50); D2D1::Matrix3x2F rotate = D2D1::Matrix3x2F::Rotation(-10.0f); D2D1::Matrix3x2F skew = D2D1::Matrix3x2F::Skew(-10.0f, 0.0f, Point2F(rectClient.Width() / 2, rectClient.Height() / 2)); m_Target->SetTransform(trans * rotate * skew); m_FillBrush->SetColor(ColorF(ColorF::Black)); m_Target->DrawTextW((LPCTSTR)m_Text, m_Text.GetLength(), m_TextFormat.Get(), ▭, m_FillBrush.Get());

缩放

缩放通常用于在计算机绘图中实现放大和缩小。在本节的最后,将缩小文本绘制(使其变小)。缩放必须在所有其他变换之前执行,因此在矩阵乘法中是最后一个操作数。缩放矩阵是从Matrix3x2F::Scale()创建的,它有2个参数来指定在x轴和y轴上的缩放。

以下是C++代码示例:

m_Target->SetTransform(D2D1::IdentityMatrix()); D2D1::Matrix3x2F trans = D2D1::Matrix3x2F::Translation(0, 50); D2D1::Matrix3x2F rotate = D2D1::Matrix3x2F::Rotation(-10.0f); D2D1::Matrix3x2F skew = D2D1::Matrix3x2F::Skew(-10.0f, 0.0f, Point2F(rectClient.Width() / 2, rectClient.Height() / 2)); D2D1::Matrix3x2F scale = D2D1::Matrix3x2F::Scale(0.6f, 0.6f); m_Target->SetTransform(trans * rotate * skew * scale); m_FillBrush->SetColor(ColorF(ColorF::Black)); m_Target->DrawTextW((LPCTSTR)m_Text, m_Text.GetLength(), m_TextFormat.Get(), ▭, m_FillBrush.Get());

矩阵乘法的顺序

在“倾斜”部分提到,矩阵乘法的顺序必须与期望的变换顺序相反。一个更完整的解释应该紧随其后。看看由两个矩阵T和S表示的两个变换,其中T变换首先应用于V,然后是S变换。V是一个由要变换的笛卡尔坐标x和y组成的向量。S(T(V))。注意:矩阵乘法是非交换的,所以必须遵守乘法的顺序。尽管T首先应用,但S出现在方程中的第一个。ST != TS。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485