summaryrefslogtreecommitdiffstats
path: root/filter/source/svg/svgwriter.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'filter/source/svg/svgwriter.cxx')
-rw-r--r--filter/source/svg/svgwriter.cxx510
1 files changed, 316 insertions, 194 deletions
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index e066806cea9a..e2079304abbc 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -37,6 +37,10 @@
#include <xmloff/namespacemap.hxx>
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <i18nlangtag/languagetag.hxx>
+#include <o3tl/string_view.hxx>
+#include <svx/svdomedia.hxx>
+#include <basegfx/utils/bgradient.hxx>
+#include <tools/vcompat.hxx>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/container/XIndexReplace.hpp>
@@ -49,43 +53,43 @@
#include <memory>
-constexpr OUStringLiteral aPrefixClipPathId = u"clip_path_";
-
-constexpr OUStringLiteral aXMLElemG = u"g";
-constexpr OUStringLiteral aXMLElemDefs = u"defs";
-constexpr OUStringLiteral aXMLElemText = u"text";
-constexpr OUStringLiteral aXMLElemTspan = u"tspan";
-constexpr OUStringLiteral aXMLElemLinearGradient = u"linearGradient";
-constexpr OUStringLiteral aXMLElemStop = u"stop";
-
-constexpr OUStringLiteral aXMLAttrTransform = u"transform";
-constexpr OUStringLiteral aXMLAttrStyle = u"style";
-constexpr OUStringLiteral aXMLAttrId = u"id";
-constexpr OUStringLiteral aXMLAttrX = u"x";
-constexpr OUStringLiteral aXMLAttrY = u"y";
-constexpr OUStringLiteral aXMLAttrX1 = u"x1";
-constexpr OUStringLiteral aXMLAttrY1 = u"y1";
-constexpr OUStringLiteral aXMLAttrX2 = u"x2";
-constexpr OUStringLiteral aXMLAttrY2 = u"y2";
-constexpr OUStringLiteral aXMLAttrCX = u"cx";
-constexpr OUStringLiteral aXMLAttrCY = u"cy";
-constexpr OUStringLiteral aXMLAttrRX = u"rx";
-constexpr OUStringLiteral aXMLAttrRY = u"ry";
-constexpr OUStringLiteral aXMLAttrWidth = u"width";
-constexpr OUStringLiteral aXMLAttrHeight = u"height";
-constexpr OUStringLiteral aXMLAttrStrokeWidth = u"stroke-width";
-constexpr OUStringLiteral aXMLAttrFill = u"fill";
-constexpr OUStringLiteral aXMLAttrFontFamily = u"font-family";
-constexpr OUStringLiteral aXMLAttrFontSize = u"font-size";
-constexpr OUStringLiteral aXMLAttrFontStyle = u"font-style";
-constexpr OUStringLiteral aXMLAttrFontWeight = u"font-weight";
-constexpr OUStringLiteral aXMLAttrTextDecoration = u"text-decoration";
-constexpr OUStringLiteral aXMLAttrXLinkHRef = u"xlink:href";
-constexpr OUStringLiteral aXMLAttrGradientUnits = u"gradientUnits";
-constexpr OUStringLiteral aXMLAttrOffset = u"offset";
-constexpr OUStringLiteral aXMLAttrStopColor = u"stop-color";
-constexpr OUStringLiteral aXMLAttrStrokeLinejoin = u"stroke-linejoin";
-constexpr OUStringLiteral aXMLAttrStrokeLinecap = u"stroke-linecap";
+constexpr OUString aPrefixClipPathId = u"clip_path_"_ustr;
+
+constexpr OUString aXMLElemG = u"g"_ustr;
+constexpr OUString aXMLElemDefs = u"defs"_ustr;
+constexpr OUString aXMLElemText = u"text"_ustr;
+constexpr OUString aXMLElemTspan = u"tspan"_ustr;
+constexpr OUString aXMLElemLinearGradient = u"linearGradient"_ustr;
+constexpr OUString aXMLElemStop = u"stop"_ustr;
+
+constexpr OUString aXMLAttrTransform = u"transform"_ustr;
+constexpr OUString aXMLAttrStyle = u"style"_ustr;
+constexpr OUString aXMLAttrId = u"id"_ustr;
+constexpr OUString aXMLAttrX = u"x"_ustr;
+constexpr OUString aXMLAttrY = u"y"_ustr;
+constexpr OUString aXMLAttrX1 = u"x1"_ustr;
+constexpr OUString aXMLAttrY1 = u"y1"_ustr;
+constexpr OUString aXMLAttrX2 = u"x2"_ustr;
+constexpr OUString aXMLAttrY2 = u"y2"_ustr;
+constexpr OUString aXMLAttrCX = u"cx"_ustr;
+constexpr OUString aXMLAttrCY = u"cy"_ustr;
+constexpr OUString aXMLAttrRX = u"rx"_ustr;
+constexpr OUString aXMLAttrRY = u"ry"_ustr;
+constexpr OUString aXMLAttrWidth = u"width"_ustr;
+constexpr OUString aXMLAttrHeight = u"height"_ustr;
+constexpr OUString aXMLAttrStrokeWidth = u"stroke-width"_ustr;
+constexpr OUString aXMLAttrFill = u"fill"_ustr;
+constexpr OUString aXMLAttrFontFamily = u"font-family"_ustr;
+constexpr OUString aXMLAttrFontSize = u"font-size"_ustr;
+constexpr OUString aXMLAttrFontStyle = u"font-style"_ustr;
+constexpr OUString aXMLAttrFontWeight = u"font-weight"_ustr;
+constexpr OUString aXMLAttrTextDecoration = u"text-decoration"_ustr;
+constexpr OUString aXMLAttrXLinkHRef = u"xlink:href"_ustr;
+constexpr OUString aXMLAttrGradientUnits = u"gradientUnits"_ustr;
+constexpr OUString aXMLAttrOffset = u"offset"_ustr;
+constexpr OUString aXMLAttrStopColor = u"stop-color"_ustr;
+constexpr OUString aXMLAttrStrokeLinejoin = u"stroke-linejoin"_ustr;
+constexpr OUString aXMLAttrStrokeLinecap = u"stroke-linecap"_ustr;
vcl::PushFlags SVGContextHandler::getPushFlags() const
@@ -217,8 +221,8 @@ void SVGAttributeWriter::AddPaintAttr( const Color& rLineColor, const Color& rFi
void SVGAttributeWriter::AddGradientDef( const tools::Rectangle& rObjRect, const Gradient& rGradient, OUString& rGradientId )
{
if( rObjRect.GetWidth() && rObjRect.GetHeight() &&
- ( rGradient.GetStyle() == GradientStyle::Linear || rGradient.GetStyle() == GradientStyle::Axial ||
- rGradient.GetStyle() == GradientStyle::Radial || rGradient.GetStyle() == GradientStyle::Elliptical ) )
+ ( rGradient.GetStyle() == css::awt::GradientStyle_LINEAR || rGradient.GetStyle() == css::awt::GradientStyle_AXIAL ||
+ rGradient.GetStyle() == css::awt::GradientStyle_RADIAL || rGradient.GetStyle() == css::awt::GradientStyle_ELLIPTICAL ) )
{
SvXMLElementExport aDesc( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
Color aStartColor( rGradient.GetStartColor() ), aEndColor( rGradient.GetEndColor() );
@@ -246,7 +250,7 @@ void SVGAttributeWriter::AddGradientDef( const tools::Rectangle& rObjRect, const
std::unique_ptr< SvXMLElementExport > apGradient;
OUString aColorStr;
- if( rGradient.GetStyle() == GradientStyle::Linear || rGradient.GetStyle() == GradientStyle::Axial )
+ if( rGradient.GetStyle() == css::awt::GradientStyle_LINEAR || rGradient.GetStyle() == css::awt::GradientStyle_AXIAL )
{
tools::Polygon aLinePoly( 2 );
@@ -265,9 +269,9 @@ void SVGAttributeWriter::AddGradientDef( const tools::Rectangle& rObjRect, const
// write stop values
double fBorder = static_cast< double >( rGradient.GetBorder() ) *
- ( ( rGradient.GetStyle() == GradientStyle::Axial ) ? 0.005 : 0.01 );
+ ( ( rGradient.GetStyle() == css::awt::GradientStyle_AXIAL ) ? 0.005 : 0.01 );
- ImplGetColorStr( ( rGradient.GetStyle() == GradientStyle::Axial ) ? aEndColor : aStartColor, aColorStr );
+ ImplGetColorStr( ( rGradient.GetStyle() == css::awt::GradientStyle_AXIAL ) ? aEndColor : aStartColor, aColorStr );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( fBorder ) );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
@@ -275,7 +279,7 @@ void SVGAttributeWriter::AddGradientDef( const tools::Rectangle& rObjRect, const
SvXMLElementExport aDesc2( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
}
- if( rGradient.GetStyle() == GradientStyle::Axial )
+ if( rGradient.GetStyle() == css::awt::GradientStyle_AXIAL )
{
ImplGetColorStr( aStartColor, aColorStr );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( 0.5 ) );
@@ -286,7 +290,7 @@ void SVGAttributeWriter::AddGradientDef( const tools::Rectangle& rObjRect, const
}
}
- if( rGradient.GetStyle() != GradientStyle::Axial )
+ if( rGradient.GetStyle() != css::awt::GradientStyle_AXIAL )
fBorder = 0.0;
ImplGetColorStr( aEndColor, aColorStr );
@@ -301,8 +305,7 @@ void SVGAttributeWriter::AddGradientDef( const tools::Rectangle& rObjRect, const
{
const double fCenterX = rObjRect.Left() + rObjRect.GetWidth() * rGradient.GetOfsX() * 0.01;
const double fCenterY = rObjRect.Top() + rObjRect.GetHeight() * rGradient.GetOfsY() * 0.01;
- const double fRadius = sqrt( static_cast< double >( rObjRect.GetWidth() ) * rObjRect.GetWidth() +
- rObjRect.GetHeight() * rObjRect.GetHeight() ) * 0.5;
+ const double fRadius = std::hypot(rObjRect.GetWidth(), rObjRect.GetHeight()) * 0.5;
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrGradientUnits, "userSpaceOnUse" );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, OUString::number( ImplRound( fCenterX ) ) );
@@ -633,8 +636,13 @@ sal_Int32 SVGTextWriter::setTextPosition(const GDIMetaFile& rMtf, size_t& nCurAc
{
// Text is found in the inner metafile.
bConfigured = true;
+
+ // nTextFound == 1 is only possible if the inner setTextPosition() had bEmpty ==
+ // false, adjust our bEmpty accordingly.
+ bEmpty = false;
+
mrActionWriter.StartMask(pA->GetPoint(), pA->GetSize(), pA->GetGradient(),
- nWriteFlags, &maTextOpacity);
+ nWriteFlags, pA->getSVGTransparencyColorStops(), &maTextOpacity);
}
}
break;
@@ -1099,7 +1107,19 @@ bool SVGTextWriter::nextParagraph()
const OUString& rParagraphId = implGetValidIDFromInterface( Reference<XInterface>(xTextContent, UNO_QUERY) );
if( !rParagraphId.isEmpty() )
{
- mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId );
+ // if there is id for empty paragraph we need to create a empty text paragraph
+ Reference < XTextRange > xRange( xTextContent, UNO_QUERY_THROW );
+ if ( xRange.is() && xRange->getString().isEmpty() )
+ {
+ endTextParagraph();
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextParagraph" );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId );
+ mpTextParagraphElem.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ));
+ }
+ else
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId );
+ }
}
return true;
}
@@ -1144,8 +1164,8 @@ bool SVGTextWriter::nextTextPortion()
Reference < XTextField > xTextField( xRangePropSet->getPropertyValue( "TextField" ), UNO_QUERY );
if( xTextField.is() )
{
- static const OUStringLiteral sServicePrefix(u"com.sun.star.text.textfield.");
- static const OUStringLiteral sPresentationServicePrefix(u"com.sun.star.presentation.TextField.");
+ static constexpr OUString sServicePrefix(u"com.sun.star.text.textfield."_ustr);
+ static constexpr OUString sPresentationServicePrefix(u"com.sun.star.presentation.TextField."_ustr);
Reference< XServiceInfo > xService( xTextField, UNO_QUERY );
const Sequence< OUString > aServices = xService->getSupportedServiceNames();
@@ -1178,8 +1198,8 @@ bool SVGTextWriter::nextTextPortion()
#if OSL_DEBUG_LEVEL > 0
sInfo += "text field type: " + sFieldName + "; content: " + xTextField->getPresentation( /* show command: */ false ) + "; ";
#endif
- // This case handle Date or Time text field inserted by the user
- // on both page/master page. It doesn't handle the standard Date/Time field.
+ // This case handles Date or Time text field inserted by the user
+ // on both page/master page. It doesn't handle the standard DateTime field.
if( sFieldName == "DateTime" )
{
Reference<XPropertySet> xTextFieldPropSet(xTextField, UNO_QUERY);
@@ -1188,7 +1208,7 @@ bool SVGTextWriter::nextTextPortion()
Reference<XPropertySetInfo> xPropSetInfo = xTextFieldPropSet->getPropertySetInfo();
if( xPropSetInfo.is() )
{
- // The standard Date/Time field has no property.
+ // The standard DateTime field has no property.
// Trying to get a property value on such field would cause a runtime exception.
// So the hasPropertyByName check is needed.
bool bIsFixed = true;
@@ -1197,7 +1217,7 @@ bool SVGTextWriter::nextTextPortion()
bool bIsDate = true;
if( xPropSetInfo->hasPropertyByName("IsDate") && ( ( xTextFieldPropSet->getPropertyValue( "IsDate" ) ) >>= bIsDate ) )
{
- msDateTimeType = OUString::createFromAscii( bIsDate ? "<date>" : "<time>" );
+ msDateTimeType = OUString::createFromAscii( bIsDate ? "Date" : "Time" );
}
}
}
@@ -1329,7 +1349,6 @@ void SVGTextWriter::startTextParagraph()
mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextParagraph" );
}
maParentFont = vcl::Font();
- addFontAttributes( /* isTexTContainer: */ true );
mpTextParagraphElem.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ));
if( !mbIsListLevelStyleImage )
@@ -1612,6 +1631,12 @@ void SVGTextWriter::writeTextPortion( const Point& rPos,
continue;
if( sContent == "\n" )
mbLineBreak = true;
+ else if (sContent == "\t")
+ {
+ // Need to emit position for the next text portion after a tab, otherwise the tab
+ // would appear as if it has 0 width.
+ mbPositioningNeeded = true;
+ }
if( sContent.match( rText, nStartPos ) )
bNotSync = false;
}
@@ -1722,7 +1747,18 @@ void SVGTextWriter::implWriteTextPortion( const Point& rPos,
if( mbIsPlaceholderShape )
{
- mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "PlaceholderText" );
+ OUString sClass = "PlaceholderText";
+ // This case handles Date or Time text field inserted by the user
+ // on both page/master page. It doesn't handle the standard DateTime field.
+ if( !msDateTimeType.isEmpty() )
+ {
+ sClass += " " + msDateTimeType;
+ }
+ else if( !msTextFieldType.isEmpty() )
+ {
+ sClass += " " + msTextFieldType;
+ }
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", sClass );
}
addFontAttributes( /* isTexTContainer: */ false );
@@ -1753,28 +1789,11 @@ void SVGTextWriter::implWriteTextPortion( const Point& rPos,
SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
mrExport.GetDocHandler()->characters( msPageCount );
}
- // This case handle Date or Time text field inserted by the user
- // on both page/master page. It doesn't handle the standard Date/Time field.
- else if ( !msDateTimeType.isEmpty() )
- {
- SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
- mrExport.GetDocHandler()->characters( msDateTimeType );
- }
- else if( mbIsPlaceholderShape && rText.startsWith("<") && rText.endsWith(">") )
- {
- OUString sContent;
- if( msTextFieldType == "PageNumber" )
- sContent = "<number>";
- else if( msTextFieldType == "PageName" )
- sContent = "<slide-name>";
- else
- sContent = rText;
-
- SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
- mrExport.GetDocHandler()->characters( sContent );
- }
else
{
+ // Without the following attribute Google Chrome does not render leading spaces
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "style", "white-space: pre" );
+
SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
mrExport.GetDocHandler()->characters( rText );
}
@@ -1796,7 +1815,8 @@ SVGActionWriter::SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport
mpVDev(VclPtr<VirtualDevice>::Create()),
mbClipAttrChanged( false ),
mbIsPlaceholderShape( false ),
- mpEmbeddedBitmapsMap( nullptr )
+ mpEmbeddedBitmapsMap( nullptr ),
+ mbIsPreview( false )
{
mpVDev->EnableOutput( false );
maTargetMapMode = MapMode(MapUnit::Map100thMM);
@@ -1873,8 +1893,8 @@ tools::PolyPolygon& SVGActionWriter::ImplMap( const tools::PolyPolygon& rPolyPol
OUString SVGActionWriter::GetPathString( const tools::PolyPolygon& rPolyPoly, bool bLine )
{
OUStringBuffer aPathData;
- static const OUStringLiteral aBlank( u" " );
- static const OUStringLiteral aComma( u"," );
+ static constexpr OUString aBlank( u" "_ustr );
+ static constexpr OUString aComma( u","_ustr );
Point aPolyPoint;
for( tools::Long i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
@@ -2100,10 +2120,11 @@ void SVGActionWriter::ImplWriteShape( const SVGShapeDescriptor& rShape )
ImplMap( rShape.maShapePolyPoly, aPolyPoly );
const bool bLineOnly
- = (rShape.maShapeFillColor == COL_TRANSPARENT) && (!rShape.mapShapeGradient);
+ = (rShape.maShapeFillColor == COL_TRANSPARENT) && (!rShape.moShapeGradient);
tools::Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
- maAttributeWriter.AddPaintAttr( rShape.maShapeLineColor, rShape.maShapeFillColor, &aBoundRect, rShape.mapShapeGradient.get() );
+ maAttributeWriter.AddPaintAttr( rShape.maShapeLineColor, rShape.maShapeFillColor, &aBoundRect,
+ rShape.moShapeGradient ? &*rShape.moShapeGradient : nullptr );
if( !rShape.maId.isEmpty() )
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, rShape.maId );
@@ -2293,12 +2314,12 @@ void SVGActionWriter::ImplWritePattern( const tools::PolyPolygon& rPolyPoly,
void SVGActionWriter::ImplWriteGradientEx( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient,
- sal_uInt32 nWriteFlags)
+ sal_uInt32 nWriteFlags, const basegfx::BColorStops* pColorStops)
{
- if ( rGradient.GetStyle() == GradientStyle::Linear ||
- rGradient.GetStyle() == GradientStyle::Axial )
+ if ( rGradient.GetStyle() == css::awt::GradientStyle_LINEAR ||
+ rGradient.GetStyle() == css::awt::GradientStyle_AXIAL )
{
- ImplWriteGradientLinear( rPolyPoly, rGradient );
+ ImplWriteGradientLinear( rPolyPoly, rGradient, pColorStops );
}
else
{
@@ -2308,7 +2329,7 @@ void SVGActionWriter::ImplWriteGradientEx( const tools::PolyPolygon& rPolyPoly,
void SVGActionWriter::ImplWriteGradientLinear( const tools::PolyPolygon& rPolyPoly,
- const Gradient& rGradient )
+ const Gradient& rGradient, const basegfx::BColorStops* pColorStops )
{
if( !rPolyPoly.Count() )
return;
@@ -2351,60 +2372,53 @@ void SVGActionWriter::ImplWriteGradientLinear( const tools::PolyPolygon& rPolyPo
{
SvXMLElementExport aElemLinearGradient( mrExport, XML_NAMESPACE_NONE, aXMLElemLinearGradient, true, true );
+ basegfx::BColorStops aColorStops;
- const Color aStartColor = ImplGetColorWithIntensity( rGradient.GetStartColor(), rGradient.GetStartIntensity() );
- const Color aEndColor = ImplGetColorWithIntensity( rGradient.GetEndColor(), rGradient.GetEndIntensity() );
- double fBorderOffset = rGradient.GetBorder() / 100.0;
- const sal_uInt16 nSteps = rGradient.GetSteps();
- if( rGradient.GetStyle() == GradientStyle::Linear )
+ if (nullptr != pColorStops && pColorStops->size() > 1)
{
- // Emulate non-smooth gradient
- if( 0 < nSteps && nSteps < 100 )
- {
- double fOffsetStep = ( 1.0 - fBorderOffset ) / static_cast<double>(nSteps);
- for( sal_uInt16 i = 0; i < nSteps; i++ ) {
- Color aColor = ImplGetGradientColor( aStartColor, aEndColor, i / static_cast<double>(nSteps) );
- ImplWriteGradientStop( aColor, fBorderOffset + ( i + 1 ) * fOffsetStep );
- aColor = ImplGetGradientColor( aStartColor, aEndColor, ( i + 1 ) / static_cast<double>(nSteps) );
- ImplWriteGradientStop( aColor, fBorderOffset + ( i + 1 ) * fOffsetStep );
- }
- }
- else
- {
- ImplWriteGradientStop( aStartColor, fBorderOffset );
- ImplWriteGradientStop( aEndColor, 1.0 );
- }
+ // if we got the real colr stops, use them. That way we are
+ // now capable in the SVG export to export real multi color gradients
+ aColorStops = *pColorStops;
}
else
{
- fBorderOffset /= 2;
- // Emulate non-smooth gradient
- if( 0 < nSteps && nSteps < 100 )
- {
- double fOffsetStep = ( 0.5 - fBorderOffset ) / static_cast<double>(nSteps);
- // Upper half
- for( sal_uInt16 i = 0; i < nSteps; i++ )
- {
- Color aColor = ImplGetGradientColor( aEndColor, aStartColor, i / static_cast<double>(nSteps) );
- ImplWriteGradientStop( aColor, fBorderOffset + i * fOffsetStep );
- aColor = ImplGetGradientColor( aEndColor, aStartColor, (i + 1 ) / static_cast<double>(nSteps) );
- ImplWriteGradientStop( aColor, fBorderOffset + i * fOffsetStep );
- }
- // Lower half
- for( sal_uInt16 i = 0; i < nSteps; i++ )
- {
- Color aColor = ImplGetGradientColor( aStartColor, aEndColor, i / static_cast<double>(nSteps) );
- ImplWriteGradientStop( aColor, 0.5 + (i + 1) * fOffsetStep );
- aColor = ImplGetGradientColor( aStartColor, aEndColor, (i + 1 ) / static_cast<double>(nSteps) );
- ImplWriteGradientStop( aColor, 0.5 + (i + 1) * fOffsetStep );
- }
- }
- else
- {
- ImplWriteGradientStop( aEndColor, fBorderOffset );
- ImplWriteGradientStop( aStartColor, 0.5 );
- ImplWriteGradientStop( aEndColor, 1.0 - fBorderOffset );
- }
+ // else create color stops with 'old' start/endColor
+ aColorStops.emplace_back(0.0, rGradient.GetStartColor().getBColor());
+ aColorStops.emplace_back(1.0, rGradient.GetEndColor().getBColor());
+ }
+
+ // create a basegfx::BGradient with the info to be able to directly
+ // use the tooling it offers
+ basegfx::BGradient aGradient(
+ aColorStops,
+ rGradient.GetStyle(),
+ rGradient.GetAngle(),
+ rGradient.GetOfsX(),
+ rGradient.GetOfsY(),
+ rGradient.GetBorder(),
+ rGradient.GetStartIntensity(),
+ rGradient.GetEndIntensity(),
+ rGradient.GetSteps());
+
+ // apply Start/EndIntensity to the whole color stops - if used
+ aGradient.tryToApplyStartEndIntensity();
+
+ // apply border to color stops - if used
+ aGradient.tryToApplyBorder();
+
+ // convert from 'axial' to linear - if needed and used
+ aGradient.tryToApplyAxial();
+
+ // apply 'Steps' as hard gradient stops - if used
+ aGradient.tryToApplySteps();
+
+ // write prepared gradient stops
+ for (const auto& rCand : aGradient.GetColorStops())
+ {
+ ImplWriteGradientStop(
+ Color(rCand.getStopColor()),
+ rCand.getStopOffset());
+ // aStartColor, fBorderOffset );
}
}
}
@@ -2442,28 +2456,9 @@ Color SVGActionWriter::ImplGetColorWithIntensity( const Color& rColor,
}
-Color SVGActionWriter::ImplGetGradientColor( const Color& rStartColor,
- const Color& rEndColor,
- double fOffset )
-{
- tools::Long nRedStep = rEndColor.GetRed() - rStartColor.GetRed();
- tools::Long nNewRed = rStartColor.GetRed() + static_cast<tools::Long>( nRedStep * fOffset );
- nNewRed = ( nNewRed < 0 ) ? 0 : ( nNewRed > 0xFF) ? 0xFF : nNewRed;
-
- tools::Long nGreenStep = rEndColor.GetGreen() - rStartColor.GetGreen();
- tools::Long nNewGreen = rStartColor.GetGreen() + static_cast<tools::Long>( nGreenStep * fOffset );
- nNewGreen = ( nNewGreen < 0 ) ? 0 : ( nNewGreen > 0xFF) ? 0xFF : nNewGreen;
-
- tools::Long nBlueStep = rEndColor.GetBlue() - rStartColor.GetBlue();
- tools::Long nNewBlue = rStartColor.GetBlue() + static_cast<tools::Long>( nBlueStep * fOffset );
- nNewBlue = ( nNewBlue < 0 ) ? 0 : ( nNewBlue > 0xFF) ? 0xFF : nNewBlue;
-
- return Color( static_cast<sal_uInt8>(nNewRed), static_cast<sal_uInt8>(nNewGreen), static_cast<sal_uInt8>(nNewBlue) );
-}
-
void SVGActionWriter::StartMask(const Point& rDestPt, const Size& rDestSize,
const Gradient& rGradient, sal_uInt32 nWriteFlags,
- OUString* pTextFillOpacity)
+ const basegfx::BColorStops* pColorStops, OUString* pTextFillOpacity)
{
OUString aStyle;
if (rGradient.GetStartColor() == rGradient.GetEndColor())
@@ -2504,7 +2499,19 @@ void SVGActionWriter::StartMask(const Point& rDestPt, const Size& rDestSize,
aGradient.SetEndColor(aTmpColor);
aGradient.SetEndIntensity(nTmpIntensity);
- ImplWriteGradientEx(aPolyPolygon, aGradient, nWriteFlags);
+ // tdf#155479 prep local ColorStops. The code above
+ // implies that the ColorStops need to be reversed,
+ // so do so & use change of local ptr to represent this
+ basegfx::BColorStops aLocalColorStops;
+
+ if (nullptr != pColorStops)
+ {
+ aLocalColorStops = *pColorStops;
+ aLocalColorStops.reverseColorStops();
+ pColorStops = &aLocalColorStops;
+ }
+
+ ImplWriteGradientEx(aPolyPolygon, aGradient, nWriteFlags, pColorStops);
}
}
@@ -2514,7 +2521,7 @@ void SVGActionWriter::StartMask(const Point& rDestPt, const Size& rDestSize,
}
void SVGActionWriter::ImplWriteMask(GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize,
- const Gradient& rGradient, sal_uInt32 nWriteFlags)
+ const Gradient& rGradient, sal_uInt32 nWriteFlags, const basegfx::BColorStops* pColorStops)
{
Point aSrcPt(rMtf.GetPrefMapMode().GetOrigin());
const Size aSrcSize(rMtf.GetPrefSize());
@@ -2541,7 +2548,7 @@ void SVGActionWriter::ImplWriteMask(GDIMetaFile& rMtf, const Point& rDestPt, con
std::unique_ptr<SvXMLElementExport> pElemG;
if (!maTextWriter.hasTextOpacity())
{
- StartMask(rDestPt, rDestSize, rGradient, nWriteFlags);
+ StartMask(rDestPt, rDestSize, rGradient, nWriteFlags, pColorStops);
pElemG.reset(
new SvXMLElementExport(mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true));
}
@@ -2554,7 +2561,7 @@ void SVGActionWriter::ImplWriteMask(GDIMetaFile& rMtf, const Point& rDestPt, con
void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
- o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth )
+ KernArraySpan pDXArray, tools::Long nWidth )
{
const FontMetric aMetric( mpVDev->GetFontMetric() );
@@ -2645,7 +2652,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
- o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth,
+ KernArraySpan pDXArray, tools::Long nWidth,
Color aTextColor )
{
sal_Int32 nLen = rText.getLength();
@@ -2662,18 +2669,17 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
ImplMap( rPos, aPos );
- std::vector<sal_Int32> aTmpArray(nLen);
+ KernArray aTmpArray;
// get text sizes
if( !pDXArray.empty() )
{
aNormSize = Size( mpVDev->GetTextWidth( rText ), 0 );
- memcpy(aTmpArray.data(), pDXArray.data(), nLen * sizeof(sal_Int32));
+ aTmpArray.assign(pDXArray);
}
else
{
aNormSize = Size( mpVDev->GetTextArray( rText, &aTmpArray ), 0 );
}
- sal_Int32* pDX = aTmpArray.data();
// if text is rotated, set transform matrix at new g element
if( rFont.GetOrientation() )
@@ -2721,7 +2727,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
{
if( nLen > 1 )
{
- aNormSize.setWidth( pDX[ nLen - 2 ] + mpVDev->GetTextWidth( OUString(rText[nLen - 1]) ) );
+ aNormSize.setWidth( aTmpArray[ nLen - 2 ] + mpVDev->GetTextWidth( OUString(rText[nLen - 1]) ) );
if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) )
{
@@ -2729,7 +2735,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
const double fFactor = static_cast<double>(nWidth) / aNormSize.Width();
for( i = 0; i < ( nLen - 1 ); i++ )
- pDX[ i ] = FRound( pDX[ i ] * fFactor );
+ aTmpArray.set(i, FRound(aTmpArray[i] * fFactor));
}
else
{
@@ -2765,7 +2771,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
if( bCont )
{
// #118796# do NOT access pDXArray, it may be zero (!)
- sal_Int32 nDXWidth = pDX[ nCurPos - 1 ];
+ sal_Int32 nDXWidth = aTmpArray[ nCurPos - 1 ];
nDXWidth = ImplMap( nDXWidth );
nX = aPos.X() + nDXWidth;
}
@@ -2804,7 +2810,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
aPoly[ 2 ].setX( aPoly[ 1 ].X() ); aPoly[ 2 ].setY( aPoly[ 0 ].Y() + nLineHeight - 1 );
aPoly[ 3 ].setX( aPoly[ 0 ].X() ); aPoly[ 3 ].setY( aPoly[ 2 ].Y() );
- ImplWritePolyPolygon( aPoly, false );
+ ImplWritePolyPolygon( tools::PolyPolygon(aPoly), false );
}
if( rFont.GetUnderline() )
@@ -2816,7 +2822,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
aPoly[ 2 ].setX( aPoly[ 1 ].X() ); aPoly[ 2 ].setY( aPoly[ 0 ].Y() + nLineHeight - 1 );
aPoly[ 3 ].setX( aPoly[ 0 ].X() ); aPoly[ 3 ].setY( aPoly[ 2 ].Y() );
- ImplWritePolyPolygon( aPoly, false );
+ ImplWritePolyPolygon( tools::PolyPolygon(aPoly), false );
}
}
@@ -2909,7 +2915,7 @@ void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
if (aGraphic.GetType() == GraphicType::Bitmap)
{
const BitmapEx& rGraphicBitmap = aGraphic.GetBitmapExRef();
- if (rGraphicBitmap.GetChecksum() == rBmpEx.GetChecksum())
+ if (rGraphicBitmap == rBmpEx)
{
bool bPNG = false;
GfxLink aGfxLink = aGraphic.GetGfxLink();
@@ -2930,7 +2936,27 @@ void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
}
}
- if( !(bCached || GraphicConverter::Export( aOStm, rBmpEx, ConvertDataFormat::PNG ) == ERRCODE_NONE) )
+ const BitmapEx* pBitmap = &rBmpEx;
+ std::unique_ptr<BitmapEx> pNewBitmap;
+
+ // for preview we generate downscaled images (1280x720 max)
+ if (mbIsPreview)
+ {
+ Size aSize = rBmpEx.GetSizePixel();
+ double fX = static_cast<double>(aSize.getWidth()) / 1280;
+ double fY = static_cast<double>(aSize.getHeight()) / 720;
+ double fFactor = fX > fY ? fX : fY;
+ if (fFactor > 1.0)
+ {
+ aSize.setWidth(aSize.getWidth() / fFactor);
+ aSize.setHeight(aSize.getHeight() / fFactor);
+ pNewBitmap = std::make_unique<BitmapEx>(rBmpEx);
+ pNewBitmap->Scale(aSize);
+ pBitmap = pNewBitmap.get();
+ }
+ }
+
+ if( !(bCached || GraphicConverter::Export( aOStm, *pBitmap, ConvertDataFormat::PNG ) == ERRCODE_NONE) )
return;
Point aPt;
@@ -2955,12 +2981,49 @@ void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, OUString::number( aSz.Width() ) );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, OUString::number( aSz.Height() ) );
- // the image must be scaled to aSz in a non-uniform way
- mrExport.AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", "none" );
+ // If we have a media object (a video), export the video.
+ // Also, use the image generated above as the video poster (thumbnail).
+ SdrMediaObj* pMediaObj
+ = pShape ? dynamic_cast<SdrMediaObj*>(SdrObject::getSdrObjectFromXShape(*pShape)) : nullptr;
+ const bool embedVideo = (pMediaObj && !pMediaObj->getTempURL().isEmpty());
+
+ if (!embedVideo)
+ {
+ // the image must be scaled to aSz in a non-uniform way
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "preserveAspectRatio", "none");
+
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, aBuffer.makeStringAndClear());
- mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, aBuffer.makeStringAndClear() );
+ SvXMLElementExport aElem(mrExport, XML_NAMESPACE_NONE, "image", true, true);
+ }
+ else
{
- SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, "image", true, true );
+ // <foreignObject xmlns="http://www.w3.org/2000/svg" overflow="visible" width="499.6" height="374.33333333333337" x="705" y="333">
+ // <body xmlns="http://www.w3.org/1999/xhtml">
+ // <video controls="controls" width="499.6" height="374.33333333333337">
+ // <source src="file:///tmp/abcdef.mp4" type="video/mp4">
+ // </video>
+ // </body>
+ // </foreignObject>
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "xmlns", "http://www.w3.org/2000/svg");
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "overflow", "visible");
+ SvXMLElementExport aForeignObject(mrExport, XML_NAMESPACE_NONE, "foreignObject", true,
+ true);
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "xmlns", "http://www.w3.org/1999/xhtml");
+ SvXMLElementExport aBody(mrExport, XML_NAMESPACE_NONE, "body", true, true);
+
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrWidth, OUString::number(aSz.Width()));
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrHeight, OUString::number(aSz.Height()));
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "autoplay", "autoplay");
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "controls", "controls");
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "loop", "loop");
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "preload", "auto");
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "poster", aBuffer.makeStringAndClear());
+ SvXMLElementExport aVideo(mrExport, XML_NAMESPACE_NONE, "video", true, true);
+
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "src", pMediaObj->getTempURL());
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "type", "video/mp4"); //FIXME: set mime type.
+ SvXMLElementExport aSource(mrExport, XML_NAMESPACE_NONE, "source", true, true);
}
}
@@ -3025,10 +3088,10 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
sal_uInt16 sz = static_cast<sal_uInt16>((pA->GetDataSize()) / 2);
if (sz)
{
- sType.append("; ");
- sType.append(
- reinterpret_cast<sal_Unicode const*>(pData),
- sz);
+ sType.append(OUString::Concat("; ")
+ + std::u16string_view(
+ reinterpret_cast<sal_Unicode const*>(pData),
+ sz));
}
}
}
@@ -3161,7 +3224,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
if( aPoly.GetSize() )
{
maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
- ImplWritePolyPolygon( aPoly, false );
+ ImplWritePolyPolygon( tools::PolyPolygon(aPoly), false );
}
}
}
@@ -3178,7 +3241,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
{
maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), COL_TRANSPARENT );
ImplAddLineAttr( pA->GetLineInfo() );
- ImplWritePolyPolygon( rPoly, true );
+ ImplWritePolyPolygon( tools::PolyPolygon(rPoly), true );
}
}
}
@@ -3208,7 +3271,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
const tools::Polygon aRectPoly( pA->GetRect() );
const tools::PolyPolygon aRectPolyPoly( aRectPoly );
- ImplWriteGradientEx( aRectPolyPoly, pA->GetGradient(), nWriteFlags );
+ ImplWriteGradientEx( aRectPolyPoly, pA->GetGradient(), nWriteFlags, nullptr );
}
}
break;
@@ -3218,7 +3281,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
if( nWriteFlags & SVGWRITER_WRITE_FILL )
{
const MetaGradientExAction* pA = static_cast<const MetaGradientExAction*>(pAction);
- ImplWriteGradientEx( pA->GetPolyPolygon(), pA->GetGradient(), nWriteFlags );
+ ImplWriteGradientEx( pA->GetPolyPolygon(), pA->GetGradient(), nWriteFlags, nullptr );
}
}
break;
@@ -3244,7 +3307,11 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
{
Color aNewLineColor( mpVDev->GetLineColor() ), aNewFillColor( mpVDev->GetFillColor() );
- aNewLineColor.SetAlpha( 255 - sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
+ // tdf#149800 do not change transparency of fully transparent
+ // i.e. invisible line, because it makes it visible,
+ // resulting an extra line behind the normal shape line
+ if ( aNewLineColor.GetAlpha() > 0 )
+ aNewLineColor.SetAlpha( 255 - sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
aNewFillColor.SetAlpha( 255 - sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
maAttributeWriter.AddPaintAttr( aNewLineColor, aNewFillColor );
@@ -3261,7 +3328,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pAction);
GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
ImplWriteMask( aTmpMtf, pA->GetPoint(), pA->GetSize(),
- pA->GetGradient(), nWriteFlags );
+ pA->GetGradient(), nWriteFlags, pA->getSVGTransparencyColorStops() );
}
}
break;
@@ -3295,7 +3362,62 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
{
const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
- if( ( pA->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN") ) &&
+ if (pA->GetComment().equalsIgnoreAsciiCase("BGRAD_SEQ_BEGIN"))
+ {
+ // detect and use the new BGRAD_SEQ_* metafile comment actions
+ const MetaGradientExAction* pGradAction(nullptr);
+ bool bDone(false);
+
+ while (!bDone && (++nCurAction < nCount))
+ {
+ pAction = rMtf.GetAction(nCurAction);
+
+ if (MetaActionType::GRADIENTEX == pAction->GetType())
+ {
+ // remember the 'paint' data action
+ pGradAction = static_cast<const MetaGradientExAction*>(pAction);
+ }
+ else if (MetaActionType::COMMENT == pAction->GetType()
+ && static_cast<const MetaCommentAction*>(pAction)->GetComment().equalsIgnoreAsciiCase("BGRAD_SEQ_END"))
+ {
+ // end action found
+ bDone = true;
+ }
+ }
+
+ if (nullptr != pGradAction)
+ {
+ // we have a complete actions sequence of BGRAD_SEQ_*, so we can now
+ // read the correct color stops here
+ basegfx::BColorStops aColorStops;
+ SvMemoryStream aMemStm(const_cast<sal_uInt8 *>(pA->GetData()), pA->GetDataSize(), StreamMode::READ);
+ VersionCompatRead aCompat(aMemStm);
+ sal_uInt16 nTmp(0);
+ double fOff, fR, fG, fB;
+ aMemStm.ReadUInt16( nTmp );
+
+ const size_t nMaxPossibleEntries = aMemStm.remainingSize() / 4 * sizeof(double);
+ if (nTmp > nMaxPossibleEntries)
+ {
+ SAL_WARN("filter.svg", "gradient record claims to have: " << nTmp << " entries, but only " << nMaxPossibleEntries << " possible, clamping");
+ nTmp = nMaxPossibleEntries;
+ }
+
+ for (sal_uInt16 a(0); a < nTmp; a++)
+ {
+ aMemStm.ReadDouble(fOff);
+ aMemStm.ReadDouble(fR);
+ aMemStm.ReadDouble(fG);
+ aMemStm.ReadDouble(fB);
+
+ aColorStops.emplace_back(fOff, basegfx::BColor(fR, fG, fB));
+ }
+
+ // export with real Color Stops
+ ImplWriteGradientEx(pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), nWriteFlags, &aColorStops);
+ }
+ }
+ else if( ( pA->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN") ) &&
( nWriteFlags & SVGWRITER_WRITE_FILL ) )
{
const MetaGradientExAction* pGradAction = nullptr;
@@ -3316,7 +3438,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
}
if( pGradAction )
- ImplWriteGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), nWriteFlags );
+ ImplWriteGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), nWriteFlags, nullptr );
}
else if( ( pA->GetComment().equalsIgnoreAsciiCase("XPATHFILL_SEQ_BEGIN") ) &&
( nWriteFlags & SVGWRITER_WRITE_FILL ) && !( nWriteFlags & SVGWRITER_NO_SHAPE_COMMENTS ) &&
@@ -3361,7 +3483,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
if( bGradient )
{
// step through following actions until the first Gradient/GradientEx action is found
- while (!mapCurShape->mapShapeGradient && bSkip
+ while (!mapCurShape->moShapeGradient && bSkip
&& (++nCurAction < nCount))
{
pAction = rMtf.GetAction( nCurAction );
@@ -3374,13 +3496,13 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
}
else if( pAction->GetType() == MetaActionType::GRADIENTEX )
{
- mapCurShape->mapShapeGradient.reset( new Gradient(
- static_cast< const MetaGradientExAction* >( pAction )->GetGradient() ) );
+ mapCurShape->moShapeGradient.emplace(
+ static_cast< const MetaGradientExAction* >( pAction )->GetGradient() );
}
else if( pAction->GetType() == MetaActionType::GRADIENT )
{
- mapCurShape->mapShapeGradient.reset( new Gradient(
- static_cast< const MetaGradientAction* >( pAction )->GetGradient() ) );
+ mapCurShape->moShapeGradient.emplace(
+ static_cast< const MetaGradientAction* >( pAction )->GetGradient() );
}
}
}
@@ -3442,7 +3564,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
mapCurShape->maId = aElementId + "_" + OUString::number(nEntryCount++);
}
- mapCurShape->maShapePolyPoly = aPoly;
+ mapCurShape->maShapePolyPoly = tools::PolyPolygon(aPoly);
}
mapCurShape->maShapeLineColor = mpVDev->GetLineColor();
@@ -3490,7 +3612,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
}
}
- if(mapCurShape && mapCurShape->maShapePolyPoly.Count() && (aStartArrow.Count() || aEndArrow.Count()))
+ if (mapCurShape->maShapePolyPoly.Count() && (aStartArrow.Count() || aEndArrow.Count()))
{
ImplWriteShape( *mapCurShape );
@@ -3666,7 +3788,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
// Both the pattern and the rectangle are embedded in a <defs> element.
// The comment content has the following format: "SLIDE_BACKGROUND <background-id>"
const OString& sComment = pA->GetComment();
- OUString sRefId = "#" + OUString::fromUtf8( sComment.getToken(1, ' ') );
+ OUString sRefId = "#" + OUString::fromUtf8( o3tl::getToken(sComment, 1, ' ') );
mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", true, true );