summaryrefslogtreecommitdiff
path: root/emfio/source
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2021-05-24 20:05:19 +0200
committerBartosz Kosiorek <gang65@poczta.onet.pl>2021-05-28 21:47:40 +0200
commit3a9027609e7ee0c7af457b06426093782ca295a8 (patch)
tree4f0f6aa86cccc2326e55196d412fe5d02daa8375 /emfio/source
parentd90aa314961ea4a6893144cd6be66dd71cc2cca1 (diff)
tdf#53004 tdf#142495 WMF EMF Fix displaying Text with OPAQUE and CLIPPED
With OPAQUE option enabled, the rectangle need to be drawn, before drawing text. With CLIPPED option enabled, the text needs to be drawn only inside rectangle. In previous implementation, the rectangle read was skipped and it was not drawn (for OPAQUE). For CLIPPED the rectangle was read but Clip was not applied to text drawing This commit fix that issues, and allow to draw rectangle correctly, with BGColor (background color), and add support for Text Clipping according to [MS-WMF] and [MS-EMF] specification. The fix applied to EMR_EXTTEXTOUTW, EMR_EXTTEXTOUTA and EXTTEXTOUT records Change-Id: I0f6248bb9465e6d5f797cddb53f058afb0815a2d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116072 Tested-by: Jenkins Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
Diffstat (limited to 'emfio/source')
-rw-r--r--emfio/source/reader/emfreader.cxx37
-rw-r--r--emfio/source/reader/mtftools.cxx35
-rw-r--r--emfio/source/reader/wmfreader.cxx23
3 files changed, 62 insertions, 33 deletions
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
index 9a8784c7e631..e6a758175fb5 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -1795,14 +1795,18 @@ namespace emfio
[[fallthrough]];
case EMR_EXTTEXTOUTW :
{
- sal_Int32 nLeft, nTop, nRight, nBottom, ptlReferenceX, ptlReferenceY, nGfxMode, nXScale, nYScale;
- sal_uInt32 nOffString, nOptions, offDx;
- sal_Int32 nLen;
+ sal_Int32 nLeft, nTop, nRight, nBottom;
+ sal_uInt32 nGfxMode;
+ float nXScale, nYScale;
+ sal_Int32 ptlReferenceX, ptlReferenceY;
+ sal_uInt32 nLen, nOffString, nOptions, offDx;
+ sal_Int32 nLeftRect, nTopRect, nRightRect, nBottomRect;
nCurPos = mpInputStream->Tell() - 8;
- mpInputStream->ReadInt32( nLeft ).ReadInt32( nTop ).ReadInt32( nRight ).ReadInt32( nBottom ).ReadInt32( nGfxMode ).ReadInt32( nXScale ).ReadInt32( nYScale )
- .ReadInt32( ptlReferenceX ).ReadInt32( ptlReferenceY ).ReadInt32( nLen ).ReadUInt32( nOffString ).ReadUInt32( nOptions );
+ mpInputStream->ReadInt32( nLeft ).ReadInt32( nTop ).ReadInt32( nRight ).ReadInt32( nBottom )
+ .ReadUInt32( nGfxMode ).ReadFloat( nXScale ).ReadFloat( nYScale )
+ .ReadInt32( ptlReferenceX ).ReadInt32( ptlReferenceY ).ReadUInt32( nLen ).ReadUInt32( nOffString ).ReadUInt32( nOptions );
SAL_INFO("emfio", "\t\tBounds: " << nLeft << ", " << nTop << ", " << nRight << ", " << nBottom);
SAL_INFO("emfio", "\t\tiGraphicsMode: 0x" << std::hex << nGfxMode << std::dec);
@@ -1810,7 +1814,13 @@ namespace emfio
SAL_INFO("emfio", "\t\teyScale: " << nYScale);
SAL_INFO("emfio", "\t\tReference: (" << ptlReferenceX << ", " << ptlReferenceY << ")");
- mpInputStream->SeekRel( 0x10 );
+ mpInputStream->ReadInt32( nLeftRect ).ReadInt32( nTopRect ).ReadInt32( nRightRect ).ReadInt32( nBottomRect );
+ const tools::Rectangle aRect( nLeftRect, nTopRect, nRightRect, nBottomRect );
+ BkMode mnBkModeBackup = mnBkMode;
+ if ( nOptions & ETO_NO_RECT ) // Don't draw the background rectangle
+ mnBkMode = BkMode::Transparent;
+ if ( nOptions & ETO_OPAQUE )
+ DrawRectWithBGColor( aRect );
mpInputStream->ReadUInt32( offDx );
ComplexTextLayoutFlags nTextLayoutMode = ComplexTextLayoutFlags::Default;
@@ -1820,15 +1830,14 @@ namespace emfio
SAL_WARN_IF( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) != 0, "emfio", "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
Point aPos( ptlReferenceX, ptlReferenceY );
- bool bLenSane = nLen > 0 && nLen < static_cast<sal_Int32>( SAL_MAX_UINT32 / sizeof(sal_Int32) );
bool bOffStringSane = nOffString <= mnEndPos - nCurPos;
- if (bLenSane && bOffStringSane)
+ if ( bOffStringSane )
{
mpInputStream->Seek( nCurPos + nOffString );
OUString aText;
if ( bFlag )
{
- if ( nLen <= static_cast<sal_Int32>( mnEndPos - mpInputStream->Tell() ) )
+ if ( nLen <= ( mnEndPos - mpInputStream->Tell() ) )
{
std::unique_ptr<char[]> pBuf(new char[ nLen ]);
mpInputStream->ReadBytes(pBuf.get(), nLen);
@@ -1862,7 +1871,7 @@ namespace emfio
for (sal_Int32 i = 0; i < aText.getLength(); ++i)
{
sal_Int32 nDxCount = 1;
- if (aText.getLength() != nLen)
+ if (aText.getLength() != static_cast<sal_Int32>( nLen ) )
{
sal_Unicode cUniChar = aText[i];
OString aTmp(&cUniChar, 1, GetCharSet());
@@ -1894,7 +1903,15 @@ namespace emfio
}
}
}
+ if ( nOptions & ETO_CLIPPED )
+ {
+ Push(); // Save the current clip. It will be restored after text drawing
+ IntersectClipRect( aRect );
+ }
DrawText(aPos, aText, pDXAry.get(), pDYAry.get(), mbRecordPath, nGfxMode);
+ if ( nOptions & ETO_CLIPPED )
+ Pop();
+ mnBkMode = mnBkModeBackup;
}
}
break;
diff --git a/emfio/source/reader/mtftools.cxx b/emfio/source/reader/mtftools.cxx
index d68e36e361ef..6bf0d98a3e76 100644
--- a/emfio/source/reader/mtftools.cxx
+++ b/emfio/source/reader/mtftools.cxx
@@ -1051,14 +1051,8 @@ namespace emfio
{
return; // empty rectangles cause trouble
}
- Point aPoints[] { Point(rRect.Left(), rRect.Top()),
- Point(rRect.Right(), rRect.Top()),
- Point(rRect.Right(), rRect.Bottom()),
- Point(rRect.Left(), rRect.Bottom()) };
- tools::Polygon aPoly(4, aPoints);
- aPoly = ImplMap( aPoly );
- aPoly.Optimize( PolyOptimizeFlags::CLOSE );
- tools::PolyPolygon aPolyPolyRect( aPoly );
+ tools::Polygon aPoly( rRect );
+ const tools::PolyPolygon aPolyPolyRect( ImplMap( aPoly ) );
maClipPath.intersectClip( aPolyPolyRect.getB2DPolyPolygon() );
}
@@ -1067,15 +1061,8 @@ namespace emfio
if (utl::ConfigManager::IsFuzzing())
return;
mbClipNeedsUpdate=true;
-
- Point aPoints[] { Point(rRect.Left(), rRect.Top()),
- Point(rRect.Right(), rRect.Top()),
- Point(rRect.Right(), rRect.Bottom()),
- Point(rRect.Left(), rRect.Bottom()) };
- tools::Polygon aPoly(4, aPoints);
- aPoly = ImplMap( aPoly );
- aPoly.Optimize( PolyOptimizeFlags::CLOSE );
- tools::PolyPolygon aPolyPolyRect( aPoly );
+ tools::Polygon aPoly( rRect );
+ const tools::PolyPolygon aPolyPolyRect( ImplMap( aPoly ) );
maClipPath.excludeClip( aPolyPolyRect.getB2DPolyPolygon() );
}
@@ -1390,6 +1377,20 @@ namespace emfio
maActPos = aDest;
}
+ void MtfTools::DrawRectWithBGColor(const tools::Rectangle& rRect)
+ {
+ WinMtfFillStyle aFillStyleBackup = maFillStyle;
+ bool aTransparentBackup = maLineStyle.bTransparent;
+
+ const tools::Polygon aPoly( rRect );
+ maLineStyle.bTransparent = true;
+ maFillStyle = maBkColor;
+ ImplSetNonPersistentLineColorTransparenz();
+ DrawPolygon(aPoly, false);
+ maFillStyle = aFillStyleBackup;
+ maLineStyle.bTransparent = aTransparentBackup;
+ }
+
void MtfTools::DrawRect( const tools::Rectangle& rRect, bool bEdge )
{
UpdateClipRegion();
diff --git a/emfio/source/reader/wmfreader.cxx b/emfio/source/reader/wmfreader.cxx
index 2f0aafabfaa9..f14949135ad4 100644
--- a/emfio/source/reader/wmfreader.cxx
+++ b/emfio/source/reader/wmfreader.cxx
@@ -666,8 +666,9 @@ namespace emfio
Point aPosition = ReadYX();
sal_uInt16 nLen = 0, nOptions = 0;
mpInputStream->ReadUInt16( nLen ).ReadUInt16( nOptions );
-
- if (nOptions & ETO_CLIPPED)
+ SAL_INFO( "emfio", "\t\t\t Pos: " << aPosition.getX() << ":" << aPosition.getY() << " String Length: " << nLen << " Options: " << nOptions );
+ tools::Rectangle aRect;
+ if ( ( nOptions & ETO_CLIPPED ) || ( nOptions & ETO_OPAQUE ) )
{
nNonStringLen += 2 * sizeof(sal_uInt16);
@@ -676,10 +677,12 @@ namespace emfio
SAL_WARN("emfio", "W_META_TEXTOUT too short");
break;
}
-
- ReadPoint();
- ReadPoint();
- SAL_WARN("emfio", "clipping unsupported");
+ const Point aTopLeft = ReadPoint();
+ const Point aBottomRight = ReadPoint();
+ aRect = tools::Rectangle( aTopLeft, aBottomRight );
+ if ( nOptions & ETO_OPAQUE )
+ DrawRectWithBGColor( aRect );
+ SAL_INFO( "emfio", "\t\t\t Rectangle : " << aTopLeft.getX() << ":" << aTopLeft.getY() << ", " << aBottomRight.getX() << ":" << aBottomRight.getY() );
}
ComplexTextLayoutFlags nTextLayoutMode = ComplexTextLayoutFlags::Default;
@@ -709,6 +712,12 @@ namespace emfio
// dxAry will not fit
if ( nNewTextLen )
{
+ if ( nOptions & ETO_CLIPPED )
+ {
+ Push(); // Save the current clip. It will be restored after text drawing
+ IntersectClipRect( aRect );
+ }
+ SAL_INFO( "emfio", "\t\t\t Text : " << aText );
std::unique_ptr<tools::Long[]> pDXAry, pDYAry;
auto nDxArySize = nMaxStreamPos - mpInputStream->Tell();
auto nDxAryEntries = nDxArySize >> 1;
@@ -768,6 +777,8 @@ namespace emfio
DrawText( aPosition, aText, pDXAry.get(), pDYAry.get() );
else
DrawText( aPosition, aText );
+ if ( nOptions & ETO_CLIPPED )
+ Pop();
}
}
}