summaryrefslogtreecommitdiff
path: root/svx/source
diff options
context:
space:
mode:
authorKhaled Hosny <khaled@aliftype.com>2022-12-16 00:10:34 +0200
committerخالد حسني <khaled@aliftype.com>2022-12-16 06:05:48 +0000
commit718af940435ae9d2ac90374e5880ecb38e96252c (patch)
tree7ddc8039bcf48e2c305629da97a57e0768dad058 /svx/source
parentbfecacb2487ba9470600e6f64056d9b1816ee96b (diff)
tdf#152533: Improve script handling in font preview
Use Edit Engine to get the script types instead of trying to duplicate (poorly) its behaviour. This has the advantage of handling weak characters and digits properly and is closer to what would happen in the document itself. We probably should go further and render the preview entirely using Edit Engine (since the current code fails short of proper bidi handling), but this is a bigger change. Change-Id: I975cb2d96a4a18dbd8110686ca09649cab0ec2f1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144284 Tested-by: Jenkins Reviewed-by: خالد حسني <khaled@aliftype.com>
Diffstat (limited to 'svx/source')
-rw-r--r--svx/source/dialog/fntctrl.cxx119
1 files changed, 49 insertions, 70 deletions
diff --git a/svx/source/dialog/fntctrl.cxx b/svx/source/dialog/fntctrl.cxx
index 393fc4e68103..0712bbe92496 100644
--- a/svx/source/dialog/fntctrl.cxx
+++ b/svx/source/dialog/fntctrl.cxx
@@ -23,10 +23,6 @@
#include <vcl/metric.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
-#include <unicode/uchar.h>
-#include <com/sun/star/uno/Reference.h>
-#include <com/sun/star/i18n/BreakIterator.hpp>
-#include <comphelper/processfactory.hxx>
#include <com/sun/star/i18n/ScriptType.hpp>
@@ -46,6 +42,7 @@
#include <svl/cjkoptions.hxx>
#include <svl/ctloptions.hxx>
+#include <editeng/editeng.hxx>
#include <editeng/colritem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/editids.hrc>
@@ -72,8 +69,6 @@
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
-using ::com::sun::star::i18n::XBreakIterator;
-using ::com::sun::star::i18n::BreakIterator;
// small helper functions to set fonts
@@ -127,6 +122,19 @@ OUString removeCRLF(const OUString& rText)
return rText.replace(0xa, ' ').replace(0xd, ' ').trim();
}
+struct ScriptInfo
+{
+ tools::Long textWidth;
+ SvtScriptType scriptType;
+ sal_Int32 changePos;
+ ScriptInfo(SvtScriptType scrptType, sal_Int32 position)
+ : textWidth(0)
+ , scriptType(scrptType)
+ , changePos(position)
+ {
+ }
+};
+
} // end anonymous namespace
class FontPrevWin_Impl
@@ -137,10 +145,7 @@ class FontPrevWin_Impl
VclPtr<Printer> mpPrinter;
bool mbDelPrinter;
- Reference <XBreakIterator> mxBreak;
- std::vector<tools::Long> maTextWidth;
- std::deque<sal_Int32> maScriptChg;
- std::vector<sal_uInt16> maScriptType;
+ std::vector<ScriptInfo> maScriptChanges;
SvxFont maCJKFont;
SvxFont maCTLFont;
OUString maText;
@@ -236,45 +241,18 @@ void FontPrevWin_Impl::CheckScript()
}
maScriptText = maText;
+ maScriptChanges.clear();
- maScriptChg.clear();
- maScriptType.clear();
- maTextWidth.clear();
+ auto aEditEngine = EditEngine(nullptr);
+ aEditEngine.SetText(maScriptText);
- if (!mxBreak.is())
+ auto aScript = aEditEngine.GetScriptType({ 0, 0, 0, 0 });
+ for (sal_Int32 i = 1; i <= maScriptText.getLength(); i++)
{
- Reference<XComponentContext> xContext = ::comphelper::getProcessComponentContext();
- mxBreak = BreakIterator::create(xContext);
- }
-
- sal_uInt16 nScript = 0;
- sal_Int32 nChg = 0;
-
- while (nChg < maText.getLength())
- {
- nScript = mxBreak->getScriptType(maText, nChg);
- nChg = mxBreak->endOfScript(maText, nChg, nScript);
- if (nChg < maText.getLength() && nChg > 0 &&
- (css::i18n::ScriptType::WEAK ==
- mxBreak->getScriptType(maText, nChg - 1)))
- {
- int8_t nType = u_charType(maText[nChg]);
- if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
- nType == U_COMBINING_SPACING_MARK)
- {
- maScriptChg.push_back(nChg - 1);
- }
- else
- {
- maScriptChg.push_back(nChg);
- }
- }
- else
- {
- maScriptChg.push_back(nChg);
- }
- maScriptType.push_back(nScript);
- maTextWidth.push_back(0);
+ auto aNextScript = aEditEngine.GetScriptType({ 0, i, 0, i });
+ if (aNextScript != aScript || i == maScriptText.getLength())
+ maScriptChanges.emplace_back(aScript, i);
+ aScript = aNextScript;
}
}
@@ -290,21 +268,21 @@ void FontPrevWin_Impl::CheckScript()
Size FontPrevWin_Impl::CalcTextSize(vcl::RenderContext& rRenderContext, OutputDevice const * _pPrinter, const SvxFont& rInFont)
{
- sal_uInt16 nScript;
+ SvtScriptType aScript;
sal_uInt16 nIdx = 0;
sal_Int32 nStart = 0;
sal_Int32 nEnd;
- size_t nCnt = maScriptChg.size();
+ size_t nCnt = maScriptChanges.size();
if (nCnt)
{
- nEnd = maScriptChg[nIdx];
- nScript = maScriptType[nIdx];
+ nEnd = maScriptChanges[nIdx].changePos;
+ aScript = maScriptChanges[nIdx].scriptType;
}
else
{
nEnd = maText.getLength();
- nScript = css::i18n::ScriptType::LATIN;
+ aScript = SvtScriptType::LATIN;
}
tools::Long nTxtWidth = 0;
tools::Long nCJKHeight = 0;
@@ -316,24 +294,24 @@ Size FontPrevWin_Impl::CalcTextSize(vcl::RenderContext& rRenderContext, OutputDe
do
{
- const SvxFont& rFont = (nScript == css::i18n::ScriptType::ASIAN) ?
+ const SvxFont& rFont = (aScript == SvtScriptType::ASIAN) ?
maCJKFont :
- ((nScript == css::i18n::ScriptType::COMPLEX) ?
+ ((aScript == SvtScriptType::COMPLEX) ?
maCTLFont :
rInFont);
tools::Long nWidth = rFont.GetTextSize(*_pPrinter, maText, nStart, nEnd - nStart).Width();
- if (nIdx >= maTextWidth.size())
+ if (nIdx >= maScriptChanges.size())
break;
- maTextWidth[nIdx++] = nWidth;
+ maScriptChanges[nIdx++].textWidth = nWidth;
nTxtWidth += nWidth;
- switch (nScript)
+ switch (aScript)
{
- case css::i18n::ScriptType::ASIAN:
+ case SvtScriptType::ASIAN:
calcFontHeightAnyAscent(rRenderContext, maCJKFont, nCJKHeight, nCJKAscent);
break;
- case css::i18n::ScriptType::COMPLEX:
+ case SvtScriptType::COMPLEX:
calcFontHeightAnyAscent(rRenderContext, maCTLFont, nCTLHeight, nCTLAscent);
break;
default:
@@ -343,8 +321,8 @@ Size FontPrevWin_Impl::CalcTextSize(vcl::RenderContext& rRenderContext, OutputDe
if (nEnd < maText.getLength() && nIdx < nCnt)
{
nStart = nEnd;
- nEnd = maScriptChg[nIdx];
- nScript = maScriptType[nIdx];
+ nEnd = maScriptChanges[nIdx].changePos;
+ aScript = maScriptChanges[nIdx].scriptType;
}
else
break;
@@ -383,38 +361,39 @@ Size FontPrevWin_Impl::CalcTextSize(vcl::RenderContext& rRenderContext, OutputDe
void FontPrevWin_Impl::DrawPrev(vcl::RenderContext& rRenderContext, Printer* _pPrinter, Point &rPt, const SvxFont& rInFont)
{
vcl::Font aOldFont = _pPrinter->GetFont();
- sal_uInt16 nScript;
+ SvtScriptType aScript;
sal_uInt16 nIdx = 0;
sal_Int32 nStart = 0;
sal_Int32 nEnd;
- size_t nCnt = maScriptChg.size();
+ size_t nCnt = maScriptChanges.size();
+
if (nCnt)
{
- nEnd = maScriptChg[nIdx];
- nScript = maScriptType[nIdx];
+ nEnd = maScriptChanges[nIdx].changePos;
+ aScript = maScriptChanges[nIdx].scriptType;
}
else
{
nEnd = maText.getLength();
- nScript = css::i18n::ScriptType::LATIN;
+ aScript = SvtScriptType::LATIN;
}
do
{
- const SvxFont& rFont = (nScript == css::i18n::ScriptType::ASIAN)
+ const SvxFont& rFont = (aScript == SvtScriptType::ASIAN)
? maCJKFont
- : ((nScript == css::i18n::ScriptType::COMPLEX)
+ : ((aScript == SvtScriptType::COMPLEX)
? maCTLFont
: rInFont);
_pPrinter->SetFont(rFont);
rFont.DrawPrev(&rRenderContext, _pPrinter, rPt, maText, nStart, nEnd - nStart);
- rPt.AdjustX(maTextWidth[nIdx++] );
+ rPt.AdjustX(maScriptChanges[nIdx++].textWidth);
if (nEnd < maText.getLength() && nIdx < nCnt)
{
nStart = nEnd;
- nEnd = maScriptChg[nIdx];
- nScript = maScriptType[nIdx];
+ nEnd = maScriptChanges[nIdx].changePos;
+ aScript = maScriptChanges[nIdx].scriptType;
}
else
break;