tdf#133453 doc import: HasSprm can return last one
The last sprm is the one that takes effect in the rare
cases of duplicate SPRMs defined, so at least have
an option to return that one as the matching value.
Unfortunately, that seems to have been ignored in the
last 20+ years of .doc support. So I added it carefully
and only enabled finding the last SPRM in the specific
case I was dealing with. However, I expect it should
~always be true, so perhaps I will followup with a
patch looking for examples of duplicate/different
SPRMs defined.
Change-Id: I5539aa3d6117380cd6d852ca165d40c7c7f3c330
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95013
Tested-by: Jenkins
Reviewed-by: Justin Luth <justin_luth@sil.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
(cherry picked from commit 4efeee09bce9835f587ea7d1577471768bf73e2d)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95125
diff --git a/sw/qa/extras/ww8export/data/tdf133453_realFontSize.doc b/sw/qa/extras/ww8export/data/tdf133453_realFontSize.doc
new file mode 100644
index 0000000..6fa50368
--- /dev/null
+++ b/sw/qa/extras/ww8export/data/tdf133453_realFontSize.doc
Binary files differ
diff --git a/sw/qa/extras/ww8export/ww8export3.cxx b/sw/qa/extras/ww8export/ww8export3.cxx
index 12a939e..96547e3 100644
--- a/sw/qa/extras/ww8export/ww8export3.cxx
+++ b/sw/qa/extras/ww8export/ww8export3.cxx
@@ -312,6 +312,11 @@ DECLARE_WW8EXPORT_TEST(testTdf120412_proportionalEscapement, "tdf120412_proporti
CPPUNIT_ASSERT_EQUAL(2, getPages());
}
DECLARE_WW8EXPORT_TEST(testTdf133453_realFontSize, "tdf133453_realFontSize.doc")
{
CPPUNIT_ASSERT_EQUAL( -95.f, getProperty<float>(getRun(getParagraph(1), 2, "2"), "CharEscapement") );
}
DECLARE_WW8EXPORT_TEST(testTdf121111_fillStyleNone, "tdf121111_fillStyleNone.docx")
{
uno::Reference<beans::XPropertySet> xStyle(getStyles("ParagraphStyles")->getByName("Numbering - First level"),
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index 7fd6ed3..f070a50 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -3450,7 +3450,7 @@ void SwWW8ImplReader::Read_SubSuperProp( sal_uInt16, const sal_uInt8* pData, sho
if ( m_xPlcxMan )
{
const sal_uInt16 nFontsizeID = m_bVer67 ? NS_sprm::v6::sprmCHps : NS_sprm::sprmCHps;
const SprmResult aFontsize = m_xPlcxMan->GetChpPLCF()->HasSprm( nFontsizeID );
const SprmResult aFontsize = m_xPlcxMan->GetChpPLCF()->HasSprm( nFontsizeID, /*bFindFirst=*/false );
if ( aFontsize.pSprm && aFontsize.nRemainingData )
Read_FontSize(nFontsizeID, aFontsize.pSprm, aFontsize.nRemainingData);
}
diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx
index 89cba1f..30294ca 100644
--- a/sw/source/filter/ww8/ww8scan.cxx
+++ b/sw/source/filter/ww8/ww8scan.cxx
@@ -915,26 +915,30 @@ void WW8SprmIter::UpdateMyMembers()
}
}
SprmResult WW8SprmIter::FindSprm(sal_uInt16 nId, const sal_uInt8* pNextByteMatch)
SprmResult WW8SprmIter::FindSprm(sal_uInt16 nId, bool bFindFirst, const sal_uInt8* pNextByteMatch)
{
SprmResult aRet;
while (GetSprms())
{
if (GetCurrentId() == nId)
{
sal_uInt16 nFixedLen = mrSprmParser.DistanceToData(nId);
sal_uInt16 nL = mrSprmParser.GetSprmSize(nId, GetSprms(), GetRemLen());
SprmResult aRet(GetCurrentParams(), nL - nFixedLen); // SPRM found!
SprmResult aSprmResult(GetCurrentParams(), nL - nFixedLen);
// typically pNextByteMatch is nullptr and we just return the first match
if (!pNextByteMatch)
return aRet;
// very occasionally we want one with a specific following byte
if (aRet.nRemainingData >= 1 && *aRet.pSprm == *pNextByteMatch)
return aRet;
if ( !pNextByteMatch || (aSprmResult.nRemainingData >= 1 && *aSprmResult.pSprm == *pNextByteMatch) )
{
if ( bFindFirst )
return aSprmResult;
aRet = aSprmResult;
}
}
advance();
}
return SprmResult(); // SPRM _not_ found
return aRet;
}
// temporary test
@@ -2945,7 +2949,7 @@ sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(sal_Int32& rLen) const
return maEntries[mnIdx].mpData;
}
SprmResult WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId )
SprmResult WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId, bool bFindFirst )
{
if (mnIdx >= mnIMax)
return SprmResult();
@@ -2954,7 +2958,7 @@ SprmResult WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId )
sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
WW8SprmIter aIter(pSprms, nLen, maSprmParser);
return aIter.FindSprm(nId);
return aIter.FindSprm(nId, bFindFirst);
}
void WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId,
@@ -3245,7 +3249,7 @@ void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc& rDesc )
}
}
SprmResult WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId)
SprmResult WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId, bool bFindFirst)
{
// const would be nicer, but for that, NewFkp() would need to be replaced or eliminated
if( !pFkp )
@@ -3259,7 +3263,7 @@ SprmResult WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId)
if (!pFkp)
return SprmResult();
SprmResult aRes = pFkp->HasSprm(nId);
SprmResult aRes = pFkp->HasSprm(nId, bFindFirst);
if (!aRes.pSprm)
{
@@ -3270,7 +3274,7 @@ SprmResult WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId)
{
WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
pFkp->GetSprmParser());
aRes = aIter.FindSprm(nId);
aRes = aIter.FindSprm(nId, bFindFirst);
}
}
@@ -3782,7 +3786,7 @@ SprmResult WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, const sal_uInt8* pOtherSprms
if (pPLCF)
{
WW8SprmIter aIter(pOtherSprms, nOtherSprmSiz, maSprmParser);
aRet = aIter.FindSprm(nId);
aRet = aIter.FindSprm(nId, /*bFindFirst=*/true);
}
return aRet;
}
@@ -3846,7 +3850,7 @@ SprmResult WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, sal_uInt8 n2nd ) const
if (pPLCF)
{
WW8SprmIter aIter(pSprms.get(), nSprmSiz, maSprmParser);
aRet = aIter.FindSprm(nId, &n2nd);
aRet = aIter.FindSprm(nId, /*bFindFirst=*/true, &n2nd);
}
return aRet;
}
diff --git a/sw/source/filter/ww8/ww8scan.hxx b/sw/source/filter/ww8/ww8scan.hxx
index 5f0f5d0..d2b32ae 100644
--- a/sw/source/filter/ww8/ww8scan.hxx
+++ b/sw/source/filter/ww8/ww8scan.hxx
@@ -275,7 +275,7 @@ public:
explicit WW8SprmIter(const sal_uInt8* pSprms_, sal_Int32 nLen_,
const wwSprmParser &rSprmParser);
void SetSprms(const sal_uInt8* pSprms_, sal_Int32 nLen_);
SprmResult FindSprm(sal_uInt16 nId, const sal_uInt8* pNextByteMatch = nullptr);
SprmResult FindSprm(sal_uInt16 nId, bool bFindFirst, const sal_uInt8* pNextByteMatch = nullptr);
void advance();
const sal_uInt8* GetSprms() const
{ return ( pSprms && (0 < nRemLen) ) ? pSprms : nullptr; }
@@ -562,8 +562,11 @@ public:
/*
calls GetLenAndIStdAndSprms()...
2020 bFindFirst note: Normally the last SPRM takes effect, so I don't know why HasSprm always returned the first value!
I don't dare to change the default due to regression potential (and slower in the few cases looking for a boolean result),
but first thing to try is use FindFirst as false.
*/
SprmResult HasSprm(sal_uInt16 nId);
SprmResult HasSprm(sal_uInt16 nId, bool bFindFirst = true);
void HasSprm(sal_uInt16 nId, std::vector<SprmResult> &rResult);
const wwSprmParser &GetSprmParser() const { return maSprmParser; }
@@ -617,7 +620,7 @@ public:
virtual void advance() override;
virtual sal_uInt16 GetIstd() const override;
void GetPCDSprms( WW8PLCFxDesc& rDesc );
SprmResult HasSprm(sal_uInt16 nId);
SprmResult HasSprm(sal_uInt16 nId, bool bFindFirst = true);
void HasSprm(sal_uInt16 nId, std::vector<SprmResult> &rResult);
bool HasFkp() const { return (nullptr != pFkp); }
};