sw: docx: recode a list bullet from the old StarOffice symbol fonts

Steps to reproduce:
1) Open a document whose list bullet uses the StarBats font, such as
   sw/qa/extras/ooxmlexport/data/starbats-bullet.docx.
2) Save it as DOCX.
3) Open the saved file in an office suite that does not have that font.
Both bullets draw as empty rectangles.

The level goes out as character U+F095 in the font starbats. StarBats
is one of the old StarOffice symbol fonts, and its characters sit in
the Unicode private use area, so a reader without the font gets no
glyph from any fallback either. Writer itself draws the bullet, because
substituting the missing font installs the table that recodes the
character to the place OpenSymbol keeps it at. Nothing did that on the
way out, so the writer put the old font name and the private use
character straight back.

MSWordExportBase::SubstituteBullet already maps an OpenSymbol or a
StarSymbol bullet to a character in a font that other suites have.
Recode a StarBats or a StarMath character to OpenSymbol first and that
mapping then covers it as well. U+F095 becomes U+2022, and from there
U+F0B7 in the font Symbol, which is what other writers produce for a
plain bullet. CreateFontToSubsFontConverter with the import flag names
exactly those two fonts and no others, so a bullet that already came in
as Symbol, Wingdings or Webdings keeps the character it had.

The font test moves from the caller into SubstituteBullet, which keeps
the new recode behind the m_bSubstituteBullets switch. The RTF writer
clears that switch and goes on writing the OpenSymbol names its own
reader expects.

Add a test that saves such a document and reads the bullet level back
out of the numbering part.

Change-Id: Id487d6ec216cdf293b645e9749d1b3f81eb6347d
Signed-off-by: Dennis Francis <dennis.francis@collabora.com>
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/9566
Tested-by: Jenkins CPCI <releng@collaboraoffice.com>
Reviewed-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit dc625bf7ece1baf29201e2622c4b4c61750203d2)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210418
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
This commit is contained in:
Dennis Francis
2026-09-02 16:11:39 +02:00
committed by Xisco Fauli
parent 154fcee000
commit 04543c13fd
3 changed files with 37 additions and 5 deletions
Binary file not shown.
@@ -106,6 +106,21 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf171527_flyInFramePr)
assertXPath(pXmlDoc, "//w:body/w:p/w:pPr/w:framePr", 1);
}
CPPUNIT_TEST_FIXTURE(Test, testStarBatsBulletKeepsAVisibleGlyph)
{
createSwDoc("starbats-bullet.docx");
save(TestFilter::DOCX);
xmlDocUniquePtr pXmlDoc = parseExport(u"word/numbering.xml"_ustr);
// The bullet comes out in a font that is widely available, at the character that font holds
// the bullet at. A reader without the old StarBats font still gets a bullet rather than an
// empty rectangle.
assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:rPr/w:rFonts", "ascii",
u"Symbol");
assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:lvlText", "val", u"\xF0B7");
}
CPPUNIT_TEST_FIXTURE(Test, testTdf171433_equation)
{
// given a document with formula
+22 -5
View File
@@ -18,6 +18,7 @@
*/
#include <hintids.hxx>
#include <unotools/fontcvt.hxx>
#include <vcl/font.hxx>
#include <editeng/langitem.hxx>
#include <unotools/fontdefs.hxx>
@@ -439,8 +440,7 @@ MSWordExportBase::GetNumberingLevelBulletStringAndFont(const SwNumFormat& rLevel
OUString sFontName = pBulletFont->GetFamilyName();
FontFamily eFamily = pBulletFont->GetFamilyTypeMaybeAskConfig();
if (IsOpenSymbol(sFontName))
SubstituteBullet(sNumStr, eChrSet, sFontName);
SubstituteBullet(sNumStr, eChrSet, sFontName);
if (sFontName.isEmpty())
sFontName = pBulletFont->GetFamilyName();
@@ -688,15 +688,32 @@ void MSWordExportBase::SubstituteBullet( OUString& rNumStr,
{
if (!m_bSubstituteBullets)
return;
OUString sFontName = rFontName;
// If Bullet char is "", don't change
if (rNumStr[0] != u'\0')
if (rNumStr[0] == u'\0')
return;
OUString sFontName = rFontName;
// StarBats and StarMath are the old StarOffice symbol fonts. Their characters sit in the
// Unicode private use area, so a reader without those fonts installed gets no glyph at all.
// Recode the character to the matching OpenSymbol one, and the mapping below then finds a
// font that other office suites do have. The IMPORT flag picks the direction that goes from
// one of those two fonts to OpenSymbol, and it covers no other font.
if (FontToSubsFontConverter hConverter
= CreateFontToSubsFontConverter(sFontName, FontToSubsFontFlags::IMPORT))
{
rNumStr = rNumStr.replaceAt(0, 1, rtl::OUStringChar(
msfilter::util::bestFitOpenSymbolToMSFont(rNumStr[0], rChrSet, sFontName)));
ConvertFontToSubsFontChar(hConverter, rNumStr[0])));
sFontName = GetFontToSubsFontName(hConverter);
}
if (!IsOpenSymbol(sFontName))
return;
rNumStr = rNumStr.replaceAt(0, 1, rtl::OUStringChar(
msfilter::util::bestFitOpenSymbolToMSFont(rNumStr[0], rChrSet, sFontName)));
rFontName = sFontName;
}