EMF+ tdf#31814 Add support of reading EmfPlusBoundaryPointData
The EmfPlusBoundaryPointData object specifies a closed cardinal spline boundary for a gradient brush. This data is starting point for displaying correctly gradients. Change-Id: I91b01417c6dc00a04dabfc5a035afe9085999240 Reviewed-on: https://gerrit.libreoffice.org/37519 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
This commit is contained in:
@@ -43,16 +43,6 @@ namespace cppcanvas
|
|||||||
{
|
{
|
||||||
namespace internal
|
namespace internal
|
||||||
{
|
{
|
||||||
|
|
||||||
enum EmfPlusBrushType
|
|
||||||
{
|
|
||||||
BrushTypeSolidColor = 0x00000000,
|
|
||||||
BrushTypeHatchFill = 0x00000001,
|
|
||||||
BrushTypeTextureFill = 0x00000002,
|
|
||||||
BrushTypePathGradient = 0x00000003,
|
|
||||||
BrushTypeLinearGradient = 0x00000004
|
|
||||||
};
|
|
||||||
|
|
||||||
EMFPBrush::EMFPBrush()
|
EMFPBrush::EMFPBrush()
|
||||||
: type(0)
|
: type(0)
|
||||||
, additionalFlags(0)
|
, additionalFlags(0)
|
||||||
@@ -154,7 +144,7 @@ namespace cppcanvas
|
|||||||
SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY);
|
SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY);
|
||||||
|
|
||||||
s.ReadInt32(surroundColorsNumber);
|
s.ReadInt32(surroundColorsNumber);
|
||||||
SAL_INFO("cppcanvas.emf", "EMF+\tsurround colors: " << surroundColorsNumber);
|
SAL_INFO("cppcanvas.emf", "EMF+\t number of surround colors: " << surroundColorsNumber);
|
||||||
|
|
||||||
if (surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32 / sizeof(::Color))
|
if (surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32 / sizeof(::Color))
|
||||||
surroundColorsNumber = SAL_MAX_INT32 / sizeof(::Color);
|
surroundColorsNumber = SAL_MAX_INT32 / sizeof(::Color);
|
||||||
@@ -191,9 +181,25 @@ namespace cppcanvas
|
|||||||
const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false)));
|
const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false)));
|
||||||
areaWidth = aBounds.getWidth();
|
areaWidth = aBounds.getWidth();
|
||||||
areaHeight = aBounds.getHeight();
|
areaHeight = aBounds.getHeight();
|
||||||
|
|
||||||
SAL_INFO("cppcanvas.emf", "EMF+\t polygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight());
|
SAL_INFO("cppcanvas.emf", "EMF+\t polygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sal_Int32 boundaryPointCount;
|
||||||
|
s.ReadInt32(boundaryPointCount);
|
||||||
|
|
||||||
|
sal_uInt64 const pos = s.Tell();
|
||||||
|
SAL_INFO("cppcanvas.emf", "EMF+\t use boundary, points: " << boundaryPointCount);
|
||||||
|
path = new EMFPPath(boundaryPointCount);
|
||||||
|
path->Read(s, 0x0, rR);
|
||||||
|
|
||||||
|
s.Seek(pos + 8 * boundaryPointCount);
|
||||||
|
|
||||||
|
const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false)));
|
||||||
|
areaWidth = aBounds.getWidth();
|
||||||
|
areaHeight = aBounds.getHeight();
|
||||||
|
SAL_INFO("cppcanvas.emf", "EMF+\t polygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
if (additionalFlags & 0x02) {
|
if (additionalFlags & 0x02) {
|
||||||
SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
|
SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation");
|
||||||
@@ -241,7 +247,7 @@ namespace cppcanvas
|
|||||||
SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
|
SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BrushTypeLinearGradient:
|
case BrushTypeLinearGradient:
|
||||||
|
@@ -81,6 +81,15 @@ namespace cppcanvas
|
|||||||
HatchStyleSolidDiamond = 0x00000034
|
HatchStyleSolidDiamond = 0x00000034
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EmfPlusBrushType
|
||||||
|
{
|
||||||
|
BrushTypeSolidColor = 0x00000000,
|
||||||
|
BrushTypeHatchFill = 0x00000001,
|
||||||
|
BrushTypeTextureFill = 0x00000002,
|
||||||
|
BrushTypePathGradient = 0x00000003,
|
||||||
|
BrushTypeLinearGradient = 0x00000004
|
||||||
|
};
|
||||||
|
|
||||||
struct EMFPPath;
|
struct EMFPPath;
|
||||||
|
|
||||||
struct EMFPBrush : public EMFPObject
|
struct EMFPBrush : public EMFPObject
|
||||||
|
@@ -330,7 +330,7 @@ namespace cppcanvas
|
|||||||
rState.isFillColorSet = false;
|
rState.isFillColorSet = false;
|
||||||
rState.isLineColorSet = false;
|
rState.isLineColorSet = false;
|
||||||
|
|
||||||
if (brush->type == 1)
|
if (brush->type == BrushTypeHatchFill)
|
||||||
{
|
{
|
||||||
// EMF+ like hatching is currently not supported. These are just color blends which serve as an approximation for some of them
|
// EMF+ like hatching is currently not supported. These are just color blends which serve as an approximation for some of them
|
||||||
// for the others the hatch "background" color (secondColor in brush) is used.
|
// for the others the hatch "background" color (secondColor in brush) is used.
|
||||||
@@ -371,11 +371,16 @@ namespace cppcanvas
|
|||||||
rState.fillColor = vcl::unotools::colorToDoubleSequence(fillColor, rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
|
rState.fillColor = vcl::unotools::colorToDoubleSequence(fillColor, rCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace());
|
||||||
pPolyAction = ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon, rParms.mrCanvas, rState ) );
|
pPolyAction = ActionSharedPtr ( internal::PolyPolyActionFactory::createPolyPolyAction( localPolygon, rParms.mrCanvas, rState ) );
|
||||||
}
|
}
|
||||||
else if (brush->type == 3 || brush->type == 4)
|
else if (brush->type == BrushTypeTextureFill)
|
||||||
{
|
{
|
||||||
if (brush->type == 3 && !(brush->additionalFlags & 0x1))
|
SAL_WARN("cppcanvas.emf", "EMF+\tTODO: implement BrushTypeTextureFill brush");
|
||||||
return; // we are unable to parse these brushes yet
|
}
|
||||||
|
else if (brush->type == BrushTypePathGradient || brush->type == BrushTypeLinearGradient)
|
||||||
|
{
|
||||||
|
if (brush->type == BrushTypePathGradient && !(brush->additionalFlags & 0x1))
|
||||||
|
{
|
||||||
|
SAL_WARN("cppcanvas.emf", "EMF+\t TODO Verify proper displaying of BrushTypePathGradient with flags: " << std::hex << brush->additionalFlags << std::dec);
|
||||||
|
}
|
||||||
::basegfx::B2DHomMatrix aTextureTransformation;
|
::basegfx::B2DHomMatrix aTextureTransformation;
|
||||||
::basegfx::B2DHomMatrix aWorldTransformation;
|
::basegfx::B2DHomMatrix aWorldTransformation;
|
||||||
::basegfx::B2DHomMatrix aBaseTransformation;
|
::basegfx::B2DHomMatrix aBaseTransformation;
|
||||||
@@ -395,14 +400,13 @@ namespace cppcanvas
|
|||||||
aBaseTransformation.set (1, 1, aBaseTransform.eM22);
|
aBaseTransformation.set (1, 1, aBaseTransform.eM22);
|
||||||
aBaseTransformation.set (1, 2, aBaseTransform.eDy);
|
aBaseTransformation.set (1, 2, aBaseTransform.eDy);
|
||||||
|
|
||||||
if (brush->type == 4) {
|
// TODO Verify on example image, why there is shift (-0.5, -0.5)
|
||||||
aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
|
if (brush->type == BrushTypePathGradient && (brush->additionalFlags & 0x1))
|
||||||
aTextureTransformation.translate (brush->areaX, brush->areaY);
|
{
|
||||||
} else {
|
|
||||||
aTextureTransformation.translate (-0.5, -0.5);
|
aTextureTransformation.translate (-0.5, -0.5);
|
||||||
|
}
|
||||||
aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
|
aTextureTransformation.scale (brush->areaWidth, brush->areaHeight);
|
||||||
aTextureTransformation.translate (brush->areaX, brush->areaY);
|
aTextureTransformation.translate (brush->areaX, brush->areaY);
|
||||||
}
|
|
||||||
|
|
||||||
if (brush->hasTransformation) {
|
if (brush->hasTransformation) {
|
||||||
::basegfx::B2DHomMatrix aTransformation;
|
::basegfx::B2DHomMatrix aTransformation;
|
||||||
@@ -452,7 +456,7 @@ namespace cppcanvas
|
|||||||
aStops[i] = brush->blendPositions [i];
|
aStops[i] = brush->blendPositions [i];
|
||||||
|
|
||||||
for (int j = 0; j < length; j++) {
|
for (int j = 0; j < length; j++) {
|
||||||
if (brush->type == 4) {
|
if (brush->type == BrushTypeLinearGradient) {
|
||||||
aColor [j] = aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i];
|
aColor [j] = aStartColor [j]*(1 - brush->blendFactors[i]) + aEndColor [j]*brush->blendFactors[i];
|
||||||
} else
|
} else
|
||||||
aColor [j] = aStartColor [j]*brush->blendFactors[i] + aEndColor [j]*(1 - brush->blendFactors[i]);
|
aColor [j] = aStartColor [j]*brush->blendFactors[i] + aEndColor [j]*(1 - brush->blendFactors[i]);
|
||||||
@@ -467,14 +471,14 @@ namespace cppcanvas
|
|||||||
|
|
||||||
for (int i = 0; i < brush->colorblendPoints; i++) {
|
for (int i = 0; i < brush->colorblendPoints; i++) {
|
||||||
aStops[i] = brush->colorblendPositions [i];
|
aStops[i] = brush->colorblendPositions [i];
|
||||||
aColors[(brush->type == 4) ? i : brush->colorblendPoints - 1 - i] = vcl::unotools::colorToDoubleSequence( brush->colorblendColors [i],
|
aColors[(brush->type == BrushTypeLinearGradient) ? i : brush->colorblendPoints - 1 - i] = vcl::unotools::colorToDoubleSequence( brush->colorblendColors [i],
|
||||||
rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
|
rParms.mrCanvas->getUNOCanvas()->getDevice()->getDeviceColorSpace() );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
aStops[0] = 0.0;
|
aStops[0] = 0.0;
|
||||||
aStops[1] = 1.0;
|
aStops[1] = 1.0;
|
||||||
|
|
||||||
if (brush->type == 4) {
|
if (brush->type == BrushTypeLinearGradient) {
|
||||||
aColors[0] = aStartColor;
|
aColors[0] = aStartColor;
|
||||||
aColors[1] = aEndColor;
|
aColors[1] = aEndColor;
|
||||||
} else {
|
} else {
|
||||||
@@ -485,7 +489,7 @@ namespace cppcanvas
|
|||||||
|
|
||||||
SAL_INFO("cppcanvas.emf", "EMF+\t\tset gradient");
|
SAL_INFO("cppcanvas.emf", "EMF+\t\tset gradient");
|
||||||
basegfx::B2DRange aBoundsRectangle (0, 0, 1, 1);
|
basegfx::B2DRange aBoundsRectangle (0, 0, 1, 1);
|
||||||
if (brush->type == 4) {
|
if (brush->type == BrushTypeLinearGradient) {
|
||||||
aGradientService = "LinearGradient";
|
aGradientService = "LinearGradient";
|
||||||
aGradInfo = basegfx::tools::createLinearODFGradientInfo(
|
aGradInfo = basegfx::tools::createLinearODFGradientInfo(
|
||||||
aBoundsRectangle,
|
aBoundsRectangle,
|
||||||
|
Reference in New Issue
Block a user