Fix setting rectangular clipping region for Direct2D
If transformation matrix of wxGraphicsContext with Direct2D renderer is e.g. rotated then rectangular clipping region represented by layer created with ID2D1RenderTarget::PushAxisAlignedClip is invalid because this kind of layers create axis-aligned clipping regions which edges are always horizontal or vertical (not e.g. rotated). To take into account current transformation matrix when clipping region is set there is necessary to represent all clipping regions (even rectangular) by generic layers (ID2D1Layer) created with ID2D1RenderTarget::CreateLayer. Closes #17622
This commit is contained in:
@@ -3409,10 +3409,11 @@ private:
|
|||||||
|
|
||||||
ID2D1RenderTarget* GetRenderTarget() const;
|
ID2D1RenderTarget* GetRenderTarget() const;
|
||||||
|
|
||||||
|
void SetClipLayer(ID2D1Geometry* clipGeometry);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum LayerType
|
enum LayerType
|
||||||
{
|
{
|
||||||
CLIP_AXIS_ALIGNED_RECT,
|
|
||||||
CLIP_LAYER,
|
CLIP_LAYER,
|
||||||
OTHER_LAYER
|
OTHER_LAYER
|
||||||
};
|
};
|
||||||
@@ -3509,16 +3510,9 @@ wxD2DContext::~wxD2DContext()
|
|||||||
LayerData ld = m_layers.top();
|
LayerData ld = m_layers.top();
|
||||||
m_layers.pop();
|
m_layers.pop();
|
||||||
|
|
||||||
if ( ld.type == CLIP_AXIS_ALIGNED_RECT )
|
GetRenderTarget()->PopLayer();
|
||||||
{
|
ld.layer.reset();
|
||||||
GetRenderTarget()->PopAxisAlignedClip();
|
ld.geometry.reset();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GetRenderTarget()->PopLayer();
|
|
||||||
ld.layer.reset();
|
|
||||||
ld.geometry.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT result = GetRenderTarget()->EndDraw();
|
HRESULT result = GetRenderTarget()->EndDraw();
|
||||||
@@ -3536,13 +3530,29 @@ void wxD2DContext::Clip(const wxRegion& region)
|
|||||||
{
|
{
|
||||||
wxCOMPtr<ID2D1Geometry> clipGeometry = wxD2DConvertRegionToGeometry(m_direct2dFactory, region);
|
wxCOMPtr<ID2D1Geometry> clipGeometry = wxD2DConvertRegionToGeometry(m_direct2dFactory, region);
|
||||||
|
|
||||||
|
SetClipLayer(clipGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxD2DContext::Clip(wxDouble x, wxDouble y, wxDouble w, wxDouble h)
|
||||||
|
{
|
||||||
|
wxCOMPtr<ID2D1RectangleGeometry> clipGeometry;
|
||||||
|
HRESULT hr = m_direct2dFactory->CreateRectangleGeometry(
|
||||||
|
D2D1::RectF(x, y, x + w, y + h), &clipGeometry);
|
||||||
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
|
||||||
|
SetClipLayer(clipGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxD2DContext::SetClipLayer(ID2D1Geometry* clipGeometry)
|
||||||
|
{
|
||||||
wxCOMPtr<ID2D1Layer> clipLayer;
|
wxCOMPtr<ID2D1Layer> clipLayer;
|
||||||
HRESULT hr = GetRenderTarget()->CreateLayer(&clipLayer);
|
HRESULT hr = GetRenderTarget()->CreateLayer(&clipLayer);
|
||||||
wxCHECK_HRESULT_RET(hr);
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
|
||||||
LayerData ld;
|
LayerData ld;
|
||||||
ld.type = CLIP_LAYER;
|
ld.type = CLIP_LAYER;
|
||||||
ld.params = D2D1::LayerParameters(D2D1::InfiniteRect(), clipGeometry);
|
ld.params = D2D1::LayerParameters(D2D1::InfiniteRect(), clipGeometry,
|
||||||
|
wxD2DConvertAntialiasMode(m_antialias));
|
||||||
ld.layer = clipLayer;
|
ld.layer = clipLayer;
|
||||||
ld.geometry = clipGeometry;
|
ld.geometry = clipGeometry;
|
||||||
|
|
||||||
@@ -3551,19 +3561,6 @@ void wxD2DContext::Clip(const wxRegion& region)
|
|||||||
m_layers.push(ld);
|
m_layers.push(ld);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxD2DContext::Clip(wxDouble x, wxDouble y, wxDouble w, wxDouble h)
|
|
||||||
{
|
|
||||||
LayerData ld;
|
|
||||||
ld.type = CLIP_AXIS_ALIGNED_RECT;
|
|
||||||
ld.params = D2D1::LayerParameters(D2D1::RectF(x, y, x + w, y + h),
|
|
||||||
NULL, D2D1_ANTIALIAS_MODE_ALIASED);
|
|
||||||
|
|
||||||
GetRenderTarget()->PushAxisAlignedClip(ld.params.contentBounds,
|
|
||||||
D2D1_ANTIALIAS_MODE_ALIASED);
|
|
||||||
// Store layer parameters.
|
|
||||||
m_layers.push(ld);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxD2DContext::ResetClip()
|
void wxD2DContext::ResetClip()
|
||||||
{
|
{
|
||||||
wxStack<LayerData> layersToRestore;
|
wxStack<LayerData> layersToRestore;
|
||||||
@@ -3573,12 +3570,6 @@ void wxD2DContext::ResetClip()
|
|||||||
LayerData ld = m_layers.top();
|
LayerData ld = m_layers.top();
|
||||||
m_layers.pop();
|
m_layers.pop();
|
||||||
|
|
||||||
if ( ld.type == CLIP_AXIS_ALIGNED_RECT )
|
|
||||||
{
|
|
||||||
GetRenderTarget()->PopAxisAlignedClip();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ld.type == CLIP_LAYER )
|
if ( ld.type == CLIP_LAYER )
|
||||||
{
|
{
|
||||||
GetRenderTarget()->PopLayer();
|
GetRenderTarget()->PopLayer();
|
||||||
@@ -3722,13 +3713,6 @@ void wxD2DContext::EndLayer()
|
|||||||
LayerData ld = m_layers.top();
|
LayerData ld = m_layers.top();
|
||||||
m_layers.pop();
|
m_layers.pop();
|
||||||
|
|
||||||
if ( ld.type == CLIP_AXIS_ALIGNED_RECT )
|
|
||||||
{
|
|
||||||
GetRenderTarget()->PopAxisAlignedClip();
|
|
||||||
layersToRestore.push(ld);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ld.type == CLIP_LAYER )
|
if ( ld.type == CLIP_LAYER )
|
||||||
{
|
{
|
||||||
GetRenderTarget()->PopLayer();
|
GetRenderTarget()->PopLayer();
|
||||||
@@ -3754,12 +3738,7 @@ void wxD2DContext::EndLayer()
|
|||||||
LayerData ld = layersToRestore.top();
|
LayerData ld = layersToRestore.top();
|
||||||
layersToRestore.pop();
|
layersToRestore.pop();
|
||||||
|
|
||||||
if ( ld.type == CLIP_AXIS_ALIGNED_RECT )
|
if ( ld.type == CLIP_LAYER )
|
||||||
{
|
|
||||||
GetRenderTarget()->PushAxisAlignedClip(ld.params.contentBounds,
|
|
||||||
ld.params.maskAntialiasMode);
|
|
||||||
}
|
|
||||||
else if ( ld.type == CLIP_LAYER )
|
|
||||||
{
|
{
|
||||||
GetRenderTarget()->PushLayer(ld.params, ld.layer);
|
GetRenderTarget()->PushLayer(ld.params, ld.layer);
|
||||||
}
|
}
|
||||||
@@ -4093,14 +4072,7 @@ void wxD2DContext::Flush()
|
|||||||
LayerData ld = m_layers.top();
|
LayerData ld = m_layers.top();
|
||||||
m_layers.pop();
|
m_layers.pop();
|
||||||
|
|
||||||
if ( ld.type == CLIP_AXIS_ALIGNED_RECT )
|
GetRenderTarget()->PopLayer();
|
||||||
{
|
|
||||||
GetRenderTarget()->PopAxisAlignedClip();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GetRenderTarget()->PopLayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save layer data.
|
// Save layer data.
|
||||||
layersToRestore.push(ld);
|
layersToRestore.push(ld);
|
||||||
@@ -4123,15 +4095,8 @@ void wxD2DContext::Flush()
|
|||||||
LayerData ld = layersToRestore.top();
|
LayerData ld = layersToRestore.top();
|
||||||
layersToRestore.pop();
|
layersToRestore.pop();
|
||||||
|
|
||||||
if ( ld.type == CLIP_AXIS_ALIGNED_RECT )
|
GetRenderTarget()->PushLayer(ld.params, ld.layer);
|
||||||
{
|
|
||||||
GetRenderTarget()->PushAxisAlignedClip(ld.params.contentBounds,
|
|
||||||
ld.params.maskAntialiasMode);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GetRenderTarget()->PushLayer(ld.params, ld.layer);
|
|
||||||
}
|
|
||||||
// Store layer parameters.
|
// Store layer parameters.
|
||||||
m_layers.push(ld);
|
m_layers.push(ld);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user