Kaydet (Commit) 7eb8f82a authored tarafından Caolán McNamara's avatar Caolán McNamara Kaydeden (comit) Miklos Vajna

Resolves: tdf#92687 implement drawPolyPolygon via cairo

modeled on the quartz impl

(cherry picked from commit 742da70e)

Change-Id: I2f6776c14c7350954932df2bffcca36172f13473
Reviewed-on: https://gerrit.libreoffice.org/20083Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
Tested-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
üst 6213ce4a
......@@ -28,6 +28,7 @@
#include <basegfx/range/b2drange.hxx>
#include <basegfx/range/b2ibox.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basebmp/scanlineformats.hxx>
......@@ -134,6 +135,27 @@ void SvpSalGraphics::clipRegion(cairo_t* cr)
cairo_clip(cr);
}
}
namespace
{
cairo_rectangle_int_t getFillDamage(cairo_t* cr)
{
cairo_rectangle_int_t extents;
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1;
cairo_region_t *region = cairo_region_create_rectangle(&extents);
cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1;
cairo_region_intersect_rectangle(region, &extents);
cairo_region_get_extents(region, &extents);
cairo_region_destroy(region);
return extents;
}
}
#endif
......@@ -144,7 +166,10 @@ bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight,
#if ENABLE_CAIRO_CANVAS
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
if (m_bUseLineColor || !m_bUseFillColor)
return bRet;
{
SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawAlphaRect case");
return false;
}
cairo_t* cr = createCairoContext(m_aDevice);
if (!cr)
......@@ -165,24 +190,10 @@ bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight,
fTransparency);
cairo_rectangle(cr, nX, nY, nWidth, nHeight);
cairo_rectangle_int_t extents;
basebmp::IBitmapDeviceDamageTrackerSharedPtr xDamageTracker(m_aDevice->getDamageTracker());
if (xDamageTracker)
{
double x1, y1, x2, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1;
cairo_region_t *region = cairo_region_create_rectangle(&extents);
cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1;
cairo_region_intersect_rectangle(region, &extents);
cairo_region_get_extents(region, &extents);
cairo_region_destroy(region);
}
extents = getFillDamage(cr);
cairo_fill(cr);
......@@ -644,10 +655,118 @@ bool SvpSalGraphics::drawPolyPolygonBezier( sal_uInt32,
return false;
}
bool SvpSalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
static void AddPolygonToPath(cairo_t* cr, const basegfx::B2DPolygon& rPolygon, bool bClosePath)
{
// TODO: maybe BaseBmp can draw B2DPolyPolygons directly
return false;
// short circuit if there is nothing to do
const int nPointCount = rPolygon.count();
if( nPointCount <= 0 )
{
return;
}
const bool bHasCurves = rPolygon.areControlPointsUsed();
for( int nPointIdx = 0, nPrevIdx = 0;; nPrevIdx = nPointIdx++ )
{
int nClosedIdx = nPointIdx;
if( nPointIdx >= nPointCount )
{
// prepare to close last curve segment if needed
if( bClosePath && (nPointIdx == nPointCount) )
{
nClosedIdx = 0;
}
else
{
break;
}
}
basegfx::B2DPoint aPoint = rPolygon.getB2DPoint( nClosedIdx );
if( !nPointIdx )
{
// first point => just move there
cairo_move_to(cr, aPoint.getX(), aPoint.getY());
continue;
}
bool bPendingCurve = false;
if( bHasCurves )
{
bPendingCurve = rPolygon.isNextControlPointUsed( nPrevIdx );
bPendingCurve |= rPolygon.isPrevControlPointUsed( nClosedIdx );
}
if( !bPendingCurve ) // line segment
{
cairo_line_to(cr, aPoint.getX(), aPoint.getY());
}
else // cubic bezier segment
{
basegfx::B2DPoint aCP1 = rPolygon.getNextControlPoint( nPrevIdx );
basegfx::B2DPoint aCP2 = rPolygon.getPrevControlPoint( nClosedIdx );
cairo_curve_to(cr, aCP1.getX(), aCP1.getY(), aCP2.getX(), aCP2.getY(),
aPoint.getX(), aPoint.getY());
}
}
if( bClosePath )
{
cairo_close_path(cr);
}
}
#endif
bool SvpSalGraphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency)
{
bool bRet = false;
(void)rPolyPoly; (void)fTransparency;
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
if (m_bUseLineColor || !m_bUseFillColor)
{
SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawPolyPolygon case");
return false;
}
cairo_t* cr = createCairoContext(m_aDevice);
if (!cr)
return false;
if (!m_aDevice->isTopDown())
{
cairo_scale(cr, 1, -1.0);
cairo_translate(cr, 0.0, -m_aDevice->getSize().getY());
}
clipRegion(cr);
cairo_set_source_rgba(cr, m_aFillColor.getRed()/255.0,
m_aFillColor.getGreen()/255.0,
m_aFillColor.getBlue()/255.0,
1.0-fTransparency);
for (const basegfx::B2DPolygon* pPoly = rPolyPoly.begin(); pPoly != rPolyPoly.end(); ++pPoly)
AddPolygonToPath(cr, *pPoly, true);
cairo_rectangle_int_t extents;
basebmp::IBitmapDeviceDamageTrackerSharedPtr xDamageTracker(m_aDevice->getDamageTracker());
if (xDamageTracker)
extents = getFillDamage(cr);
cairo_fill(cr);
cairo_surface_flush(cairo_get_target(cr));
cairo_destroy(cr); // unref
if (xDamageTracker)
{
xDamageTracker->damaged(basegfx::B2IBox(extents.x, extents.y, extents.x + extents.width,
extents.y + extents.height));
}
bRet = true;
#endif
return bRet;
}
void SvpSalGraphics::copyArea( long nDestX,
......@@ -883,9 +1002,19 @@ SystemGraphicsData SvpSalGraphics::GetGraphicsData() const
bool SvpSalGraphics::supportsOperation(OutDevSupportType eType) const
{
#if ENABLE_CAIRO_CANVAS
return m_aDrawMode != basebmp::DrawMode_XOR &&
OutDevSupport_TransparentRect == eType &&
isCairoCompatible(m_aDevice);
if (m_aDrawMode == basebmp::DrawMode_XOR)
return false;
if (!isCairoCompatible(m_aDevice))
return false;
switch (eType)
{
case OutDevSupport_TransparentRect:
case OutDevSupport_B2DDraw:
return true;
case OutDevSupport_B2DClip: //what's this one ?
return false;
}
return false;
#else
(void)eType;
return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment