summaryrefslogtreecommitdiff
path: root/emfio/source/reader/mtftools.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'emfio/source/reader/mtftools.cxx')
-rw-r--r--emfio/source/reader/mtftools.cxx822
1 files changed, 544 insertions, 278 deletions
diff --git a/emfio/source/reader/mtftools.cxx b/emfio/source/reader/mtftools.cxx
index b05beeb2a9dc..5e1b36c861c2 100644
--- a/emfio/source/reader/mtftools.cxx
+++ b/emfio/source/reader/mtftools.cxx
@@ -35,7 +35,7 @@
#include <osl/diagnose.h>
#include <vcl/virdev.hxx>
#include <o3tl/safeint.hxx>
-#include <unotools/configmgr.hxx>
+#include <comphelper/configuration.hxx>
#include <unotools/defaultencoding.hxx>
#include <unotools/wincodepage.hxx>
@@ -62,38 +62,47 @@ namespace emfio
rInStream.ReadFloat(rXForm.eM22);
rInStream.ReadFloat(rXForm.eDx);
rInStream.ReadFloat(rXForm.eDy);
+ if (std::isnan(rXForm.eM11) ||
+ std::isnan(rXForm.eM12) ||
+ std::isnan(rXForm.eM21) ||
+ std::isnan(rXForm.eM22) ||
+ std::isnan(rXForm.eDx) ||
+ std::isnan(rXForm.eDy))
+ {
+ SAL_WARN("emfio", "XForm member isnan, ignoring");
+ rXForm = XForm();
+ }
}
return rInStream;
}
- void WinMtfClipPath::intersectClipRect( const tools::Rectangle& rRect )
+ void WinMtfClipPath::intersectClip( const basegfx::B2DPolyPolygon& rPolyPolygon )
{
- maClip.intersectRange(vcl::unotools::b2DRectangleFromRectangle(rRect));
+ maClip.intersectPolyPolygon(rPolyPolygon);
}
- void WinMtfClipPath::excludeClipRect( const tools::Rectangle& rRect )
+ void WinMtfClipPath::excludeClip( const basegfx::B2DPolyPolygon& rPolyPolygon )
{
- maClip.subtractRange(vcl::unotools::b2DRectangleFromRectangle(rRect));
+ maClip.subtractPolyPolygon(rPolyPolygon);
}
- void WinMtfClipPath::setClipPath( const tools::PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
+ void WinMtfClipPath::setClipPath( const basegfx::B2DPolyPolygon& rB2DPoly, RegionMode nClippingMode )
{
- const basegfx::B2DPolyPolygon& rB2DPoly=rPolyPolygon.getB2DPolyPolygon();
switch ( nClippingMode )
{
- case RGN_OR :
+ case RegionMode::RGN_OR :
maClip.unionPolyPolygon(rB2DPoly);
break;
- case RGN_XOR :
+ case RegionMode::RGN_XOR :
maClip.xorPolyPolygon(rB2DPoly);
break;
- case RGN_DIFF :
+ case RegionMode::RGN_DIFF :
maClip.subtractPolyPolygon(rB2DPoly);
break;
- case RGN_AND :
+ case RegionMode::RGN_AND :
maClip.intersectPolyPolygon(rB2DPoly);
break;
- case RGN_COPY :
+ case RegionMode::RGN_COPY :
maClip = basegfx::utils::B2DClipState(rB2DPoly);
break;
}
@@ -180,25 +189,25 @@ namespace emfio
aFont.SetCharSet( eCharSet );
aFont.SetFamilyName( rFont.alfFaceName );
FontFamily eFamily;
- switch ( rFont.lfPitchAndFamily & 0xf0 )
+ switch ( rFont.lfPitchAndFamily >> 4 & 0x0f )
{
- case FF_ROMAN:
+ case FamilyFont::FF_ROMAN:
eFamily = FAMILY_ROMAN;
break;
- case FF_SWISS:
+ case FamilyFont::FF_SWISS:
eFamily = FAMILY_SWISS;
break;
- case FF_MODERN:
+ case FamilyFont::FF_MODERN:
eFamily = FAMILY_MODERN;
break;
- case FF_SCRIPT:
+ case FamilyFont::FF_SCRIPT:
eFamily = FAMILY_SCRIPT;
break;
- case FF_DECORATIVE:
+ case FamilyFont::FF_DECORATIVE:
eFamily = FAMILY_DECORATIVE;
break;
@@ -257,7 +266,7 @@ namespace emfio
aFont.SetOrientation( Degree10(static_cast<sal_Int16>(rFont.lfEscapement)) );
- Size aFontSize( Size( rFont.lfWidth, rFont.lfHeight ) );
+ Size aFontSize( rFont.lfWidth, rFont.lfHeight );
if ( rFont.lfHeight > 0 )
{
// #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
@@ -277,19 +286,225 @@ namespace emfio
// Convert height to positive
aFontSize.setHeight( std::abs(aFontSize.Height()) );
-
aFont.SetFontSize(aFontSize);
+
+ // tdf#127471 adapt nFontWidth from Windows-like notation to
+ // NormedFontScaling if used for text scaling
+#ifndef _WIN32
+ const bool bFontScaledHorizontally(aFontSize.Width() != 0 && aFontSize.Width() != aFontSize.Height());
+
+ if(bFontScaledHorizontally)
+ {
+ // tdf#127471 nFontWidth is the Windows FontScaling, need to convert to
+ // Non-Windowslike notation relative to FontHeight.
+ const tools::Long nAverageFontWidth(aFont.GetOrCalculateAverageFontWidth());
+
+ if(nAverageFontWidth > 0)
+ {
+ const double fScaleFactor(static_cast<double>(aFontSize.Height()) / static_cast<double>(nAverageFontWidth));
+ aFont.SetAverageFontWidth(static_cast<tools::Long>(static_cast<double>(aFontSize.Width()) * fScaleFactor));
+ }
+ }
+#endif
};
- Color MtfTools::ReadColor()
+ // tdf#127471
+ ScaledFontDetectCorrectHelper::ScaledFontDetectCorrectHelper()
+ {
+ }
+
+ void ScaledFontDetectCorrectHelper::endCurrentMetaFontAction()
+ {
+ if(maCurrentMetaFontAction.is() && !maAlternativeFontScales.empty())
+ {
+ // create average corrected FontScale value and count
+ // positive/negative hits
+ sal_uInt32 nPositive(0);
+ sal_uInt32 nNegative(0);
+ double fAverage(0.0);
+
+ for(double fPart : maAlternativeFontScales)
+ {
+ if(fPart < 0.0)
+ {
+ nNegative++;
+ fAverage += -fPart;
+ }
+ else
+ {
+ nPositive++;
+ fAverage += fPart;
+ }
+ }
+
+ fAverage /= static_cast<double>(maAlternativeFontScales.size());
+
+ if(nPositive >= nNegative)
+ {
+ // correction intended, it is probably an old imported file
+ maPositiveIdentifiedCases.emplace_back(maCurrentMetaFontAction, fAverage);
+ }
+ else
+ {
+ // correction not favorable in the majority of cases for this Font, still
+ // remember to have a weight in the last decision for correction
+ maNegativeIdentifiedCases.emplace_back(maCurrentMetaFontAction, fAverage);
+ }
+ }
+
+ maCurrentMetaFontAction.clear();
+ maAlternativeFontScales.clear();
+ }
+
+ void ScaledFontDetectCorrectHelper::newCurrentMetaFontAction(const rtl::Reference<MetaFontAction>& rNewMetaFontAction)
+ {
+ maCurrentMetaFontAction.clear();
+ maAlternativeFontScales.clear();
+
+ if(!rNewMetaFontAction.is())
+ return;
+
+ // check 1st criteria for FontScale active. We usually write this,
+ // so this will already sort out most situations
+ const vcl::Font& rCandidate(rNewMetaFontAction->GetFont());
+
+ if(0 != rCandidate.GetAverageFontWidth())
+ {
+ const tools::Long nUnscaledAverageFontWidth(rCandidate.GetOrCalculateAverageFontWidth());
+
+ // check 2nd (system-dependent) criteria for FontScale
+ if(nUnscaledAverageFontWidth != rCandidate.GetFontHeight())
+ {
+ // FontScale is active, remember and use as current
+ maCurrentMetaFontAction = rNewMetaFontAction;
+ }
+ }
+ }
+
+ void ScaledFontDetectCorrectHelper::evaluateAlternativeFontScale(OUString const & rText, tools::Long nImportedTextLength)
+ {
+ if(!maCurrentMetaFontAction.is())
+ return;
+
+ SolarMutexGuard aGuard; // VirtualDevice is not thread-safe
+ ScopedVclPtrInstance< VirtualDevice > pTempVirtualDevice;
+
+ // calculate measured TextLength
+ const vcl::Font& rFontCandidate(maCurrentMetaFontAction->GetFont());
+ pTempVirtualDevice->SetFont(rFontCandidate);
+ tools::Long nMeasuredTextLength(pTempVirtualDevice->GetTextWidth(rText));
+ // on failure, use original length
+ if (!nMeasuredTextLength)
+ nMeasuredTextLength = nImportedTextLength;
+
+ // compare expected and imported TextLengths
+ if (nImportedTextLength == nMeasuredTextLength)
+ return;
+
+ const double fFactorText(static_cast<double>(nImportedTextLength) / static_cast<double>(nMeasuredTextLength));
+ const double fFactorTextPercent(fabs(1.0 - fFactorText) * 100.0);
+
+ // if we assume that loaded file was written on old linux, we have to
+ // back-convert the scale value depending on which system we run
+#ifdef _WIN32
+ // When running on Windows the value was not adapted at font import (see WinMtfFontStyle
+ // constructor), so it is still NormedFontScaling and we need to convert to Windows-style
+ // scaling
+#else
+ // When running on unx (non-Windows) the value was already adapted at font import (see WinMtfFontStyle
+ // constructor). It was wrongly assumed to be Windows-style FontScaling, so we need to revert that
+ // to get back to the needed unx-style FontScale
+#endif
+ // Interestingly this leads to the *same* correction, so no need to make this
+ // system-dependent (!)
+ const tools::Long nUnscaledAverageFontWidth(rFontCandidate.GetOrCalculateAverageFontWidth());
+ const tools::Long nScaledAverageFontWidth(rFontCandidate.GetAverageFontWidth());
+ const double fScaleFactor(static_cast<double>(nUnscaledAverageFontWidth) / static_cast<double>(rFontCandidate.GetFontHeight()));
+ const double fCorrectedAverageFontWidth(static_cast<double>(nScaledAverageFontWidth) * fScaleFactor);
+ tools::Long nCorrectedTextLength(0);
+
+ { // do in own scope, only need nUnscaledAverageFontWidth
+ vcl::Font rFontCandidate2(rFontCandidate);
+ rFontCandidate2.SetAverageFontWidth(static_cast<tools::Long>(fCorrectedAverageFontWidth));
+ pTempVirtualDevice->SetFont(rFontCandidate2);
+ nCorrectedTextLength = pTempVirtualDevice->GetTextWidth(rText);
+ // on failure, use original length
+ if (!nCorrectedTextLength)
+ nCorrectedTextLength = nImportedTextLength;
+ }
+
+ const double fFactorCorrectedText(static_cast<double>(nImportedTextLength) / static_cast<double>(nCorrectedTextLength));
+ const double fFactorCorrectedTextPercent(fabs(1.0 - fFactorCorrectedText) * 100.0);
+
+ // If FactorCorrectedText fits better than FactorText this is probably
+ // an import of an old EMF/WMF written by LibreOffice on a non-Windows (unx) system
+ // and should be corrected.
+ // Usually in tested cases this lies inside 5% of range, so detecting this just using
+ // fFactorTextPercent inside 5% -> no old file
+ // fFactorCorrectedTextPercent inside 5% -> is old file
+ // works not too bad, but there are some strange not so often used fonts where that
+ // values do deviate, so better just compare if old corrected would fit better than
+ // the uncorrected case, that is usually safe.
+ if(fFactorCorrectedTextPercent < fFactorTextPercent)
+ {
+ maAlternativeFontScales.push_back(fCorrectedAverageFontWidth);
+ }
+ else
+ {
+ // also push, but negative to remember non-fitting case
+ maAlternativeFontScales.push_back(-fCorrectedAverageFontWidth);
+ }
+ }
+
+ void ScaledFontDetectCorrectHelper::applyAlternativeFontScale()
{
- sal_uInt32 nColor;
+ // make sure last evtl. detected current FontAction gets added to identified cases
+ endCurrentMetaFontAction();
+ // Take final decision to correct FontScaling for this imported Metafile or not.
+ // It is possible to weight positive against negative cases, so to only finally
+ // correct when more positive cases were detected.
+ // But that would be inconsequent and wrong. *If* the detected case is an old import
+ // the whole file was written with wrong FontScale values and all Font actions
+ // need to be corrected. Thus, for now, correct all when there are/is positive
+ // cases detected.
+ // On the other hand it *may* be that for some strange fonts there is a false-positive
+ // in the positive cases, so at least insist on positive cases being more than negative.
+ // Still, do then correct *all* cases.
+ if(!maPositiveIdentifiedCases.empty()
+ && maPositiveIdentifiedCases.size() >= maNegativeIdentifiedCases.size())
+ {
+ for(std::pair<rtl::Reference<MetaFontAction>, double>& rCandidate : maPositiveIdentifiedCases)
+ {
+ rCandidate.first->correctFontScale(static_cast<tools::Long>(rCandidate.second));
+ }
+ for(std::pair<rtl::Reference<MetaFontAction>, double>& rCandidate : maNegativeIdentifiedCases)
+ {
+ rCandidate.first->correctFontScale(static_cast<tools::Long>(rCandidate.second));
+ }
+ }
+
+ maPositiveIdentifiedCases.clear();
+ maNegativeIdentifiedCases.clear();
+ }
+
+ Color MtfTools::ReadColor()
+ {
+ sal_uInt32 nColor(0);
mpInputStream->ReadUInt32( nColor );
- Color aColor(static_cast<sal_uInt8>(nColor), static_cast<sal_uInt8>(nColor >> 8), static_cast<sal_uInt8>(nColor >> 16));
+ Color aColor( COL_BLACK );
+ if ( ( nColor & 0xFFFF0000 ) == 0x01000000 )
+ {
+ size_t index = nColor & 0x0000FFFF;
+ if ( index < maPalette.aPaletteColors.size() )
+ aColor = maPalette.aPaletteColors[ index ];
+ else
+ SAL_INFO( "emfio", "\t\t Palette index out of range: " << index );
+ }
+ else
+ aColor = Color( static_cast<sal_uInt8>( nColor ), static_cast<sal_uInt8>( nColor >> 8 ), static_cast<sal_uInt8>( nColor >> 16 ) );
SAL_INFO("emfio", "\t\tColor: " << aColor);
-
return aColor;
};
@@ -312,86 +527,40 @@ namespace emfio
double fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx;
double fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy;
- if ( mnGfxMode == GM_COMPATIBLE )
+ if ( meGfxMode == GraphicsMode::GM_COMPATIBLE )
{
- switch( mnMapMode )
+ fX2 -= mnWinOrgX;
+ fY2 -= mnWinOrgY;
+
+ switch( meMapMode )
{
- case MM_LOENGLISH :
+ case MappingMode::MM_LOENGLISH :
{
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH * 10;
- fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH * 10;
- double nDevOrgX = mnDevOrgX;
- if (mnPixX)
- nDevOrgX *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
- fX2 += nDevOrgX;
- double nDevOrgY = mnDevOrgY;
- if (mnPixY)
- nDevOrgY *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
- fY2 += nDevOrgY;
+ fX2 = o3tl::convert(fX2, o3tl::Length::in100, o3tl::Length::mm100);
+ fY2 = o3tl::convert(-fY2, o3tl::Length::in100, o3tl::Length::mm100);
}
break;
- case MM_HIENGLISH :
+ case MappingMode::MM_HIENGLISH :
{
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
- fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
- double nDevOrgX = mnDevOrgX;
- if (mnPixX)
- nDevOrgX *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
- fX2 += nDevOrgX;
- double nDevOrgY = mnDevOrgY;
- if (mnPixY)
- nDevOrgY *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
- fY2 += nDevOrgY;
+ fX2 = o3tl::convert(fX2, o3tl::Length::in1000, o3tl::Length::mm100);
+ fY2 = o3tl::convert(-fY2, o3tl::Length::in1000, o3tl::Length::mm100);
}
break;
- case MM_TWIPS:
+ case MappingMode::MM_TWIPS:
{
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH / MILLIINCH_PER_TWIPS;
- fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH / MILLIINCH_PER_TWIPS;
- double nDevOrgX = mnDevOrgX;
- if (mnPixX)
- nDevOrgX *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
- fX2 += nDevOrgX;
- double nDevOrgY = mnDevOrgY;
- if (mnPixY)
- nDevOrgY *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
- fY2 += nDevOrgY;
+ fX2 = o3tl::convert(fX2, o3tl::Length::twip, o3tl::Length::mm100);
+ fY2 = o3tl::convert(-fY2, o3tl::Length::twip, o3tl::Length::mm100);
}
break;
- case MM_LOMETRIC :
+ case MappingMode::MM_LOMETRIC :
{
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- fX2 *= 10;
- fY2 *= 10;
- double nDevOrgX = mnDevOrgX;
- if (mnPixX)
- nDevOrgX *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
- fX2 += nDevOrgX;
- double nDevOrgY = mnDevOrgY;
- if (mnPixY)
- nDevOrgY *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
- fY2 += nDevOrgY;
+ fX2 = o3tl::convert(fX2, o3tl::Length::mm10, o3tl::Length::mm100);
+ fY2 = o3tl::convert(-fY2, o3tl::Length::mm10, o3tl::Length::mm100);
}
break;
- case MM_HIMETRIC : // in hundredth of a millimeter
+ case MappingMode::MM_HIMETRIC : // in hundredth of a millimeter
{
- fX2 -= mnWinOrgX;
- fY2 = mnWinOrgY-fY2;
- double nDevOrgX = mnDevOrgX;
- if (mnPixX)
- nDevOrgX *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
- fX2 += nDevOrgX;
- double nDevOrgY = mnDevOrgY;
- if (mnPixY)
- nDevOrgY *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
- fY2 += nDevOrgY;
+ fY2 *= -1;
}
break;
default :
@@ -403,27 +572,33 @@ namespace emfio
}
else
{
- fX2 -= mnWinOrgX;
- fY2 -= mnWinOrgY;
- if ( mnMapMode != MM_TEXT )
+ if ( meMapMode != MappingMode::MM_TEXT )
{
fX2 /= mnWinExtX;
fY2 /= mnWinExtY;
fX2 *= mnDevWidth;
fY2 *= mnDevHeight;
}
- fX2 += mnDevOrgX;
- fY2 += mnDevOrgY; // fX2, fY2 now in device units
fX2 *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
fY2 *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
}
}
break;
}
+
+ double nDevOrgX = mnDevOrgX;
+ if (mnPixX)
+ nDevOrgX *= static_cast<double>(mnMillX) * 100.0 / static_cast<double>(mnPixX);
+ fX2 += nDevOrgX;
+ double nDevOrgY = mnDevOrgY;
+ if (mnPixY)
+ nDevOrgY *= static_cast<double>(mnMillY) * 100.0 / static_cast<double>(mnPixY);
+ fY2 += nDevOrgY;
+
fX2 -= mrclFrame.Left();
fY2 -= mrclFrame.Top();
}
- return Point(basegfx::fround(fX2), basegfx::fround(fY2));
+ return Point(basegfx::fround<tools::Long>(fX2), basegfx::fround<tools::Long>(fY2));
}
else
return Point();
@@ -456,37 +631,37 @@ namespace emfio
fHeight = rSz.Height() * aScale.getY();
}
- if ( mnGfxMode == GM_COMPATIBLE )
+ if ( meGfxMode == GraphicsMode::GM_COMPATIBLE )
{
- switch( mnMapMode )
+ switch( meMapMode )
{
- case MM_LOENGLISH :
+ case MappingMode::MM_LOENGLISH :
{
- fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
- fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
+ fWidth = o3tl::convert(fWidth, o3tl::Length::in100, o3tl::Length::mm100);
+ fHeight = o3tl::convert(-fHeight, o3tl::Length::in100, o3tl::Length::mm100);
}
break;
- case MM_HIENGLISH :
+ case MappingMode::MM_HIENGLISH :
{
- fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
- fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
+ fWidth = o3tl::convert(fWidth, o3tl::Length::in1000, o3tl::Length::mm100);
+ fHeight = o3tl::convert(-fHeight, o3tl::Length::in1000, o3tl::Length::mm100);
}
break;
- case MM_LOMETRIC :
+ case MappingMode::MM_LOMETRIC :
{
- fWidth *= 10;
- fHeight*=-10;
+ fWidth = o3tl::convert(fWidth, o3tl::Length::mm10, o3tl::Length::mm100);
+ fHeight = o3tl::convert(-fHeight, o3tl::Length::mm10, o3tl::Length::mm100);
}
break;
- case MM_HIMETRIC : // in hundredth of millimeters
+ case MappingMode::MM_HIMETRIC : // in hundredth of millimeters
{
fHeight *= -1;
}
break;
- case MM_TWIPS:
+ case MappingMode::MM_TWIPS:
{
- fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
- fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
+ fWidth = o3tl::convert(fWidth, o3tl::Length::twip, o3tl::Length::mm100);
+ fHeight = o3tl::convert(-fHeight, o3tl::Length::twip, o3tl::Length::mm100);
}
break;
default :
@@ -498,7 +673,7 @@ namespace emfio
}
else
{
- if ( mnMapMode != MM_TEXT )
+ if ( meMapMode != MappingMode::MM_TEXT )
{
fWidth /= mnWinExtX;
fHeight /= mnWinExtY;
@@ -512,7 +687,7 @@ namespace emfio
break;
}
}
- return Size(basegfx::fround(fWidth), basegfx::fround(fHeight));
+ return Size(basegfx::fround<tools::Long>(fWidth), basegfx::fround<tools::Long>(fHeight));
}
else
return Size();
@@ -580,55 +755,61 @@ namespace emfio
return rPolyPolygon;
}
- void MtfTools::SelectObject( sal_Int32 nIndex )
+ void MtfTools::SelectObject( sal_uInt32 nIndex )
{
if ( nIndex & ENHMETA_STOCK_OBJECT )
{
- sal_uInt16 nStockId = static_cast<sal_uInt8>(nIndex);
+ SAL_INFO ( "emfio", "\t\t ENHMETA_STOCK_OBJECT, StockObject Enumeration: 0x" << std::hex << nIndex );
+ StockObject nStockId = static_cast<StockObject>(nIndex & 0xFF);
switch( nStockId )
{
- case WHITE_BRUSH :
+ case StockObject::WHITE_BRUSH :
{
maFillStyle = WinMtfFillStyle( COL_WHITE );
mbFillStyleSelected = true;
}
break;
- case LTGRAY_BRUSH :
+ case StockObject::LTGRAY_BRUSH :
{
maFillStyle = WinMtfFillStyle( COL_LIGHTGRAY );
mbFillStyleSelected = true;
}
break;
- case GRAY_BRUSH :
- case DKGRAY_BRUSH :
+ case StockObject::GRAY_BRUSH :
{
maFillStyle = WinMtfFillStyle( COL_GRAY );
mbFillStyleSelected = true;
}
break;
- case BLACK_BRUSH :
+ case StockObject::DKGRAY_BRUSH :
+ {
+ maFillStyle = WinMtfFillStyle( COL_GRAY7 );
+ mbFillStyleSelected = true;
+ }
+ break;
+ case StockObject::BLACK_BRUSH :
{
maFillStyle = WinMtfFillStyle( COL_BLACK );
mbFillStyleSelected = true;
}
break;
- case NULL_BRUSH :
+ case StockObject::NULL_BRUSH :
{
maFillStyle = WinMtfFillStyle( COL_TRANSPARENT, true );
mbFillStyleSelected = true;
}
break;
- case WHITE_PEN :
+ case StockObject::WHITE_PEN :
{
- maLineStyle = WinMtfLineStyle( COL_WHITE );
+ maLineStyle = WinMtfLineStyle(COL_WHITE, PS_COSMETIC, 0);
}
break;
- case BLACK_PEN :
+ case StockObject::BLACK_PEN :
{
- maLineStyle = WinMtfLineStyle( COL_BLACK );
+ maLineStyle = WinMtfLineStyle(COL_BLACK, PS_COSMETIC, 0);
}
break;
- case NULL_PEN :
+ case StockObject::NULL_PEN :
{
maLineStyle = WinMtfLineStyle( COL_TRANSPARENT, true );
}
@@ -643,34 +824,58 @@ namespace emfio
GDIObj *pGDIObj = nullptr;
- if ( o3tl::make_unsigned(nIndex) < mvGDIObj.size() )
+ if ( nIndex < mvGDIObj.size() )
pGDIObj = mvGDIObj[ nIndex ].get();
if ( pGDIObj )
{
+
+ SAL_INFO ( "emfio", "\t\t Index: " << nIndex );
if (const auto pen = dynamic_cast<WinMtfLineStyle*>(pGDIObj))
+ {
maLineStyle = *pen;
+ SAL_INFO ( "emfio", "\t Line Style, Color: 0x" << std::hex << maLineStyle.aLineColor
+ << ", Weight: " << maLineStyle.aLineInfo.GetWidth() );
+ }
else if (const auto brush = dynamic_cast<WinMtfFillStyle*>(
pGDIObj))
{
maFillStyle = *brush;
mbFillStyleSelected = true;
+ SAL_INFO("emfio", "\t\tBrush Object, Index: " << nIndex << ", Color: " << maFillStyle.aFillColor);
}
else if (const auto font = dynamic_cast<WinMtfFontStyle*>(
pGDIObj))
{
maFont = font->aFont;
+ SAL_INFO("emfio", "\t\tFont Object, Index: " << nIndex << ", Font: " << maFont.GetFamilyName() << " " << maFont.GetStyleName());
}
+ else if (const auto palette = dynamic_cast<WinMtfPalette*>(
+ pGDIObj))
+ {
+ maPalette = palette->aPaletteColors;
+ SAL_INFO("emfio", "\t\tPalette Object, Index: " << nIndex << ", Number of colours: " << maPalette.aPaletteColors.size() );
+ }
+ }
+ else
+ {
+ SAL_WARN("emfio", "Warning: Unable to find Object with index:" << nIndex);
}
}
}
- void MtfTools::SetTextLayoutMode( ComplexTextLayoutFlags nTextLayoutMode )
+ void MtfTools::SetTextLayoutMode( vcl::text::ComplexTextLayoutFlags nTextLayoutMode )
{
mnTextLayoutMode = nTextLayoutMode;
}
- void MtfTools::SetBkMode( BkMode nMode )
+ void MtfTools::SetArcDirection(bool bClockWise)
+ {
+ SAL_INFO("emfio", "\t\t Arc direction: " << (bClockWise ? "ClockWise" : "CounterClockWise"));
+ mbClockWiseArcDirection = bClockWise;
+ }
+
+ void MtfTools::SetBkMode( BackgroundMode nMode )
{
mnBkMode = nMode;
}
@@ -716,7 +921,7 @@ namespace emfio
Point aPoint( aPoly[ 0 ] );
aPoly.Insert( nCount, aPoint );
}
- mpGDIMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( std::move(aPoly) ) );
}
}
}
@@ -756,7 +961,7 @@ namespace emfio
mvGDIObj[ nIndex ] = std::move(pObject);
}
- void MtfTools::CreateObjectIndexed( sal_Int32 nIndex, std::unique_ptr<GDIObj> pObject )
+ void MtfTools::CreateObjectIndexed( sal_uInt32 nIndex, std::unique_ptr<GDIObj> pObject )
{
if ( ( nIndex & ENHMETA_STOCK_OBJECT ) != 0 )
return;
@@ -780,14 +985,22 @@ namespace emfio
if ( pLineStyle->aLineInfo.GetStyle() == LineStyle::Dash )
{
aSize.AdjustWidth(1 );
- tools::Long nDotLen = ImplMap( aSize ).Width();
- pLineStyle->aLineInfo.SetDistance( nDotLen );
- pLineStyle->aLineInfo.SetDotLen( nDotLen );
- pLineStyle->aLineInfo.SetDashLen( nDotLen * 3 );
+ tools::Long nDashLen, nDotLen = ImplMap( aSize ).Width();
+ const bool bFail = o3tl::checked_multiply<tools::Long>(nDotLen, 3, nDashLen);
+ if (!bFail)
+ {
+ pLineStyle->aLineInfo.SetDistance( nDotLen );
+ pLineStyle->aLineInfo.SetDotLen( nDotLen );
+ pLineStyle->aLineInfo.SetDashLen( nDotLen * 3 );
+ }
+ else
+ {
+ SAL_WARN("emfio", "DotLen too long: " << nDotLen);
+ }
}
}
}
- if ( o3tl::make_unsigned(nIndex) >= mvGDIObj.size() )
+ if ( nIndex >= mvGDIObj.size() )
ImplResizeObjectArry( nIndex + 16 );
mvGDIObj[ nIndex ] = std::move(pObject);
@@ -798,11 +1011,11 @@ namespace emfio
CreateObject(std::make_unique<GDIObj>());
}
- void MtfTools::DeleteObject( sal_Int32 nIndex )
+ void MtfTools::DeleteObject( sal_uInt32 nIndex )
{
if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
{
- if ( o3tl::make_unsigned(nIndex) < mvGDIObj.size() )
+ if ( nIndex < mvGDIObj.size() )
{
mvGDIObj[ nIndex ].reset();
}
@@ -811,47 +1024,51 @@ namespace emfio
void MtfTools::IntersectClipRect( const tools::Rectangle& rRect )
{
- if (utl::ConfigManager::IsFuzzing())
+ if (comphelper::IsFuzzing())
return;
mbClipNeedsUpdate=true;
if ((rRect.Left()-rRect.Right()==0) && (rRect.Top()-rRect.Bottom()==0))
{
return; // empty rectangles cause trouble
}
- maClipPath.intersectClipRect( ImplMap( rRect ) );
+ tools::Polygon aPoly( rRect );
+ const tools::PolyPolygon aPolyPolyRect( ImplMap( aPoly ) );
+ maClipPath.intersectClip( aPolyPolyRect.getB2DPolyPolygon() );
}
void MtfTools::ExcludeClipRect( const tools::Rectangle& rRect )
{
- if (utl::ConfigManager::IsFuzzing())
+ if (comphelper::IsFuzzing())
return;
mbClipNeedsUpdate=true;
- maClipPath.excludeClipRect( ImplMap( rRect ) );
+ tools::Polygon aPoly( rRect );
+ const tools::PolyPolygon aPolyPolyRect( ImplMap( aPoly ) );
+ maClipPath.excludeClip( aPolyPolyRect.getB2DPolyPolygon() );
}
void MtfTools::MoveClipRegion( const Size& rSize )
{
- if (utl::ConfigManager::IsFuzzing())
+ if (comphelper::IsFuzzing())
return;
mbClipNeedsUpdate=true;
maClipPath.moveClipRegion( ImplMap( rSize ) );
}
- void MtfTools::SetClipPath( const tools::PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, bool bIsMapped )
+ void MtfTools::SetClipPath( const tools::PolyPolygon& rPolyPolygon, RegionMode eClippingMode, bool bIsMapped )
{
- if (utl::ConfigManager::IsFuzzing())
+ if (comphelper::IsFuzzing())
return;
mbClipNeedsUpdate = true;
tools::PolyPolygon aPolyPolygon(rPolyPolygon);
if (!bIsMapped)
{
- if (!mbIsMapDevSet && (mnMapMode == MM_ISOTROPIC || mnMapMode == MM_ANISOTROPIC))
+ if (!mbIsMapDevSet && (meMapMode == MappingMode::MM_ISOTROPIC || meMapMode == MappingMode::MM_ANISOTROPIC))
aPolyPolygon = ImplScale(aPolyPolygon);
else
aPolyPolygon = ImplMap(aPolyPolygon);
}
- maClipPath.setClipPath(aPolyPolygon, nClippingMode);
+ maClipPath.setClipPath(aPolyPolygon.getB2DPolyPolygon(), eClippingMode);
}
void MtfTools::SetDefaultClipPath()
@@ -861,35 +1078,19 @@ namespace emfio
}
MtfTools::MtfTools( GDIMetaFile& rGDIMetaFile, SvStream& rStreamWMF)
- : maPathObj(),
- maClipPath(),
- maLatestLineStyle(),
- maLineStyle(),
- maNopLineStyle(),
- maLatestFillStyle(),
- maFillStyle(),
- maNopFillStyle(),
- maLatestFont(),
- maFont(),
- mnLatestTextAlign(90),
- mnTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP),
- maLatestTextColor(),
- maTextColor(),
+ : mnLatestTextAlign(90),
+ mnTextAlign(TextAlignmentMode::TA_LEFT | TextAlignmentMode::TA_TOP | TextAlignmentMode::TA_NOUPDATECP),
maLatestBkColor(ColorTransparency, 0x12345678),
maBkColor(COL_WHITE),
- mnLatestTextLayoutMode(ComplexTextLayoutFlags::Default),
- mnTextLayoutMode(ComplexTextLayoutFlags::Default),
- mnLatestBkMode(BkMode::NONE),
- mnBkMode(BkMode::OPAQUE),
+ mnLatestTextLayoutMode(vcl::text::ComplexTextLayoutFlags::Default),
+ mnTextLayoutMode(vcl::text::ComplexTextLayoutFlags::Default),
+ mnLatestBkMode(BackgroundMode::NONE),
+ mnBkMode(BackgroundMode::OPAQUE),
meLatestRasterOp(RasterOp::Invert),
meRasterOp(RasterOp::OverPaint),
- mvGDIObj(),
- maActPos(),
mnRop(),
- mvSaveStack(),
- mnGfxMode(GM_COMPATIBLE),
- mnMapMode(MM_TEXT),
- maXForm(),
+ meGfxMode(GraphicsMode::GM_COMPATIBLE),
+ meMapMode(MappingMode::MM_TEXT),
mnDevOrgX(0),
mnDevOrgY(0),
mnDevWidth(1),
@@ -902,14 +1103,12 @@ namespace emfio
mnPixY(100),
mnMillX(1),
mnMillY(1),
- mrclFrame(),
- mrclBounds(),
mpGDIMetaFile(&rGDIMetaFile),
mpInputStream(&rStreamWMF),
mnStartPos(0),
mnEndPos(0),
- maBmpSaveList(),
mbNopMode(false),
+ mbClockWiseArcDirection(false),
mbFillStyleSelected(false),
mbClipNeedsUpdate(true),
mbComplexClip(false),
@@ -926,12 +1125,12 @@ namespace emfio
mnStartPos = mpInputStream->Tell();
SetDevOrg(Point());
- mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::CLIPREGION ) ); // The original clipregion has to be on top
+ mpGDIMetaFile->AddAction( new MetaPushAction( vcl::PushFlags::CLIPREGION ) ); // The original clipregion has to be on top
// of the stack so it can always be restored
// this is necessary to be able to support
// SetClipRgn( NULL ) and similar ClipRgn actions (SJ)
- maFont.SetFamilyName( "Arial" ); // sj: #i57205#, we do have some scaling problems if using
+ maFont.SetFamilyName( u"Arial"_ustr ); // sj: #i57205#, we do have some scaling problems if using
maFont.SetCharSet( RTL_TEXTENCODING_MS_1252 ); // the default font then most times a x11 font is used, we
maFont.SetFontHeight( 423 ); // will prevent this defining a font
@@ -962,7 +1161,7 @@ namespace emfio
mbComplexClip = false;
mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the original clipregion
- mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::CLIPREGION ) );
+ mpGDIMetaFile->AddAction( new MetaPushAction( vcl::PushFlags::CLIPREGION ) );
// skip for 'no clipping at all' case
if( maClipPath.isEmpty() )
@@ -973,31 +1172,16 @@ namespace emfio
mbComplexClip = rClipPoly.count() > 1
|| !basegfx::utils::isRectangle(rClipPoly);
- static bool bEnableComplexClipViaRegion = getenv("SAL_WMF_COMPLEXCLIP_VIA_REGION") != nullptr;
-
- if (bEnableComplexClipViaRegion)
+ // This makes cases like tdf#45820 work in reasonable time.
+ if (mbComplexClip)
{
- //this makes cases like tdf#45820 work in reasonable time, and I feel in theory should
- //be just fine. In practice I see the output is different so needs work before its the
- //default, but for file fuzzing it should be good enough
- if (mbComplexClip)
- {
- mpGDIMetaFile->AddAction(
- new MetaISectRegionClipRegionAction(
- vcl::Region(rClipPoly)));
- mbComplexClip = false;
- }
- else
- {
- mpGDIMetaFile->AddAction(
- new MetaISectRectClipRegionAction(
- vcl::unotools::rectangleFromB2DRectangle(
- rClipPoly.getB2DRange())));
- }
+ mpGDIMetaFile->AddAction(
+ new MetaISectRegionClipRegionAction(
+ vcl::Region(rClipPoly)));
+ mbComplexClip = false;
}
else
{
- //normal case
mpGDIMetaFile->AddAction(
new MetaISectRectClipRegionAction(
vcl::unotools::rectangleFromB2DRectangle(
@@ -1027,7 +1211,7 @@ namespace emfio
void MtfTools::UpdateFillStyle()
{
if ( !mbFillStyleSelected ) // SJ: #i57205# taking care of bkcolor if no brush is selected
- maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == BkMode::Transparent );
+ maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == BackgroundMode::Transparent );
if (!( maLatestFillStyle == maFillStyle ) )
{
maLatestFillStyle = maFillStyle;
@@ -1095,7 +1279,7 @@ namespace emfio
{
if ( !bStroke )
{
- mpGDIMetaFile->AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
+ mpGDIMetaFile->AddAction( new MetaPushAction( vcl::PushFlags::LINECOLOR ) );
mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), false ) );
}
if ( maPathObj.Count() == 1 )
@@ -1106,11 +1290,16 @@ namespace emfio
if ( !bStroke )
mpGDIMetaFile->AddAction( new MetaPopAction() );
}
- else
+ // tdf#142014 By default the stroke is made with hairline. If width is bigger, we need to use PolyLineAction
+ if ( bStroke )
{
- sal_uInt16 i, nCount = maPathObj.Count();
- for ( i = 0; i < nCount; i++ )
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( maPathObj[ i ], maLineStyle.aLineInfo ) );
+ // bFill is drawing hairstyle line. So we need to draw it only when the width is different than 0
+ if ( !bFill || maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
+ {
+ sal_uInt16 i, nCount = maPathObj.Count();
+ for ( i = 0; i < nCount; i++ )
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( maPathObj[ i ], maLineStyle.aLineInfo ) );
+ }
}
ClearPath();
}
@@ -1148,6 +1337,23 @@ namespace emfio
maActPos = aDest;
}
+ void MtfTools::DrawRectWithBGColor(const tools::Rectangle& rRect)
+ {
+ WinMtfFillStyle aFillStyleBackup = maFillStyle;
+ bool bTransparentBackup = maLineStyle.bTransparent;
+ BackgroundMode mnBkModeBackup = mnBkMode;
+
+ const tools::Polygon aPoly( rRect );
+ maLineStyle.bTransparent = true;
+ maFillStyle = maBkColor;
+ mnBkMode = BackgroundMode::OPAQUE;
+ ImplSetNonPersistentLineColorTransparenz();
+ DrawPolygon(aPoly, false);
+ mnBkMode = mnBkModeBackup; // The rectangle needs to be always drawned even if mode is transparent
+ maFillStyle = std::move(aFillStyleBackup);
+ maLineStyle.bTransparent = bTransparentBackup;
+ }
+
void MtfTools::DrawRect( const tools::Rectangle& rRect, bool bEdge )
{
UpdateClipRegion();
@@ -1192,6 +1398,12 @@ namespace emfio
UpdateLineStyle();
UpdateFillStyle();
mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), std::abs( ImplMap( rSize ).Width() ), std::abs( ImplMap( rSize ).Height() ) ) );
+ // tdf#142139 Wrong line width during WMF import
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LineStyle::Dash ) )
+ {
+ tools::Polygon aRoundRectPoly( rRect, rSize.Width(), rSize.Height() );
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( ImplMap( aRoundRectPoly ), maLineStyle.aLineInfo ) );
+ }
}
void MtfTools::DrawEllipse( const tools::Rectangle& rRect )
@@ -1207,7 +1419,7 @@ namespace emfio
ImplSetNonPersistentLineColorTransparenz();
mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( std::move(aCenter), aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
}
else
{
@@ -1233,7 +1445,7 @@ namespace emfio
Point aCenter( aRect.Center() );
Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( std::move(aCenter), aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
}
else
mpGDIMetaFile->AddAction( new MetaPolyLineAction( tools::Polygon( aRect, aStart, aEnd, PolyStyle::Arc ), maLineStyle.aLineInfo ) );
@@ -1353,10 +1565,10 @@ namespace emfio
WriteSvtGraphicFill( aMemStm, aFill );
- mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN"_ostr, 0,
static_cast<const sal_uInt8*>(aMemStm.GetData()),
aMemStm.TellEnd() ) );
- mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END" ) );
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END"_ostr ) );
}
}
@@ -1416,7 +1628,7 @@ namespace emfio
else
{
UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) );
}
}
@@ -1424,10 +1636,12 @@ namespace emfio
{
sal_uInt16 nPoints = rPolygon.GetSize();
if ( ( nPoints < 4 ) || ( ( ( nPoints - 4 ) % 3 ) != 0 ) )
+ {
+ SAL_WARN("emfio",
+ "EMF file error: Number of Bezier points is not set of three");
return;
-
+ }
UpdateClipRegion();
-
ImplMap( rPolygon );
if ( bTo )
{
@@ -1446,29 +1660,28 @@ namespace emfio
else
{
UpdateLineStyle();
- mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( std::move(rPolygon), maLineStyle.aLineInfo ) );
}
}
- void MtfTools::DrawText( Point& rPosition, OUString const & rText, tools::Long* pDXArry, tools::Long* pDYArry, bool bRecordPath, sal_Int32 nGfxMode )
+ void MtfTools::DrawText( Point& rPosition, OUString const & rText, KernArray* pDXArry, tools::Long* pDYArry, bool bRecordPath, GraphicsMode nGfxMode )
{
UpdateClipRegion();
rPosition = ImplMap( rPosition );
- sal_Int32 nOldGfxMode = GetGfxMode();
- SetGfxMode( GM_COMPATIBLE );
+ GraphicsMode nOldGfxMode = GetGfxMode();
+ SetGfxMode( GraphicsMode::GM_COMPATIBLE );
if (pDXArry)
{
- sal_Int32 nSumX = 0, nSumY = 0;
+ sal_Int64 nSumX = 0, nSumY = 0;
for (sal_Int32 i = 0; i < rText.getLength(); i++ )
{
- nSumX += pDXArry[i];
+ nSumX += (*pDXArry)[i];
// #i121382# Map DXArray using WorldTransform
const Size aSizeX(ImplMap(Size(nSumX, 0)));
const basegfx::B2DVector aVectorX(aSizeX.Width(), aSizeX.Height());
- pDXArry[i] = basegfx::fround(aVectorX.getLength());
- pDXArry[i] *= (nSumX >= 0 ? 1 : -1);
+ pDXArry->set(i, basegfx::fround(aVectorX.getLength()) * (nSumX >= 0 ? 1 : -1));
if (pDYArry)
{
@@ -1477,7 +1690,7 @@ namespace emfio
const Size aSizeY(ImplMap(Size(0, nSumY)));
const basegfx::B2DVector aVectorY(aSizeY.Width(), aSizeY.Height());
// Reverse Y
- pDYArry[i] = basegfx::fround(aVectorY.getLength());
+ pDYArry[i] = basegfx::fround<tools::Long>(aVectorY.getLength());
pDYArry[i] *= (nSumY >= 0 ? -1 : 1);
}
}
@@ -1487,11 +1700,11 @@ namespace emfio
mnLatestTextLayoutMode = mnTextLayoutMode;
mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) );
}
- SetGfxMode( nGfxMode );
+ SetGfxMode(nGfxMode);
TextAlign eTextAlign;
- if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
+ if (mnTextAlign & TA_BASELINE)
eTextAlign = ALIGN_BASELINE;
- else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
+ else if (mnTextAlign & TA_BOTTOM)
eTextAlign = ALIGN_BOTTOM;
else
eTextAlign = ALIGN_TOP;
@@ -1528,25 +1741,25 @@ namespace emfio
aTmp.SetColor( maTextColor );
aTmp.SetFillColor( maBkColor );
- if( mnBkMode == BkMode::Transparent )
+ if( mnBkMode == BackgroundMode::Transparent )
aTmp.SetTransparent( true );
else
aTmp.SetTransparent( false );
aTmp.SetAlignment( eTextAlign );
- if ( nGfxMode == GM_ADVANCED )
+ if ( nGfxMode == GraphicsMode::GM_ADVANCED )
{
// check whether there is a font rotation applied via transformation
Point aP1( ImplMap( Point() ) );
Point aP2( ImplMap( Point( 0, 100 ) ) );
- aP2.AdjustX( -(aP1.X()) );
- aP2.AdjustY( -(aP1.Y()) );
+ aP2.setX(o3tl::saturating_sub(aP2.X(), aP1.X()));
+ aP2.setY(o3tl::saturating_sub(aP2.Y(), aP1.Y()));
double fX = aP2.X();
double fY = aP2.Y();
if ( fX )
{
- double fOrientation = acos( fX / sqrt( fX * fX + fY * fY ) ) * 57.29577951308;
+ double fOrientation = basegfx::rad2deg(acos(fX / std::hypot(fX, fY)));
if ( fY > 0 )
fOrientation = 360 - fOrientation;
fOrientation += 90;
@@ -1569,9 +1782,9 @@ namespace emfio
{
nTextWidth = pVDev->GetTextWidth( OUString(rText[ nLen - 1 ]) );
if( nLen > 1 )
- nTextWidth += pDXArry[ nLen - 2 ];
+ nTextWidth += (*pDXArry)[ nLen - 2 ];
// tdf#39894: We should consider the distance to next character cell origin
- aActPosDelta.setX( pDXArry[ nLen - 1 ] );
+ aActPosDelta.setX( (*pDXArry)[ nLen - 1 ] );
if ( pDYArry )
{
aActPosDelta.setY( pDYArry[ nLen - 1 ] );
@@ -1586,9 +1799,9 @@ namespace emfio
if( mnTextAlign & TA_UPDATECP )
rPosition = maActPos;
- if ( mnTextAlign & TA_RIGHT_CENTER )
+ if (mnTextAlign & TA_RIGHT_CENTER)
{
- Point aDisplacement( ( ( mnTextAlign & TA_RIGHT_CENTER ) == TA_RIGHT ) ? nTextWidth : nTextWidth >> 1, 0 );
+ Point aDisplacement(((mnTextAlign & TA_RIGHT_CENTER) == TA_CENTER) ? nTextWidth >> 1: nTextWidth, 0);
Point().RotateAround(aDisplacement, maFont.GetOrientation());
rPosition -= aDisplacement;
}
@@ -1599,14 +1812,29 @@ namespace emfio
maActPos = rPosition + aActPosDelta;
}
}
- if ( bChangeFont || ( maLatestFont != aTmp ) )
+
+ if(bChangeFont || (maLatestFont != aTmp))
{
maLatestFont = aTmp;
- mpGDIMetaFile->AddAction( new MetaFontAction( aTmp ) );
+ rtl::Reference<MetaFontAction> aNewMetaFontAction(new MetaFontAction(aTmp));
+
+ // tdf#127471 end evtl active MetaFontAction scale corrector detector/collector
+ maScaledFontHelper.endCurrentMetaFontAction();
+
+ // !bRecordPath: else no MetaTextArrayAction will be created
+ // nullptr != pDXArry: detection only possible when text size is given
+ // rText.getLength(): no useful check without text
+ if(!bRecordPath && nullptr != pDXArry && 0 != rText.getLength())
+ {
+ maScaledFontHelper.newCurrentMetaFontAction(aNewMetaFontAction);
+ }
+
+ mpGDIMetaFile->AddAction( aNewMetaFontAction );
mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlignment() ) );
mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) );
mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) );
}
+
if ( bRecordPath )
{
// TODO
@@ -1617,29 +1845,40 @@ namespace emfio
{
for (sal_Int32 i = 0; i < rText.getLength(); ++i)
{
- Point aCharDisplacement( i ? pDXArry[i-1] : 0, i ? pDYArry[i-1] : 0 );
+ Point aCharDisplacement( i ? (*pDXArry)[i-1] : 0, i ? pDYArry[i-1] : 0 );
Point().RotateAround(aCharDisplacement, maFont.GetOrientation());
- mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition + aCharDisplacement, OUString( rText[i] ), nullptr, 0, 1 ) );
+ mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition + aCharDisplacement, OUString( rText[i] ), KernArraySpan(), {}, 0, 1 ) );
}
}
else
{
/* because text without dx array is badly scaled, we
will create such an array if necessary */
- tools::Long* pDX = pDXArry;
- if (!pDXArry)
+ KernArraySpan pDX;
+ KernArray aMyDXArray;
+ if (pDXArry)
+ {
+ pDX = *pDXArry;
+ // only useful when we have an imported DXArray
+ if(!rText.isEmpty())
+ {
+ maScaledFontHelper.evaluateAlternativeFontScale(
+ rText,
+ (*pDXArry)[rText.getLength() - 1] // extract imported TextLength
+ );
+ }
+ }
+ else
{
// #i117968# VirtualDevice is not thread safe, but filter is used in multithreading
SolarMutexGuard aGuard;
ScopedVclPtrInstance< VirtualDevice > pVDev;
- pDX = new tools::Long[ rText.getLength() ];
pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));
pVDev->SetFont( maLatestFont );
- pVDev->GetTextArray( rText, pDX, 0, rText.getLength());
+ pVDev->GetTextArray( rText, &aMyDXArray, 0, rText.getLength());
+ pDX = aMyDXArray;
}
- mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, rText.getLength() ) );
- if ( !pDXArry ) // this means we have created our own array
- delete[] pDX; // which must be deleted
+ mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, {}, 0, rText.getLength() ) );
}
}
SetGfxMode( nOldGfxMode );
@@ -1653,13 +1892,13 @@ namespace emfio
vcl::bitmap::DrawAndClipBitmap(rPos, rSize, rBitmap, aBmpEx, maClipPath.getClipPath());
}
- if ( aBmpEx.IsTransparent() )
+ if ( aBmpEx.IsAlpha() )
mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) );
else
mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) );
}
- void MtfTools::ResolveBitmapActions( std::vector<std::unique_ptr<BSaveStruct>>& rSaveList )
+ void MtfTools::ResolveBitmapActions( std::vector<BSaveStruct>& rSaveList )
{
UpdateClipRegion();
@@ -1672,7 +1911,7 @@ namespace emfio
size_t nObjectsOfSameSize = 0;
size_t nObjectStartIndex = nObjects - nObjectsLeft;
- BSaveStruct* pSave = rSaveList[nObjectStartIndex].get();
+ BSaveStruct* pSave = &rSaveList[nObjectStartIndex];
tools::Rectangle aRect( pSave->aOutRect );
for ( i = nObjectStartIndex; i < nObjects; )
@@ -1680,7 +1919,7 @@ namespace emfio
nObjectsOfSameSize++;
if ( ++i < nObjects )
{
- pSave = rSaveList[i].get();
+ pSave = &rSaveList[i];
if ( pSave->aOutRect != aRect )
break;
}
@@ -1690,7 +1929,7 @@ namespace emfio
for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ )
{
- pSave = rSaveList[i].get();
+ pSave = &rSaveList[i];
sal_uInt32 nWinRop = pSave->nWinRop;
sal_uInt8 nRasterOperation = static_cast<sal_uInt8>( nWinRop >> 16 );
@@ -1718,7 +1957,7 @@ namespace emfio
{
if ( nObjectsOfSameSize == 2 )
{
- BSaveStruct* pSave2 = rSaveList[i + 1].get();
+ BSaveStruct* pSave2 = &rSaveList[i + 1];
if ( ( pSave->aBmpEx.GetPrefSize() == pSave2->aBmpEx.GetPrefSize() ) &&
( pSave->aBmpEx.GetPrefMapMode() == pSave2->aBmpEx.GetPrefMapMode() ) )
{
@@ -1923,14 +2162,19 @@ namespace emfio
if ( !(rSize.Width() && rSize.Height()) )
return;
- switch( mnMapMode )
+ switch( meMapMode )
{
- case MM_ISOTROPIC :
- case MM_ANISOTROPIC :
+ case MappingMode::MM_ISOTROPIC :
+ case MappingMode::MM_ANISOTROPIC :
{
mnDevWidth = rSize.Width();
mnDevHeight = rSize.Height();
+ break;
}
+
+ //do nothing
+ default:
+ break;
}
if (regular)
{
@@ -1965,7 +2209,7 @@ namespace emfio
{
if (!mbIsMapDevSet)
{
- if ( mnMapMode == MM_ISOTROPIC ) //TODO: WHAT ABOUT ANISOTROPIC???
+ if ( meMapMode == MappingMode::MM_ISOTROPIC ) //TODO: WHAT ABOUT ANISOTROPIC???
{
sal_Int32 nX, nY;
if (o3tl::checked_add(mnWinExtX, mnWinOrgX, nX) || o3tl::checked_sub(mnWinExtY, mnWinOrgY, nY))
@@ -1981,10 +2225,10 @@ namespace emfio
if (!(rSize.Width() && rSize.Height()))
return;
- switch( mnMapMode )
+ switch( meMapMode )
{
- case MM_ISOTROPIC :
- case MM_ANISOTROPIC :
+ case MappingMode::MM_ISOTROPIC :
+ case MappingMode::MM_ANISOTROPIC :
{
mnWinExtX = rSize.Width();
mnWinExtY = rSize.Height();
@@ -1993,7 +2237,12 @@ namespace emfio
SetDevByWin();
}
mbIsMapWinSet = true;
+ break;
}
+
+ default:
+ //do nothing
+ break;
}
}
@@ -2025,15 +2274,15 @@ namespace emfio
mnMillY = rSize.Height();
}
- void MtfTools::SetMapMode( sal_uInt32 nMapMode )
+ void MtfTools::SetMapMode( MappingMode nMapMode )
{
- mnMapMode = nMapMode;
- if ( nMapMode == MM_TEXT && !mbIsMapWinSet )
+ meMapMode = nMapMode;
+ if ( nMapMode == MappingMode::MM_TEXT && !mbIsMapWinSet )
{
mnWinExtX = mnDevWidth;
mnWinExtY = mnDevHeight;
}
- else if ( mnMapMode == MM_HIMETRIC )
+ else if ( meMapMode == MappingMode::MM_HIMETRIC )
{
sal_Int32 nWinExtX, nWinExtY;
if (o3tl::checked_multiply<sal_Int32>(mnMillX, 100, nWinExtX) ||
@@ -2056,24 +2305,24 @@ namespace emfio
maXForm.eDy = rXForm.eDy;
}
- void MtfTools::ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode )
+ void MtfTools::ModifyWorldTransform( const XForm& rXForm, ModifyWorldTransformMode nMode )
{
switch( nMode )
{
- case MWT_IDENTITY :
+ case ModifyWorldTransformMode::MWT_IDENTITY :
{
maXForm.eM11 = maXForm.eM22 = 1.0f;
maXForm.eM12 = maXForm.eM21 = maXForm.eDx = maXForm.eDy = 0.0f;
break;
}
- case MWT_RIGHTMULTIPLY :
- case MWT_LEFTMULTIPLY :
+ case ModifyWorldTransformMode::MWT_RIGHTMULTIPLY :
+ case ModifyWorldTransformMode::MWT_LEFTMULTIPLY :
{
const XForm* pLeft;
const XForm* pRight;
- if ( nMode == MWT_LEFTMULTIPLY )
+ if ( nMode == ModifyWorldTransformMode::MWT_LEFTMULTIPLY )
{
pLeft = &rXForm;
pRight = &maXForm;
@@ -2126,7 +2375,7 @@ namespace emfio
maXForm.eDy = cF[2][1];
break;
}
- case MWT_SET:
+ case ModifyWorldTransformMode::MWT_SET:
{
SetWorldTransform(rXForm);
break;
@@ -2146,10 +2395,11 @@ namespace emfio
pSave->aTextColor = maTextColor;
pSave->nTextAlign = mnTextAlign;
pSave->nTextLayoutMode = mnTextLayoutMode;
- pSave->nMapMode = mnMapMode;
- pSave->nGfxMode = mnGfxMode;
+ pSave->eMapMode = meMapMode;
+ pSave->eGfxMode = meGfxMode;
pSave->nBkMode = mnBkMode;
pSave->aBkColor = maBkColor;
+ pSave->bClockWiseArcDirection = mbClockWiseArcDirection;
pSave->bFillStyleSelected = mbFillStyleSelected;
pSave->aActPos = maActPos;
@@ -2168,21 +2418,35 @@ namespace emfio
pSave->maPathObj = maPathObj;
pSave->maClipPath = maClipPath;
- SAL_INFO("emfio", "\t\t GfxMode: " << mnGfxMode);
- SAL_INFO("emfio", "\t\t MapMode: " << mnMapMode);
+ SAL_INFO("emfio", "\t\t GfxMode: " << static_cast<sal_uInt32>(meGfxMode));
+ SAL_INFO("emfio", "\t\t MapMode: " << static_cast<sal_uInt32>(meMapMode));
SAL_INFO("emfio", "\t\t WinOrg: " << mnWinOrgX << ", " << mnWinOrgY);
SAL_INFO("emfio", "\t\t WinExt: " << mnWinExtX << " x " << mnWinExtY);
SAL_INFO("emfio", "\t\t DevOrg: " << mnDevOrgX << ", " << mnDevOrgY);
SAL_INFO("emfio", "\t\t DevWidth/Height: " << mnDevWidth << " x " << mnDevHeight);
+ SAL_INFO("emfio", "\t\t LineStyle: " << maLineStyle.aLineColor << " FillStyle: " << maFillStyle.aFillColor );
mvSaveStack.push_back( pSave );
}
- void MtfTools::Pop()
+ void MtfTools::Pop( const sal_Int32 nSavedDC )
{
- // Get the latest data from the stack
- if( mvSaveStack.empty() )
+ if ( nSavedDC == 0 )
+ return;
+
+ sal_Int32 aIndex;
+ if ( nSavedDC < 0 ) // WMF/EMF, if negative, nSavedDC represents an instance relative to the current state.
+ aIndex = static_cast< sal_Int32 >( mvSaveStack.size() ) + nSavedDC;
+ else
+ aIndex = nSavedDC; // WMF, if positive, nSavedDC represents a specific instance of the state to be restored.
+ if( aIndex < 0 )
+ {
+ mvSaveStack.clear();
+ return;
+ }
+ if( mvSaveStack.empty() || ( aIndex >= static_cast< sal_Int32 >( mvSaveStack.size() ) ) )
return;
+ mvSaveStack.resize( aIndex + 1 );
// Backup the current data on the stack
std::shared_ptr<SaveStruct>& pSave( mvSaveStack.back() );
@@ -2194,9 +2458,10 @@ namespace emfio
mnTextAlign = pSave->nTextAlign;
mnTextLayoutMode = pSave->nTextLayoutMode;
mnBkMode = pSave->nBkMode;
- mnGfxMode = pSave->nGfxMode;
- mnMapMode = pSave->nMapMode;
+ meGfxMode = pSave->eGfxMode;
+ meMapMode = pSave->eMapMode;
maBkColor = pSave->aBkColor;
+ mbClockWiseArcDirection = pSave->bClockWiseArcDirection;
mbFillStyleSelected = pSave->bFillStyleSelected;
maActPos = pSave->aActPos;
@@ -2224,12 +2489,13 @@ namespace emfio
meLatestRasterOp = meRasterOp;
}
- SAL_INFO("emfio", "\t\t GfxMode: " << mnGfxMode);
- SAL_INFO("emfio", "\t\t MapMode: " << mnMapMode);
+ SAL_INFO("emfio", "\t\t GfxMode: " << static_cast<sal_uInt32>(meGfxMode));
+ SAL_INFO("emfio", "\t\t MapMode: " << static_cast<sal_uInt32>(meMapMode));
SAL_INFO("emfio", "\t\t WinOrg: " << mnWinOrgX << ", " << mnWinOrgY);
SAL_INFO("emfio", "\t\t WinExt: " << mnWinExtX << " x " << mnWinExtY);
SAL_INFO("emfio", "\t\t DevOrg: " << mnDevOrgX << ", " << mnDevOrgY);
SAL_INFO("emfio", "\t\t DevWidth/Height: " << mnDevWidth << " x " << mnDevHeight);
+ SAL_INFO("emfio", "\t\t LineStyle: " << maLineStyle.aLineColor << " FillStyle: " << maFillStyle.aFillColor );
mvSaveStack.pop_back();
}
@@ -2267,14 +2533,14 @@ namespace emfio
// on windows where the function parameters are probably resolved in reverse order
mem.Flush();
- mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS_HEADER_INFO", 0, static_cast<const sal_uInt8*>(mem.GetData()), mem.GetEndOfData() ) );
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS_HEADER_INFO"_ostr, 0, static_cast<const sal_uInt8*>(mem.GetData()), mem.GetEndOfData() ) );
mpGDIMetaFile->UseCanvas( true );
}
void MtfTools::PassEMFPlus( void const * pBuffer, sal_uInt32 nLength )
{
EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS comment length %04x\n",(unsigned int) nLength));
- mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS", 0, static_cast<const sal_uInt8*>(pBuffer), nLength ) );
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS"_ostr, 0, static_cast<const sal_uInt8*>(pBuffer), nLength ) );
}
}