summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--canvas/source/cairo/cairo_textlayout.cxx2
-rw-r--r--canvas/source/directx/dx_textlayout_drawhelper.cxx1
-rw-r--r--canvas/source/vcl/textlayout.cxx1
-rw-r--r--drawinglayer/source/primitive2d/textbreakuphelper.cxx10
-rw-r--r--drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx7
-rw-r--r--drawinglayer/source/primitive2d/textlayoutdevice.cxx6
-rw-r--r--drawinglayer/source/primitive2d/textprimitive2d.cxx13
-rw-r--r--drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx1
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx3
-rw-r--r--drawinglayer/source/tools/emfphelperdata.cxx4
-rw-r--r--drawinglayer/source/tools/wmfemfhelper.cxx7
-rw-r--r--editeng/inc/editdoc.hxx4
-rw-r--r--editeng/source/editeng/editeng.cxx3
-rw-r--r--editeng/source/editeng/impedit3.cxx33
-rw-r--r--editeng/source/items/svxfont.cxx13
-rw-r--r--editeng/source/outliner/outleeng.cxx5
-rw-r--r--editeng/source/outliner/outleeng.hxx3
-rw-r--r--editeng/source/outliner/outliner.cxx9
-rw-r--r--emfio/source/reader/mtftools.cxx4
-rw-r--r--include/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx2
-rw-r--r--include/drawinglayer/primitive2d/textlayoutdevice.hxx3
-rw-r--r--include/drawinglayer/primitive2d/textprimitive2d.hxx8
-rw-r--r--include/editeng/editeng.hxx4
-rw-r--r--include/editeng/outliner.hxx7
-rw-r--r--include/editeng/svxfont.hxx3
-rw-r--r--include/vcl/metaact.hxx11
-rw-r--r--include/vcl/outdev.hxx12
-rw-r--r--include/vcl/pdfwriter.hxx1
-rw-r--r--include/vcl/rendercontext/SalLayoutFlags.hxx3
-rw-r--r--sc/source/ui/view/hintwin.cxx4
-rw-r--r--sd/source/ui/view/sdview.cxx1
-rw-r--r--sfx2/source/control/thumbnailviewitem.cxx1
-rw-r--r--svgio/source/svgreader/svgcharacternode.cxx2
-rw-r--r--svtools/source/control/ruler.cxx4
-rw-r--r--svx/source/diagram/IDiagramHelper.cxx3
-rw-r--r--svx/source/svdraw/svdotextdecomposition.cxx14
-rw-r--r--svx/source/svdraw/svdotextpathdecomposition.cxx5
-rw-r--r--svx/source/tbxctrls/StylesPreviewWindow.cxx3
-rw-r--r--sw/source/core/inc/scriptinfo.hxx2
-rw-r--r--sw/source/core/layout/paintfrm.cxx1
-rw-r--r--sw/source/core/text/itradj.cxx6
-rw-r--r--sw/source/core/text/porlay.cxx6
-rw-r--r--sw/source/core/text/portxt.cxx2
-rw-r--r--sw/source/core/txtnode/fntcache.cxx32
-rw-r--r--sw/source/uibase/docvw/HeaderFooterWin.cxx2
-rw-r--r--sw/source/uibase/docvw/UnfloatTableButton.cxx2
-rw-r--r--vcl/inc/ImplLayoutArgs.hxx2
-rw-r--r--vcl/inc/impglyphitem.hxx4
-rw-r--r--vcl/inc/pdf/pdfwriter_impl.hxx2
-rw-r--r--vcl/inc/sallayout.hxx2
-rw-r--r--vcl/qa/cppunit/complextext.cxx37
-rw-r--r--vcl/qa/cppunit/svm/svmtest.cxx2
-rw-r--r--vcl/qa/cppunit/text.cxx2
-rw-r--r--vcl/source/control/imp_listbox.cxx2
-rw-r--r--vcl/source/filter/eps/eps.cxx12
-rw-r--r--vcl/source/filter/svm/SvmConverter.cxx2
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx98
-rw-r--r--vcl/source/gdi/gdimtf.cxx4
-rw-r--r--vcl/source/gdi/impglyphitem.cxx25
-rw-r--r--vcl/source/gdi/metaact.cxx12
-rw-r--r--vcl/source/gdi/pdfwriter.cxx3
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx8
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx2
-rw-r--r--vcl/source/gdi/textlayout.cxx2
-rw-r--r--vcl/source/outdev/text.cxx42
-rw-r--r--vcl/source/outdev/transparent.cxx2
-rw-r--r--vcl/source/text/ImplLayoutArgs.cxx32
-rw-r--r--vcl/source/window/menuitemlist.cxx2
-rw-r--r--vcl/source/window/status.cxx2
69 files changed, 346 insertions, 228 deletions
diff --git a/canvas/source/cairo/cairo_textlayout.cxx b/canvas/source/cairo/cairo_textlayout.cxx
index cbbf02c5629d..2b48dd977d52 100644
--- a/canvas/source/cairo/cairo_textlayout.cxx
+++ b/canvas/source/cairo/cairo_textlayout.cxx
@@ -270,7 +270,7 @@ namespace cairocanvas
if (maLogicalAdvancements.hasElements())
{
- rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets,
+ rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets, {},
::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
}
diff --git a/canvas/source/directx/dx_textlayout_drawhelper.cxx b/canvas/source/directx/dx_textlayout_drawhelper.cxx
index 20ff8bd441c9..9e83b77ca901 100644
--- a/canvas/source/directx/dx_textlayout_drawhelper.cxx
+++ b/canvas/source/directx/dx_textlayout_drawhelper.cxx
@@ -215,6 +215,7 @@ namespace dxcanvas
xVirtualDevice->DrawTextArray( aEmptyPoint,
aText,
DXArray,
+ {},
rText.StartPosition,
rText.Length,
bIsRTL ? SalLayoutFlags::BiDiRtl : SalLayoutFlags::NONE);
diff --git a/canvas/source/vcl/textlayout.cxx b/canvas/source/vcl/textlayout.cxx
index 63a3453ff0c4..f628d155f3a7 100644
--- a/canvas/source/vcl/textlayout.cxx
+++ b/canvas/source/vcl/textlayout.cxx
@@ -344,6 +344,7 @@ namespace vclcanvas
rOutDev.DrawTextArray( rOutpos,
maText.Text,
aOffsets,
+ {},
::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
}
diff --git a/drawinglayer/source/primitive2d/textbreakuphelper.cxx b/drawinglayer/source/primitive2d/textbreakuphelper.cxx
index 5ca10ce633b6..8f92d9817a0e 100644
--- a/drawinglayer/source/primitive2d/textbreakuphelper.cxx
+++ b/drawinglayer/source/primitive2d/textbreakuphelper.cxx
@@ -58,6 +58,7 @@ namespace drawinglayer::primitive2d
// prepare values for new portion
basegfx::B2DHomMatrix aNewTransform;
std::vector< double > aNewDXArray;
+ std::vector< sal_Bool > aNewKashidaArray;
const bool bNewStartIsNotOldStart(nIndex > mrSource.getTextPosition());
if(!mbNoDXArray)
@@ -68,6 +69,13 @@ namespace drawinglayer::primitive2d
mrSource.getDXArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition()));
}
+ if(!mbNoDXArray && !mrSource.getKashidaArray().empty())
+ {
+ aNewKashidaArray = std::vector< sal_Bool >(
+ mrSource.getKashidaArray().begin() + (nIndex - mrSource.getTextPosition()),
+ mrSource.getKashidaArray().begin() + ((nIndex + nLength) - mrSource.getTextPosition()));
+ }
+
if(bNewStartIsNotOldStart)
{
// needs to be moved to a new start position
@@ -137,6 +145,7 @@ namespace drawinglayer::primitive2d
nIndex,
nLength,
std::move(aNewDXArray),
+ std::move(aNewKashidaArray),
mrSource.getFontAttribute(),
mrSource.getLocale(),
mrSource.getFontColor(),
@@ -168,6 +177,7 @@ namespace drawinglayer::primitive2d
nIndex,
nLength,
std::move(aNewDXArray),
+ std::move(aNewKashidaArray),
mrSource.getFontAttribute(),
mrSource.getLocale(),
mrSource.getFontColor()));
diff --git a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx
index 0db26fbeb28d..b14e6994f7c9 100644
--- a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx
@@ -36,6 +36,7 @@ namespace drawinglayer::primitive2d
sal_Int32 nTextPosition,
sal_Int32 nTextLength,
const std::vector< double >& rDXArray,
+ const std::vector< sal_Bool >& rKashidaArray,
const attribute::FontAttribute& rFontAttribute) const
{
// create the SimpleTextPrimitive needed in any case
@@ -46,6 +47,7 @@ namespace drawinglayer::primitive2d
nTextPosition,
nTextLength,
std::vector(rDXArray),
+ std::vector(rKashidaArray),
rFontAttribute,
getLocale(),
getFontColor())));
@@ -189,7 +191,7 @@ namespace drawinglayer::primitive2d
getFontAttribute().getBiDiStrong());
// handle as one word
- impCreateGeometryContent(aRetval, aDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), aNewFontAttribute);
+ impCreateGeometryContent(aRetval, aDecTrans, getText(), getTextPosition(), getTextLength(), getDXArray(), getKashidaArray(), aNewFontAttribute);
// Handle Shadow, Outline and TextRelief
if(!aRetval.empty())
@@ -294,6 +296,7 @@ namespace drawinglayer::primitive2d
sal_Int32 nTextPosition,
sal_Int32 nTextLength,
std::vector< double >&& rDXArray,
+ std::vector< sal_Bool >&& rKashidaArray,
const attribute::FontAttribute& rFontAttribute,
const css::lang::Locale& rLocale,
const basegfx::BColor& rFontColor,
@@ -312,7 +315,7 @@ namespace drawinglayer::primitive2d
bool bEmphasisMarkBelow,
TextRelief eTextRelief,
bool bShadow)
- : TextSimplePortionPrimitive2D(rNewTransform, rText, nTextPosition, nTextLength, std::move(rDXArray), rFontAttribute, rLocale, rFontColor, false, 0, rFillColor),
+ : TextSimplePortionPrimitive2D(rNewTransform, rText, nTextPosition, nTextLength, std::move(rDXArray), std::move(rKashidaArray), rFontAttribute, rLocale, rFontColor, false, 0, rFillColor),
maOverlineColor(rOverlineColor),
maTextlineColor(rTextlineColor),
meFontOverline(eFontOverline),
diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index f70f9f63b81d..78e0c23189ad 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -215,8 +215,8 @@ double TextLayouterDevice::getTextWidth(const OUString& rText, sal_uInt32 nIndex
void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector,
const OUString& rText, sal_uInt32 nIndex,
- sal_uInt32 nLength,
- const std::vector<double>& rDXArray) const
+ sal_uInt32 nLength, const std::vector<double>& rDXArray,
+ const std::vector<sal_Bool>& rKashidaArray) const
{
const sal_uInt32 nDXArrayCount(rDXArray.size());
sal_uInt32 nTextLength(nLength);
@@ -239,7 +239,7 @@ void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPoly
}
mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, nLength, 0,
- aIntegerDXArray);
+ aIntegerDXArray, rKashidaArray);
}
else
{
diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx
index 6330c89b9184..f60f73b21045 100644
--- a/drawinglayer/source/primitive2d/textprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx
@@ -132,13 +132,13 @@ void TextSimplePortionPrimitive2D::getTextOutlinesAndTransformation(
// get the text outlines
aTextLayouter.getTextOutlines(rTarget, getText(), getTextPosition(), getTextLength(),
- aScaledDXArray);
+ aScaledDXArray, getKashidaArray());
}
else
{
// get the text outlines
aTextLayouter.getTextOutlines(rTarget, getText(), getTextPosition(), getTextLength(),
- getDXArray());
+ getDXArray(), getKashidaArray());
}
// create primitives for the outlines
@@ -202,14 +202,16 @@ void TextSimplePortionPrimitive2D::create2DDecomposition(
TextSimplePortionPrimitive2D::TextSimplePortionPrimitive2D(
basegfx::B2DHomMatrix rNewTransform, OUString rText, sal_Int32 nTextPosition,
- sal_Int32 nTextLength, std::vector<double>&& rDXArray, attribute::FontAttribute aFontAttribute,
- css::lang::Locale aLocale, const basegfx::BColor& rFontColor, bool bFilled,
- tools::Long nWidthToFill, const Color& rTextFillColor)
+ sal_Int32 nTextLength, std::vector<double>&& rDXArray, std::vector<sal_Bool>&& rKashidaArray,
+ attribute::FontAttribute aFontAttribute, css::lang::Locale aLocale,
+ const basegfx::BColor& rFontColor, bool bFilled, tools::Long nWidthToFill,
+ const Color& rTextFillColor)
: maTextTransform(std::move(rNewTransform))
, maText(std::move(rText))
, mnTextPosition(nTextPosition)
, mnTextLength(nTextLength)
, maDXArray(std::move(rDXArray))
+ , maKashidaArray(std::move(rKashidaArray))
, maFontAttribute(std::move(aFontAttribute))
, maLocale(std::move(aLocale))
, maFontColor(rFontColor)
@@ -241,6 +243,7 @@ bool TextSimplePortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive)
&& getTextPosition() == rCompare.getTextPosition()
&& getTextLength() == rCompare.getTextLength()
&& getDXArray() == rCompare.getDXArray()
+ && getKashidaArray() == rCompare.getKashidaArray()
&& getFontAttribute() == rCompare.getFontAttribute()
&& LocalesAreEqual(getLocale(), rCompare.getLocale())
&& getFontColor() == rCompare.getFontColor() && mbFilled == rCompare.mbFilled
diff --git a/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx b/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx
index f7aedb3c9172..269be2d01817 100644
--- a/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.cxx
@@ -97,6 +97,7 @@ namespace drawinglayer::primitive2d
0,
len,
std::move(aDXArray),
+ {},
getFontAttribute(),
getLocale(),
getFontColor()));
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index 019feba35182..822800882d55 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -321,7 +321,8 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(
if (!aTransformedDXArray.empty())
{
- mpOutputDevice->DrawTextArray(aStartPoint, aText, aTransformedDXArray, nPos, nLen);
+ mpOutputDevice->DrawTextArray(aStartPoint, aText, aTransformedDXArray,
+ rTextCandidate.getKashidaArray(), nPos, nLen);
}
else
{
diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx
index 542259568cd0..e9b8422557a9 100644
--- a/drawinglayer/source/tools/emfphelperdata.cxx
+++ b/drawinglayer/source/tools/emfphelperdata.cxx
@@ -1683,6 +1683,7 @@ namespace emfplushelper
0, // text always starts at 0
stringLength,
std::move(emptyVector), // EMF-PLUS has no DX-array
+ {},
fontAttribute,
locale,
color.getBColor(), // Font Color
@@ -1702,6 +1703,7 @@ namespace emfplushelper
0, // text always starts at 0
stringLength,
std::move(emptyVector), // EMF-PLUS has no DX-array
+ {},
fontAttribute,
locale,
color.getBColor());
@@ -2195,6 +2197,7 @@ namespace emfplushelper
pos, // take character at current pos
aLength, // use determined length
std::move(aDXArray), // generated DXArray
+ {},
fontAttribute,
Application::GetSettings().GetLanguageTag().getLocale(),
color.getBColor(),
@@ -2214,6 +2217,7 @@ namespace emfplushelper
pos, // take character at current pos
aLength, // use determined length
std::move(aDXArray), // generated DXArray
+ {},
fontAttribute,
Application::GetSettings().GetLanguageTag().getLocale(),
color.getBColor());
diff --git a/drawinglayer/source/tools/wmfemfhelper.cxx b/drawinglayer/source/tools/wmfemfhelper.cxx
index f763cd887ff7..4ec6863eecea 100644
--- a/drawinglayer/source/tools/wmfemfhelper.cxx
+++ b/drawinglayer/source/tools/wmfemfhelper.cxx
@@ -1077,6 +1077,7 @@ namespace wmfemfhelper
sal_uInt16 nTextStart,
sal_uInt16 nTextLength,
std::vector< double >&& rDXArray,
+ std::vector< sal_Bool >&& rKashidaArray,
TargetHolder& rTarget,
PropertyHolder const & rProperty)
{
@@ -1161,6 +1162,7 @@ namespace wmfemfhelper
nTextStart,
nTextLength,
std::move(rDXArray),
+ std::move(rKashidaArray),
aFontAttribute,
aLocale,
aFontColor,
@@ -1189,6 +1191,7 @@ namespace wmfemfhelper
nTextStart,
nTextLength,
std::vector(rDXArray),
+ std::vector(rKashidaArray),
std::move(aFontAttribute),
std::move(aLocale),
aFontColor);
@@ -1770,6 +1773,7 @@ namespace wmfemfhelper
nTextIndex,
nTextLength,
std::move(aDXArray),
+ {},
rTargetHolders.Current(),
rPropertyHolders.Current());
}
@@ -1794,6 +1798,7 @@ namespace wmfemfhelper
// prepare DXArray (if used)
std::vector< double > aDXArray;
const std::vector<sal_Int32> & rDXArray = pA->GetDXArray();
+ std::vector< sal_Bool > aKashidaArray = pA->GetKashidaArray();
if(!rDXArray.empty())
{
@@ -1811,6 +1816,7 @@ namespace wmfemfhelper
nTextIndex,
nTextLength,
std::move(aDXArray),
+ std::move(aKashidaArray),
rTargetHolders.Current(),
rPropertyHolders.Current());
}
@@ -1874,6 +1880,7 @@ namespace wmfemfhelper
nTextIndex,
nTextLength,
std::move(aTextArray),
+ {},
rTargetHolders.Current(),
rPropertyHolders.Current());
}
diff --git a/editeng/inc/editdoc.hxx b/editeng/inc/editdoc.hxx
index 6ce00d05c40b..25a3dca4b1fc 100644
--- a/editeng/inc/editdoc.hxx
+++ b/editeng/inc/editdoc.hxx
@@ -463,6 +463,7 @@ public:
private:
CharPosArrayType aPositions;
+ std::vector<sal_Bool> aKashidaPositions;
sal_Int32 nTxtWidth;
sal_Int32 nStartPosX;
sal_Int32 nStart; // could be replaced by nStartPortion
@@ -531,6 +532,9 @@ public:
CharPosArrayType& GetCharPosArray() { return aPositions;}
const CharPosArrayType& GetCharPosArray() const { return aPositions;}
+ std::vector<sal_Bool>& GetKashidaArray() { return aKashidaPositions; }
+ const std::vector<sal_Bool>& GetKashidaArray() const { return aKashidaPositions; }
+
EditLine* Clone() const;
EditLine& operator = ( const EditLine& rLine );
diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx
index db4ae5db4491..88bc04a9efed 100644
--- a/editeng/source/editeng/editeng.cxx
+++ b/editeng/source/editeng/editeng.cxx
@@ -2465,7 +2465,8 @@ css::uno::Reference< css::datatransfer::XTransferable >
// ====================== Virtual Methods ========================
void EditEngine::DrawingText( const Point&, const OUString&, sal_Int32, sal_Int32,
- o3tl::span<const sal_Int32>, const SvxFont&, sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/,
+ o3tl::span<const sal_Int32>, o3tl::span<const sal_Bool>,
+ const SvxFont&, sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/,
const EEngineData::WrongSpellVector*, const SvxFieldData*, bool, bool,
const css::lang::Locale*, const Color&, const Color&)
diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx
index 143a763208e1..9d71560c108b 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -2147,6 +2147,10 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine,
nLastScript = nScript;
}
+ // Save the number of blanks, we will use it below when marking Kashida
+ // positions.
+ auto nBlankSize = aPositions.size();
+
// Kashidas ?
ImpFindKashidas( pNode, nFirstChar, nLastChar, aPositions );
@@ -2186,6 +2190,19 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine,
DBG_ASSERT( nSomeExtraSpace < static_cast<tools::Long>(nGaps), "AdjustBlocks: ExtraSpace too large" );
DBG_ASSERT( nSomeExtraSpace >= 0, "AdjustBlocks: ExtraSpace < 0 " );
+ // Mark Kashida positions, so that VCL knows where to insert Kashida and
+ // where to only expand the width.
+ if (aPositions.size() > nBlankSize)
+ {
+ pLine->GetKashidaArray().resize(pLine->GetCharPosArray().size(), false);
+ for (auto i = nBlankSize; i < aPositions.size(); i++)
+ {
+ auto nChar = aPositions[i];
+ if ( nChar < nLastChar )
+ pLine->GetKashidaArray()[nChar-nFirstChar] = 1 /*sal_True*/;
+ }
+ }
+
// Correct the positions in the Array and the portion widths:
// Last character won't be considered...
for (auto const& nChar : aPositions)
@@ -2202,7 +2219,6 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine,
rLastPortion.GetSize().AdjustWidth( 1 );
// Correct positions in array
- // Even for kashidas just change positions, VCL will then draw the kashida automatically
sal_Int32 nPortionEnd = nPortionStart + rLastPortion.GetLen();
for ( sal_Int32 _n = nChar; _n < nPortionEnd; _n++ )
{
@@ -3293,6 +3309,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
sal_Int32 nTextStart = 0;
sal_Int32 nTextLen = 0;
o3tl::span<const sal_Int32> pDXArray;
+ o3tl::span<const sal_Bool> pKashidaArray;
std::vector<sal_Int32> aTmpDXArray;
if ( rTextPortion.GetKind() == PortionKind::TEXT )
@@ -3303,6 +3320,12 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
pDXArray = o3tl::span(pLine->GetCharPosArray().data() + (nIndex - pLine->GetStart()),
pLine->GetCharPosArray().size() - (nIndex - pLine->GetStart()));
+ if (!pLine->GetKashidaArray().empty())
+ {
+ pKashidaArray = o3tl::span(pLine->GetKashidaArray().data() + (nIndex - pLine->GetStart()),
+ pLine->GetKashidaArray().size() - (nIndex - pLine->GetStart()));
+ }
+
// Paint control characters (#i55716#)
/* XXX: Given that there's special handling
* only for some specific characters
@@ -3552,7 +3575,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
ImplCalcDigitLang(aTmpFont.GetLanguage()));
// StripPortions() data callback
- GetEditEnginePtr()->DrawingText( aOutPos, aText, nTextStart, nTextLen, pDXArray,
+ GetEditEnginePtr()->DrawingText( aOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray,
aTmpFont, n, rTextPortion.GetRightToLeftLevel(),
!aWrongSpellVector.empty() ? &aWrongSpellVector : nullptr,
pFieldData,
@@ -3656,7 +3679,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
--nTextLen;
// output directly
- aTmpFont.QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray );
+ aTmpFont.QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray );
if ( bDrawFrame )
{
@@ -3792,7 +3815,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
const Color aTextLineColor(rOutDev.GetTextLineColor());
GetEditEnginePtr()->DrawingText(
- aTmpPos, OUString(), 0, 0, {},
+ aTmpPos, OUString(), 0, 0, {}, {},
aTmpFont, n, 0,
nullptr,
nullptr,
@@ -3841,7 +3864,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po
const Color aTextLineColor(rOutDev.GetTextLineColor());
GetEditEnginePtr()->DrawingText(
- aTmpPos, OUString(), 0, 0, {},
+ aTmpPos, OUString(), 0, 0, {}, {},
aTmpFont, n, 0,
nullptr,
nullptr,
diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx
index ca8c5f3fddc6..ac360873824a 100644
--- a/editeng/source/items/svxfont.cxx
+++ b/editeng/source/items/svxfont.cxx
@@ -545,21 +545,24 @@ Size SvxFont::GetTextSize(const OutputDevice& rOut, const OUString &rTxt,
static void DrawTextArray( OutputDevice* pOut, const Point& rStartPt, const OUString& rStr,
o3tl::span<const sal_Int32> pDXAry,
+ o3tl::span<const sal_Bool> pKashidaAry,
sal_Int32 nIndex, sal_Int32 nLen )
{
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen);
- pOut->DrawTextArray(rStartPt, rStr, pDXAry, nIndex, nLen, SalLayoutFlags::NONE, layoutGlyphs);
+ pOut->DrawTextArray(rStartPt, rStr, pDXAry, pKashidaAry, nIndex, nLen, SalLayoutFlags::NONE, layoutGlyphs);
}
void SvxFont::QuickDrawText( OutputDevice *pOut,
const Point &rPos, const OUString &rTxt,
- const sal_Int32 nIdx, const sal_Int32 nLen, o3tl::span<const sal_Int32> pDXArray ) const
+ const sal_Int32 nIdx, const sal_Int32 nLen,
+ o3tl::span<const sal_Int32> pDXArray,
+ o3tl::span<const sal_Bool> pKashidaArray) const
{
// Font has to be selected in OutputDevice...
if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() )
{
- DrawTextArray( pOut, rPos, rTxt, pDXArray, nIdx, nLen );
+ DrawTextArray( pOut, rPos, rTxt, pDXArray, pKashidaArray, nIdx, nLen );
return;
}
@@ -596,9 +599,9 @@ void SvxFont::QuickDrawText( OutputDevice *pOut,
else
{
if ( !IsCaseMap() )
- DrawTextArray( pOut, aPos, rTxt, pDXArray, nIdx, nLen );
+ DrawTextArray( pOut, aPos, rTxt, pDXArray, pKashidaArray, nIdx, nLen );
else
- DrawTextArray( pOut, aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen );
+ DrawTextArray( pOut, aPos, CalcCaseMap( rTxt ), pDXArray, pKashidaArray, nIdx, nLen );
}
}
}
diff --git a/editeng/source/outliner/outleeng.cxx b/editeng/source/outliner/outleeng.cxx
index e4fc414ad8e3..275636b6581e 100644
--- a/editeng/source/outliner/outleeng.cxx
+++ b/editeng/source/outliner/outleeng.cxx
@@ -141,7 +141,8 @@ OUString OutlinerEditEng::GetUndoComment( sal_uInt16 nUndoId ) const
}
void OutlinerEditEng::DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart, sal_Int32 nTextLen,
- o3tl::span<const sal_Int32> pDXArray, const SvxFont& rFont, sal_Int32 nPara, sal_uInt8 nRightToLeft,
+ o3tl::span<const sal_Int32> pDXArray, o3tl::span<const sal_Bool> pKashidaArray,
+ const SvxFont& rFont, sal_Int32 nPara, sal_uInt8 nRightToLeft,
const EEngineData::WrongSpellVector* pWrongSpellVector,
const SvxFieldData* pFieldData,
bool bEndOfLine,
@@ -150,7 +151,7 @@ void OutlinerEditEng::DrawingText( const Point& rStartPos, const OUString& rText
const Color& rOverlineColor,
const Color& rTextLineColor)
{
- pOwner->DrawingText(rStartPos,rText,nTextStart,nTextLen,pDXArray,rFont,nPara,nRightToLeft,
+ pOwner->DrawingText(rStartPos,rText,nTextStart,nTextLen,pDXArray,pKashidaArray,rFont,nPara,nRightToLeft,
pWrongSpellVector, pFieldData, bEndOfLine, bEndOfParagraph, false/*bEndOfBullet*/, pLocale, rOverlineColor, rTextLineColor);
}
diff --git a/editeng/source/outliner/outleeng.hxx b/editeng/source/outliner/outleeng.hxx
index 963e74582ec0..d19b54eba06a 100644
--- a/editeng/source/outliner/outleeng.hxx
+++ b/editeng/source/outliner/outleeng.hxx
@@ -44,7 +44,8 @@ public:
virtual void ParagraphConnected( sal_Int32 nLeftParagraph, sal_Int32 nRightParagraph ) override;
virtual void DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart,
- sal_Int32 nTextLen, o3tl::span<const sal_Int32> pDXArray, const SvxFont& rFont,
+ sal_Int32 nTextLen, o3tl::span<const sal_Int32> pDXArray,
+ o3tl::span<const sal_Bool> pKashidaArray, const SvxFont& rFont,
sal_Int32 nPara, sal_uInt8 nRightToLeft,
const EEngineData::WrongSpellVector* pWrongSpellVector,
const SvxFieldData* pFieldData,
diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx
index 4d67810c7a77..d7ea27662e77 100644
--- a/editeng/source/outliner/outliner.cxx
+++ b/editeng/source/outliner/outliner.cxx
@@ -974,7 +974,7 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point&
aTextPos.AdjustY( -(aMetric.GetDescent()) );
}
- DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), aBuf,
+ DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), aBuf, {},
aSvxFont, nPara, bRightToLeftPara ? 1 : 0, nullptr, nullptr, false, false, true, nullptr, Color(), Color());
}
else
@@ -1650,7 +1650,8 @@ void Outliner::StripPortions()
}
void Outliner::DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart,
- sal_Int32 nTextLen, o3tl::span<const sal_Int32> pDXArray,const SvxFont& rFont,
+ sal_Int32 nTextLen, o3tl::span<const sal_Int32> pDXArray,
+ o3tl::span<const sal_Bool> pKashidaArray, const SvxFont& rFont,
sal_Int32 nPara, sal_uInt8 nRightToLeft,
const EEngineData::WrongSpellVector* pWrongSpellVector,
const SvxFieldData* pFieldData,
@@ -1663,7 +1664,7 @@ void Outliner::DrawingText( const Point& rStartPos, const OUString& rText, sal_I
{
if(aDrawPortionHdl.IsSet())
{
- DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, pDXArray, pWrongSpellVector,
+ DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, pDXArray, pKashidaArray, pWrongSpellVector,
pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, false, 0, bEndOfLine, bEndOfParagraph, bEndOfBullet);
aDrawPortionHdl.Call( &aInfo );
@@ -1676,7 +1677,7 @@ void Outliner::DrawingTab( const Point& rStartPos, tools::Long nWidth, const OUS
{
if(aDrawPortionHdl.IsSet())
{
- DrawPortionInfo aInfo( rStartPos, rChar, 0, rChar.getLength(), rFont, nPara, {}, nullptr,
+ DrawPortionInfo aInfo( rStartPos, rChar, 0, rChar.getLength(), rFont, nPara, {}, {}, nullptr,
nullptr, nullptr, rOverlineColor, rTextLineColor, nRightToLeft, true, nWidth, bEndOfLine, bEndOfParagraph, false);
aDrawPortionHdl.Call( &aInfo );
diff --git a/emfio/source/reader/mtftools.cxx b/emfio/source/reader/mtftools.cxx
index 67dfdbeaedf0..95c51188bc3f 100644
--- a/emfio/source/reader/mtftools.cxx
+++ b/emfio/source/reader/mtftools.cxx
@@ -1828,7 +1828,7 @@ namespace emfio
{
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] ), o3tl::span<const sal_Int32>{}, 0, 1 ) );
+ mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition + aCharDisplacement, OUString( rText[i] ), o3tl::span<const sal_Int32>{}, {}, 0, 1 ) );
}
}
else
@@ -1859,7 +1859,7 @@ namespace emfio
pVDev->GetTextArray( rText, &aMyDXArray, 0, rText.getLength());
pDX = aMyDXArray;
}
- mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, rText.getLength() ) );
+ mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, {}, 0, rText.getLength() ) );
}
}
SetGfxMode( nOldGfxMode );
diff --git a/include/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx b/include/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx
index 1a4d821c7e60..73663ff95d32 100644
--- a/include/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx
@@ -63,6 +63,7 @@ namespace drawinglayer::primitive2d
sal_Int32 nTextPosition,
sal_Int32 nTextLength,
const ::std::vector< double >& rDXArray,
+ const ::std::vector< sal_Bool >& rKashidaArray,
const attribute::FontAttribute& rFontAttribute) const;
/// local decomposition.
@@ -77,6 +78,7 @@ namespace drawinglayer::primitive2d
sal_Int32 nTextPosition,
sal_Int32 nTextLength,
std::vector< double >&& rDXArray,
+ std::vector< sal_Bool >&& rKashidaArray,
const attribute::FontAttribute& rFontAttribute,
const css::lang::Locale& rLocale,
const basegfx::BColor& rFontColor,
diff --git a/include/drawinglayer/primitive2d/textlayoutdevice.hxx b/include/drawinglayer/primitive2d/textlayoutdevice.hxx
index 93587769c449..6348de0ddd25 100644
--- a/include/drawinglayer/primitive2d/textlayoutdevice.hxx
+++ b/include/drawinglayer/primitive2d/textlayoutdevice.hxx
@@ -84,7 +84,8 @@ public:
double getTextWidth(const OUString& rText, sal_uInt32 nIndex, sal_uInt32 nLength) const;
void getTextOutlines(basegfx::B2DPolyPolygonVector&, const OUString& rText, sal_uInt32 nIndex,
- sal_uInt32 nLength, const ::std::vector<double>& rDXArray) const;
+ sal_uInt32 nLength, const ::std::vector<double>& rDXArray,
+ const ::std::vector<sal_Bool>& rKashidaArray) const;
basegfx::B2DRange getTextBoundRect(const OUString& rText, sal_uInt32 nIndex,
sal_uInt32 nLength) const;
diff --git a/include/drawinglayer/primitive2d/textprimitive2d.hxx b/include/drawinglayer/primitive2d/textprimitive2d.hxx
index fd80e531e910..4182b0c0fbe4 100644
--- a/include/drawinglayer/primitive2d/textprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/textprimitive2d.hxx
@@ -72,6 +72,9 @@ namespace drawinglayer::primitive2d
point in FontCoordinateSystem X-Direction (given by maTextTransform) to the start
point of the second character
+ @param rKashidaArray
+ The Kashida insertion positions.
+
@param rFontAttribute
The font definition
@@ -107,6 +110,9 @@ private:
/// The DX array in logic units
std::vector<double> maDXArray;
+ /// The Kashida array
+ std::vector<sal_Bool> maKashidaArray;
+
/// The font definition
attribute::FontAttribute maFontAttribute;
@@ -139,6 +145,7 @@ public:
TextSimplePortionPrimitive2D(basegfx::B2DHomMatrix aNewTransform, OUString aText,
sal_Int32 nTextPosition, sal_Int32 nTextLength,
std::vector<double>&& rDXArray,
+ std::vector<sal_Bool>&& rKashidaArray,
attribute::FontAttribute aFontAttribute, css::lang::Locale aLocale,
const basegfx::BColor& rFontColor, bool bFilled = false,
tools::Long nWidthToFill = 0,
@@ -156,6 +163,7 @@ public:
sal_Int32 getTextPosition() const { return mnTextPosition; }
sal_Int32 getTextLength() const { return mnTextLength; }
const ::std::vector<double>& getDXArray() const { return maDXArray; }
+ const ::std::vector<sal_Bool>& getKashidaArray() const { return maKashidaArray; }
const attribute::FontAttribute& getFontAttribute() const { return maFontAttribute; }
const css::lang::Locale& getLocale() const { return maLocale; }
const basegfx::BColor& getFontColor() const { return maFontColor; }
diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx
index a0ce29ca26d1..ae0990666ded 100644
--- a/include/editeng/editeng.hxx
+++ b/include/editeng/editeng.hxx
@@ -498,7 +498,9 @@ public:
virtual void DrawingText( const Point& rStartPos, const OUString& rText,
sal_Int32 nTextStart, sal_Int32 nTextLen,
- o3tl::span<const sal_Int32> pDXArray, const SvxFont& rFont,
+ o3tl::span<const sal_Int32> pDXArray,
+ o3tl::span<const sal_Bool> pKashidaArray,
+ const SvxFont& rFont,
sal_Int32 nPara, sal_uInt8 nRightToLeft,
const EEngineData::WrongSpellVector* pWrongSpellVector,
const SvxFieldData* pFieldData,
diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx
index 6e19aa129a78..3326a3d6662b 100644
--- a/include/editeng/outliner.hxx
+++ b/include/editeng/outliner.hxx
@@ -401,6 +401,7 @@ public:
sal_Int32 mnPara;
const SvxFont& mrFont;
o3tl::span<const sal_Int32> mpDXArray;
+ o3tl::span<const sal_Bool> mpKashidaArray;
const EEngineData::WrongSpellVector* mpWrongSpellVector;
const SvxFieldData* mpFieldData;
@@ -427,6 +428,7 @@ public:
const SvxFont& rFnt,
sal_Int32 nPar,
o3tl::span<const sal_Int32> pDXArr,
+ o3tl::span<const sal_Bool> pKashidaArr,
const EEngineData::WrongSpellVector* pWrongSpellVector,
const SvxFieldData* pFieldData,
const css::lang::Locale* pLocale,
@@ -445,6 +447,7 @@ public:
mnPara(nPar),
mrFont(rFnt),
mpDXArray(pDXArr),
+ mpKashidaArray(pKashidaArr),
mpWrongSpellVector(pWrongSpellVector),
mpFieldData(pFieldData),
mpLocale(pLocale),
@@ -818,7 +821,9 @@ public:
void DrawingText( const Point& rStartPos, const OUString& rText,
sal_Int32 nTextStart, sal_Int32 nTextLen,
- o3tl::span<const sal_Int32> pDXArray, const SvxFont& rFont,
+ o3tl::span<const sal_Int32> pDXArray,
+ o3tl::span<const sal_Bool> pKashidaArray,
+ const SvxFont& rFont,
sal_Int32 nPara, sal_uInt8 nRightToLeft,
const EEngineData::WrongSpellVector* pWrongSpellVector,
const SvxFieldData* pFieldData,
diff --git a/include/editeng/svxfont.hxx b/include/editeng/svxfont.hxx
index e0f92c57289d..ac4ec390128a 100644
--- a/include/editeng/svxfont.hxx
+++ b/include/editeng/svxfont.hxx
@@ -96,7 +96,8 @@ public:
void QuickDrawText( OutputDevice *pOut, const Point &rPos, const OUString &rTxt,
const sal_Int32 nIdx = 0, const sal_Int32 nLen = SAL_MAX_INT32,
- o3tl::span<const sal_Int32> pDXArray = {} ) const;
+ o3tl::span<const sal_Int32> pDXArray = {},
+ o3tl::span<const sal_Bool> pKashidaArray = {} ) const;
Size QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt,
const sal_Int32 nIdx, const sal_Int32 nLen,
diff --git a/include/vcl/metaact.hxx b/include/vcl/metaact.hxx
index 37c3db3d9273..11caf48b2429 100644
--- a/include/vcl/metaact.hxx
+++ b/include/vcl/metaact.hxx
@@ -507,6 +507,7 @@ private:
Point maStartPt;
OUString maStr;
std::vector<sal_Int32> maDXAry;
+ std::vector<sal_Bool> maKashidaAry;
sal_Int32 mnIndex;
sal_Int32 mnLen;
@@ -516,10 +517,14 @@ public:
MetaTextArrayAction();
MetaTextArrayAction( const MetaTextArrayAction& rAction );
MetaTextArrayAction( const Point& rStartPt, OUString aStr,
- std::vector<sal_Int32> rDXAry, sal_Int32 nIndex,
+ std::vector<sal_Int32> rDXAry,
+ std::vector<sal_Bool> pKashidaAry,
+ sal_Int32 nIndex,
sal_Int32 nLen );
MetaTextArrayAction( const Point& rStartPt, OUString aStr,
- o3tl::span<const sal_Int32> pDXAry, sal_Int32 nIndex,
+ o3tl::span<const sal_Int32> pDXAry,
+ o3tl::span<const sal_Bool> pKashidaAry,
+ sal_Int32 nIndex,
sal_Int32 nLen );
virtual void Execute( OutputDevice* pOut ) override;
@@ -534,11 +539,13 @@ public:
sal_Int32 GetIndex() const { return mnIndex; }
sal_Int32 GetLen() const { return mnLen; }
const std::vector<sal_Int32> & GetDXArray() const { return maDXAry; }
+ const std::vector<sal_Bool> & GetKashidaArray() const { return maKashidaAry; }
void SetPoint(const Point& rPt) { maStartPt = rPt; }
void SetText(const OUString& rStr) { maStr = rStr; }
void SetIndex(sal_Int32 rIndex) { mnIndex = rIndex; }
void SetLen(sal_Int32 rLen) { mnLen = rLen; }
void SetDXArray(std::vector<sal_Int32> aArray);
+ void SetKashidaArray(std::vector<sal_Bool> aArray);
};
class SAL_DLLPUBLIC_RTTI MetaStretchTextAction final : public MetaAction
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 2595415db1b5..af55ebd3d614 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -963,6 +963,7 @@ public:
bool GetTextBoundRect( tools::Rectangle& rRect,
const OUString& rStr, sal_Int32 nBase = 0, sal_Int32 nIndex = 0, sal_Int32 nLen = -1,
sal_uLong nLayoutWidth = 0, o3tl::span<const sal_Int32> pDXArray = {},
+ o3tl::span<const sal_Bool> pKashidaArray = {},
const SalLayoutGlyphs* pGlyphs = nullptr ) const;
tools::Rectangle ImplGetTextBoundRect( const SalLayout& ) const;
@@ -973,12 +974,14 @@ public:
bool GetTextOutlines( PolyPolyVector&,
const OUString& rStr, sal_Int32 nBase = 0, sal_Int32 nIndex = 0,
sal_Int32 nLen = -1,
- sal_uLong nLayoutWidth = 0, o3tl::span<const sal_Int32> pDXArray = {} ) const;
+ sal_uLong nLayoutWidth = 0, o3tl::span<const sal_Int32> pDXArray = {},
+ o3tl::span<const sal_Bool> pKashidaArray = {} ) const;
bool GetTextOutlines( basegfx::B2DPolyPolygonVector &rVector,
const OUString& rStr, sal_Int32 nBase, sal_Int32 nIndex = 0,
sal_Int32 nLen = -1,
- sal_uLong nLayoutWidth = 0, o3tl::span<const sal_Int32> pDXArray = {} ) const;
+ sal_uLong nLayoutWidth = 0, o3tl::span<const sal_Int32> pDXArray = {},
+ o3tl::span<const sal_Bool> pKashidaArray = {} ) const;
OUString GetEllipsisString( const OUString& rStr, tools::Long nMaxWidth,
@@ -1044,6 +1047,7 @@ public:
void DrawTextArray( const Point& rStartPt, const OUString& rStr,
o3tl::span<const sal_Int32> pDXAry,
+ o3tl::span<const sal_Bool> pKashidaAry={},
sal_Int32 nIndex = 0,
sal_Int32 nLen = -1,
SalLayoutFlags flags = SalLayoutFlags::NONE,
@@ -1236,7 +1240,9 @@ public:
std::unique_ptr<SalLayout>
ImplLayout( const OUString&, sal_Int32 nIndex, sal_Int32 nLen,
const Point& rLogicPos = Point(0,0), tools::Long nLogicWidth=0,
- o3tl::span<const sal_Int32> pLogicDXArray={}, SalLayoutFlags flags = SalLayoutFlags::NONE,
+ o3tl::span<const sal_Int32> pLogicDXArray={},
+ o3tl::span<const sal_Bool> pKashidaArray={},
+ SalLayoutFlags flags = SalLayoutFlags::NONE,
vcl::text::TextLayoutCache const* = nullptr,
const SalLayoutGlyphs* pGlyphs = nullptr) const;
diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx
index 8764f3f49c8e..0c2cbb6294dd 100644
--- a/include/vcl/pdfwriter.hxx
+++ b/include/vcl/pdfwriter.hxx
@@ -764,6 +764,7 @@ The following structure describes the permissions used in PDF security
FontLineStyle eOverline );
void DrawTextArray( const Point& rStartPt, const OUString& rStr,
o3tl::span<const sal_Int32> pDXAry,
+ o3tl::span<const sal_Bool> pKashidaAry,
sal_Int32 nIndex,
sal_Int32 nLen );
void DrawStretchText( const Point& rStartPt, sal_uLong nWidth,
diff --git a/include/vcl/rendercontext/SalLayoutFlags.hxx b/include/vcl/rendercontext/SalLayoutFlags.hxx
index 68c26cadb48b..e8c5901d8528 100644
--- a/include/vcl/rendercontext/SalLayoutFlags.hxx
+++ b/include/vcl/rendercontext/SalLayoutFlags.hxx
@@ -30,13 +30,12 @@ enum class SalLayoutFlags
DisableKerning = 0x0010,
KerningAsian = 0x0020,
Vertical = 0x0040,
- KashidaJustification = 0x0800,
ForFallback = 0x2000,
GlyphItemsOnly = 0x4000,
};
namespace o3tl
{
-template <> struct typed_flags<SalLayoutFlags> : is_typed_flags<SalLayoutFlags, 0x6877>
+template <> struct typed_flags<SalLayoutFlags> : is_typed_flags<SalLayoutFlags, 0x6077>
{
};
}
diff --git a/sc/source/ui/view/hintwin.cxx b/sc/source/ui/view/hintwin.cxx
index 1dc76d139dd0..d57d8e0b787f 100644
--- a/sc/source/ui/view/hintwin.cxx
+++ b/sc/source/ui/view/hintwin.cxx
@@ -83,7 +83,7 @@ drawinglayer::primitive2d::Primitive2DContainer ScOverlayHint::createOverlaySequ
rtl::Reference<drawinglayer::primitive2d::TextSimplePortionPrimitive2D> pTitle =
new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
aTextMatrix, m_aTitle, 0, m_aTitle.getLength(),
- std::vector<double>(), std::move(aFontAttr), css::lang::Locale(),
+ std::vector<double>(), {}, std::move(aFontAttr), css::lang::Locale(),
rColor.getBColor());
Point aTextStart(nLeft + aHintMargin.Width() + aIndent.Width(),
@@ -123,7 +123,7 @@ drawinglayer::primitive2d::Primitive2DContainer ScOverlayHint::createOverlaySequ
rtl::Reference<drawinglayer::primitive2d::TextSimplePortionPrimitive2D> pMessage =
new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
aTextMatrix, aLine, 0, aLine.getLength(),
- std::vector<double>(), aFontAttr, css::lang::Locale(),
+ std::vector<double>(), {}, aFontAttr, css::lang::Locale(),
rColor.getBColor());
rRange.expand(pMessage->getB2DRange(aDummy));
diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx
index 429a8c408753..7099977b31cf 100644
--- a/sd/source/ui/view/sdview.cxx
+++ b/sd/source/ui/view/sdview.cxx
@@ -430,6 +430,7 @@ void ViewRedirector::createRedirectedPrimitive2DSequence(
0,
nTextLength,
std::move(aDXArray),
+ {},
std::move(aFontAttribute),
std::move(aLocale),
aRGBColor));
diff --git a/sfx2/source/control/thumbnailviewitem.cxx b/sfx2/source/control/thumbnailviewitem.cxx
index 36a33edc086b..9b75120289be 100644
--- a/sfx2/source/control/thumbnailviewitem.cxx
+++ b/sfx2/source/control/thumbnailviewitem.cxx
@@ -269,6 +269,7 @@ void ThumbnailViewItem::addTextPrimitives (const OUString& rText, const Thumbnai
new TextSimplePortionPrimitive2D(aTextMatrix,
aText, nLineStart, nLineLength,
std::vector<double>(),
+ {},
pAttrs->aFontAttr,
css::lang::Locale(),
aTextColor));
diff --git a/svgio/source/svgreader/svgcharacternode.cxx b/svgio/source/svgreader/svgcharacternode.cxx
index 581129cf1025..0a4731b200d5 100644
--- a/svgio/source/svgreader/svgcharacternode.cxx
+++ b/svgio/source/svgreader/svgcharacternode.cxx
@@ -452,6 +452,7 @@ namespace svgio::svgreader
nIndex,
nLength,
std::move(aTextArray),
+ {},
aFontAttribute,
aLocale,
aFill,
@@ -480,6 +481,7 @@ namespace svgio::svgreader
nIndex,
nLength,
std::move(aTextArray),
+ {},
aFontAttribute,
aLocale,
aFill);
diff --git a/svtools/source/control/ruler.cxx b/svtools/source/control/ruler.cxx
index 07e030aac109..340d29b27cfc 100644
--- a/svtools/source/control/ruler.cxx
+++ b/svtools/source/control/ruler.cxx
@@ -79,7 +79,7 @@ SalLayoutGlyphs* lcl_GetRulerTextGlyphs(const vcl::RenderContext& rRenderContext
// Calculate glyph items.
std::unique_ptr<SalLayout> pLayout = rRenderContext.ImplLayout(
- rText, 0, rText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ rText, 0, rText.getLength(), Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly);
if (!pLayout)
return nullptr;
@@ -339,7 +339,7 @@ void Ruler::ImplVDrawText(vcl::RenderContext& rRenderContext, tools::Long nX, to
tools::Rectangle aRect;
SalLayoutGlyphs* pTextLayout
= lcl_GetRulerTextGlyphs(rRenderContext, rText, maTextGlyphs[rText]);
- rRenderContext.GetTextBoundRect(aRect, rText, 0, 0, -1, 0, {}, pTextLayout);
+ rRenderContext.GetTextBoundRect(aRect, rText, 0, 0, -1, 0, {}, {}, pTextLayout);
tools::Long nShiftX = ( aRect.GetWidth() / 2 ) + aRect.Left();
tools::Long nShiftY = ( aRect.GetHeight() / 2 ) + aRect.Top();
diff --git a/svx/source/diagram/IDiagramHelper.cxx b/svx/source/diagram/IDiagramHelper.cxx
index 672c7485540a..ad1db2334d68 100644
--- a/svx/source/diagram/IDiagramHelper.cxx
+++ b/svx/source/diagram/IDiagramHelper.cxx
@@ -167,7 +167,8 @@ void OverlayDiagramPrimitive::create2DDecomposition(
aName,
0,
aName.getLength(),
- aDXArray);
+ aDXArray,
+ {});
// put into one PolyPolygon (also simplification - overlapping chars
// may create XOR gaps, so these exist for a reason, but low probability)
diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx
index 666c20d48f5a..f5955eb7d869 100644
--- a/svx/source/svdraw/svdotextdecomposition.cxx
+++ b/svx/source/svdraw/svdotextdecomposition.cxx
@@ -234,6 +234,18 @@ namespace
}
}
+ ::std::vector< sal_Bool > aKashidaArray;
+
+ if(!rInfo.mpKashidaArray.empty() && rInfo.mnTextLen)
+ {
+ aKashidaArray.reserve(rInfo.mnTextLen);
+
+ for(sal_Int32 a=0; a < rInfo.mnTextLen; a++)
+ {
+ aKashidaArray.push_back(rInfo.mpKashidaArray[a]);
+ }
+ }
+
// create complex text primitive and append
const Color aFontColor(rInfo.mrFont.GetColor());
const basegfx::BColor aBFontColor(aFontColor.getBColor());
@@ -316,6 +328,7 @@ namespace
rInfo.mnTextStart,
rInfo.mnTextLen,
std::vector(aDXArray),
+ std::vector(aKashidaArray),
aFontAttribute,
rInfo.mpLocale ? *rInfo.mpLocale : css::lang::Locale(),
aBFontColor,
@@ -344,6 +357,7 @@ namespace
rInfo.mnTextStart,
rInfo.mnTextLen,
std::vector(aDXArray),
+ std::vector(aKashidaArray),
std::move(aFontAttribute),
rInfo.mpLocale ? *rInfo.mpLocale : css::lang::Locale(),
aBFontColor,
diff --git a/svx/source/svdraw/svdotextpathdecomposition.cxx b/svx/source/svdraw/svdotextpathdecomposition.cxx
index 99a7169c1fe6..7537625b2a26 100644
--- a/svx/source/svdraw/svdotextpathdecomposition.cxx
+++ b/svx/source/svdraw/svdotextpathdecomposition.cxx
@@ -58,6 +58,7 @@ namespace
sal_Int32 mnParagraph;
SvxFont maFont;
::std::vector< double > maDblDXArray; // double DXArray, font size independent -> unit coordinate system
+ ::std::vector< sal_Bool > maKashidaArray;
lang::Locale maLocale;
bool mbRTL : 1;
@@ -70,6 +71,7 @@ namespace
mnTextLength(rInfo.mnTextLen),
mnParagraph(rInfo.mnPara),
maFont(rInfo.mrFont),
+ maKashidaArray(rInfo.mpKashidaArray.begin(), rInfo.mpKashidaArray.end()),
maLocale(rInfo.mpLocale ? *rInfo.mpLocale : lang::Locale()),
mbRTL(!rInfo.mrFont.IsVertical() && rInfo.IsRTL())
{
@@ -107,6 +109,7 @@ namespace
const SvxFont& getFont() const { return maFont; }
bool isRTL() const { return mbRTL; }
const ::std::vector< double >& getDoubleDXArray() const { return maDblDXArray; }
+ const ::std::vector< sal_Bool >& getKashidaArray() const { return maKashidaArray; }
const lang::Locale& getLocale() const { return maLocale; }
sal_Int32 getPortionIndex(sal_Int32 nIndex, sal_Int32 nLength) const
@@ -497,6 +500,7 @@ namespace
nPortionIndex,
nNextGlyphLen,
std::vector(aNewDXArray),
+ std::vector(pCandidate->getKashidaArray()),
aCandidateFontAttribute,
pCandidate->getLocale(),
aRGBShadowColor) );
@@ -514,6 +518,7 @@ namespace
nPortionIndex,
nNextGlyphLen,
std::move(aNewDXArray),
+ std::vector(pCandidate->getKashidaArray()),
aCandidateFontAttribute,
pCandidate->getLocale(),
aRGBColor) );
diff --git a/svx/source/tbxctrls/StylesPreviewWindow.cxx b/svx/source/tbxctrls/StylesPreviewWindow.cxx
index 3ad9fa780117..8f5dfea0b2c8 100644
--- a/svx/source/tbxctrls/StylesPreviewWindow.cxx
+++ b/svx/source/tbxctrls/StylesPreviewWindow.cxx
@@ -358,7 +358,8 @@ void StyleItemController::DrawText(vcl::RenderContext& rRenderContext)
const SalLayoutGlyphs* layoutGlyphs
= SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&rRenderContext, m_aStyleName.second);
tools::Rectangle aTextRect;
- rRenderContext.GetTextBoundRect(aTextRect, m_aStyleName.second, 0, 0, -1, 0, {}, layoutGlyphs);
+ rRenderContext.GetTextBoundRect(aTextRect, m_aStyleName.second, 0, 0, -1, 0, {}, {},
+ layoutGlyphs);
Point aPos(0, 0);
aPos.AdjustX(LEFT_MARGIN);
diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx
index cfe9ef3e55fb..ee536803a617 100644
--- a/sw/source/core/inc/scriptinfo.hxx
+++ b/sw/source/core/inc/scriptinfo.hxx
@@ -289,7 +289,7 @@ public:
The value which has to be added to a kashida opportunity.
@return The number of kashida opportunities in the given range
*/
- sal_Int32 KashidaJustify( sal_Int32* pKernArray,
+ sal_Int32 KashidaJustify( sal_Int32* pKernArray, sal_Bool* pKashidaArray,
TextFrameIndex nStt, TextFrameIndex nLen, tools::Long nSpaceAdd = 0) const;
/** Clears array of kashidas marked as invalid
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 1c9fde902730..dd76c8609fda 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -3782,6 +3782,7 @@ void SwColumnFrame::PaintBreak( ) const
aTextMatrix,
aBreakText, 0, aBreakText.getLength(),
std::vector< double >(),
+ {},
std::move(aFontAttr),
lang::Locale(),
aLineColor ) );
diff --git a/sw/source/core/text/itradj.cxx b/sw/source/core/text/itradj.cxx
index a952ce7649c2..b248f20f4785 100644
--- a/sw/source/core/text/itradj.cxx
+++ b/sw/source/core/text/itradj.cxx
@@ -122,7 +122,7 @@ static bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTextSizeInfo& rInf,
// total number of kashida positions, or the number of kashida positions after some positions
// have been dropped.
// Here we want the clean total, which is OK: We have called ClearKashidaInvalid() before.
- rKashidas = rSI.KashidaJustify(nullptr, rItr.GetStart(), rItr.GetLength());
+ rKashidas = rSI.KashidaJustify(nullptr, nullptr, rItr.GetStart(), rItr.GetLength());
if (rKashidas <= 0) // nothing to do
return true;
@@ -147,7 +147,7 @@ static bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTextSizeInfo& rInf,
if (nNext == TextFrameIndex(COMPLETE_STRING) || nNext > nEnd)
nNext = nEnd;
- sal_Int32 nKashidasInAttr = rSI.KashidaJustify(nullptr, nIdx, nNext - nIdx);
+ sal_Int32 nKashidasInAttr = rSI.KashidaJustify(nullptr, nullptr, nIdx, nNext - nIdx);
if (nKashidasInAttr > 0)
{
// Kashida glyph looks suspicious, skip Kashida justification
@@ -212,7 +212,7 @@ static bool lcl_CheckKashidaWidth ( SwScriptInfo& rSI, SwTextSizeInfo& rInf, SwT
if (nNext == TextFrameIndex(COMPLETE_STRING) || nNext > nEnd)
nNext = nEnd;
- sal_Int32 nKashidasInAttr = rSI.KashidaJustify(nullptr, nIdx, nNext - nIdx);
+ sal_Int32 nKashidasInAttr = rSI.KashidaJustify(nullptr, nullptr, nIdx, nNext - nIdx);
tools::Long nFontMinKashida = rInf.GetOut()->GetMinKashida();
if ( nFontMinKashida && nKashidasInAttr > 0 && SwScriptInfo::IsArabicText( rInf.GetText(), nIdx, nNext - nIdx ) )
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 30abc01703f1..3db6a07600e9 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -2231,6 +2231,7 @@ tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, T
// have been dropped, depending on the state of the m_KashidaInvalid set.
sal_Int32 SwScriptInfo::KashidaJustify( sal_Int32* pKernArray,
+ sal_Bool* pKashidaArray,
TextFrameIndex const nStt,
TextFrameIndex const nLen,
tools::Long nSpaceAdd ) const
@@ -2286,6 +2287,11 @@ sal_Int32 SwScriptInfo::KashidaJustify( sal_Int32* pKernArray,
{
TextFrameIndex nArrayPos = nIdx - nStt;
+ // mark Kashida insertion positions, code in VCL will use this
+ // array to know where to insert Kashida.
+ if (pKashidaArray)
+ pKashidaArray[sal_Int32(nArrayPos)] = true;
+
// next kashida position
++nCntKash;
while (nCntKash < nCntKashEnd && !IsKashidaValid(nCntKash))
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index c0f66496f134..09a2fc2c0b67 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -113,7 +113,7 @@ static TextFrameIndex lcl_AddSpace(const SwTextSizeInfo &rInf,
{
if ( SwScriptInfo::IsArabicText( *pStr, nPos, nEnd - nPos ) && pSI->CountKashida() )
{
- const sal_Int32 nKashRes = pSI->KashidaJustify(nullptr, nPos, nEnd - nPos);
+ const sal_Int32 nKashRes = pSI->KashidaJustify(nullptr, nullptr, nPos, nEnd - nPos);
// i60591: need to check result of KashidaJustify
// determine if kashida justification is applicable
if (nKashRes != -1)
diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index 4058f12a1492..88d9037a3eb1 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -951,7 +951,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
rInf.GetFrame()->SwitchHorizontalToVertical( aTextOriginPos );
rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(),
- aKernArray, sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
+ aKernArray, {}, sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
return;
}
@@ -980,6 +980,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
{
std::vector<sal_Int32> aKernArray;
GetTextArray(rInf.GetOut(), rInf, aKernArray);
+ std::vector<sal_Bool> aKashidaArray;
if( bStretch )
{
@@ -1050,13 +1051,16 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
{
if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
{
+ aKashidaArray.resize(aKernArray.size(), false);
if ( pSI && pSI->CountKashida() &&
- pSI->KashidaJustify( aKernArray.data(), rInf.GetIdx(),
+ pSI->KashidaJustify( aKernArray.data(), aKashidaArray.data(), rInf.GetIdx(),
rInf.GetLen(), nSpaceAdd ) != -1 )
{
bSpecialJust = true;
nSpaceAdd = 0;
}
+ else
+ aKashidaArray.clear();
}
}
@@ -1104,18 +1108,18 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
aKernArray[0] = rInf.GetWidth() + nSpaceAdd;
rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(),
- aKernArray, sal_Int32(rInf.GetIdx()), 1 );
+ aKernArray, aKashidaArray, sal_Int32(rInf.GetIdx()), 1 );
}
else
{
aKernArray[ sal_Int32(rInf.GetLen()) - 2 ] += nSpaceAdd;
rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(),
- aKernArray, sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
+ aKernArray, aKashidaArray, sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
}
}
else
rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(),
- aKernArray, sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
+ aKernArray, aKashidaArray, sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
}
else
{
@@ -1209,6 +1213,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
GetTextArray(rInf.GetOut(), rInf, aKernArray);
}
+ std::vector<sal_Bool> aKashidaArray;
+
// Modify Printer and ScreenArrays for special justifications
tools::Long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
@@ -1248,12 +1254,16 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
{
if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
{
+ aKashidaArray.resize(aKernArray.size(), false);
if ( pSI && pSI->CountKashida() &&
- pSI->KashidaJustify( aKernArray.data(), rInf.GetIdx(),
+ pSI->KashidaJustify( aKernArray.data(), aKashidaArray.data(), rInf.GetIdx(),
rInf.GetLen(), nSpaceAdd ) != -1 )
nSpaceAdd = 0;
else
+ {
+ aKashidaArray.clear();
bNoHalfSpace = true;
+ }
}
}
@@ -1339,9 +1349,9 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
rInf.GetFrame()->SwitchHorizontalToVertical( aTextOriginPos );
rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(),
- aKernArray, sal_Int32(rInf.GetIdx()), 1 );
+ aKernArray, aKashidaArray, sal_Int32(rInf.GetIdx()), 1 );
if( bBullet )
- rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, aKernArray,
+ rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, aKernArray, aKashidaArray,
rInf.GetIdx() ? 1 : 0, 1 );
}
else
@@ -1464,7 +1474,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
: sal_Int32(rInf.GetIdx());
const SalLayoutGlyphs* pGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&rInf.GetOut(),
*pStr, nTmpIdx, nLen);
- rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, aKernArray,
+ rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, aKernArray, aKashidaArray,
nTmpIdx , nLen, SalLayoutFlags::NONE, pGlyphs );
if (bBullet)
{
@@ -1503,7 +1513,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
}
}
rInf.GetOut().DrawTextArray( aTextOriginPos, aBulletOverlay, aKernArray,
- nTmpIdx , nLen );
+ aKashidaArray, nTmpIdx , nLen );
pTmpFont->SetColor( aPreviousColor );
pTmpFont->SetUnderline(aPreviousUnderline);
@@ -1738,7 +1748,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf)
if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
{
if ( pSI && pSI->CountKashida() &&
- pSI->KashidaJustify( aKernArray.data(), rInf.GetIdx(), rInf.GetLen(),
+ pSI->KashidaJustify( aKernArray.data(), nullptr, rInf.GetIdx(), rInf.GetLen(),
nSpaceAdd ) != -1 )
nSpaceAdd = 0;
}
diff --git a/sw/source/uibase/docvw/HeaderFooterWin.cxx b/sw/source/uibase/docvw/HeaderFooterWin.cxx
index cca26f41e78c..ba75b20ec3ff 100644
--- a/sw/source/uibase/docvw/HeaderFooterWin.cxx
+++ b/sw/source/uibase/docvw/HeaderFooterWin.cxx
@@ -319,7 +319,7 @@ void SwHeaderFooterWin::PaintButton()
aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
aTextMatrix, m_sLabel, 0, m_sLabel.getLength(),
- std::vector<double>(), std::move(aFontAttr), css::lang::Locale(), aLineColor)));
+ std::vector<double>(), {}, std::move(aFontAttr), css::lang::Locale(), aLineColor)));
// Create the 'plus' or 'arrow' primitive
B2DRectangle aSignArea(B2DPoint(aRect.Right() - BUTTON_WIDTH, 0.0),
diff --git a/sw/source/uibase/docvw/UnfloatTableButton.cxx b/sw/source/uibase/docvw/UnfloatTableButton.cxx
index 82320732c707..49bf9c660771 100644
--- a/sw/source/uibase/docvw/UnfloatTableButton.cxx
+++ b/sw/source/uibase/docvw/UnfloatTableButton.cxx
@@ -223,7 +223,7 @@ void UnfloatTableButton::PaintButton()
aSeq.push_back(drawinglayer::primitive2d::Primitive2DReference(
new drawinglayer::primitive2d::TextSimplePortionPrimitive2D(
- aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), std::vector<double>(),
+ aTextMatrix, m_sLabel, 0, m_sLabel.getLength(), std::vector<double>(), {},
std::move(aFontAttr), css::lang::Locale(), aLineColor)));
// Create the processor and process the primitives
diff --git a/vcl/inc/ImplLayoutArgs.hxx b/vcl/inc/ImplLayoutArgs.hxx
index a94557afeb36..105a4e2d8961 100644
--- a/vcl/inc/ImplLayoutArgs.hxx
+++ b/vcl/inc/ImplLayoutArgs.hxx
@@ -37,6 +37,7 @@ public:
// positioning related inputs
const DeviceCoordinate* mpDXArray; // in integer pixel units
const double* mpAltNaturalDXArray; // in floating point pixel units
+ const sal_Bool* mpKashidaArray;
DeviceCoordinate mnLayoutWidth; // in pixel units
Degree10 mnOrientation; // in 0-3600 system
@@ -50,6 +51,7 @@ public:
void SetLayoutWidth(DeviceCoordinate nWidth);
void SetDXArray(const DeviceCoordinate* pDXArray);
void SetAltNaturalDXArray(const double* pDXArray);
+ void SetKashidaArray(const sal_Bool* pKashidaArray);
void SetOrientation(Degree10 nOrientation);
void ResetPos();
diff --git a/vcl/inc/impglyphitem.hxx b/vcl/inc/impglyphitem.hxx
index f0e4e70ef21c..f43ef0e99e61 100644
--- a/vcl/inc/impglyphitem.hxx
+++ b/vcl/inc/impglyphitem.hxx
@@ -37,7 +37,6 @@ enum class GlyphItemFlags : sal_uInt16
IS_DIACRITIC = 0x04,
IS_VERTICAL = 0x08,
IS_SPACING = 0x10,
- ALLOW_KASHIDA = 0x20,
IS_DROPPED = 0x40,
IS_CLUSTER_START = 0x80,
IS_UNSAFE_TO_BREAK = 0x100, // HB_GLYPH_FLAG_UNSAFE_TO_BREAK from harfbuzz
@@ -45,7 +44,7 @@ enum class GlyphItemFlags : sal_uInt16
};
namespace o3tl
{
-template <> struct typed_flags<GlyphItemFlags> : is_typed_flags<GlyphItemFlags, 0x3ff>
+template <> struct typed_flags<GlyphItemFlags> : is_typed_flags<GlyphItemFlags, 0x3df>
{
};
};
@@ -82,7 +81,6 @@ public:
bool IsDiacritic() const { return bool(m_nFlags & GlyphItemFlags::IS_DIACRITIC); }
bool IsVertical() const { return bool(m_nFlags & GlyphItemFlags::IS_VERTICAL); }
bool IsSpacing() const { return bool(m_nFlags & GlyphItemFlags::IS_SPACING); }
- bool AllowKashida() const { return bool(m_nFlags & GlyphItemFlags::ALLOW_KASHIDA); }
bool IsDropped() const { return bool(m_nFlags & GlyphItemFlags::IS_DROPPED); }
bool IsClusterStart() const { return bool(m_nFlags & GlyphItemFlags::IS_CLUSTER_START); }
bool IsUnsafeToBreak() const { return bool(m_nFlags & GlyphItemFlags::IS_UNSAFE_TO_BREAK); }
diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx
index d718529476b9..4ebddbe5edaf 100644
--- a/vcl/inc/pdf/pdfwriter_impl.hxx
+++ b/vcl/inc/pdf/pdfwriter_impl.hxx
@@ -1188,7 +1188,7 @@ public:
/* actual drawing functions */
void drawText( const Point& rPos, const OUString& rText, sal_Int32 nIndex, sal_Int32 nLen, bool bTextLines = true );
- void drawTextArray( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, sal_Int32 nIndex, sal_Int32 nLen );
+ void drawTextArray( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, o3tl::span<const sal_Bool> pKashidaArray, sal_Int32 nIndex, sal_Int32 nLen );
void drawStretchText( const Point& rPos, sal_uLong nWidth, const OUString& rText,
sal_Int32 nIndex, sal_Int32 nLen );
void drawText( const tools::Rectangle& rRect, const OUString& rOrigStr, DrawTextFlags nStyle );
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index 35f27ee20edf..885de2446db7 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -143,7 +143,7 @@ private:
GenericSalLayout& operator=( const GenericSalLayout& ) = delete;
template<typename DC>
- void ApplyDXArray(const DC*, SalLayoutFlags nLayoutFlags);
+ void ApplyDXArray(const DC*, const sal_Bool*);
void Justify(DeviceCoordinate nNewWidth);
void ApplyAsianKerning(const OUString& rStr);
diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx
index 9e96205946b1..ff85b14e33ef 100644
--- a/vcl/qa/cppunit/complextext.cxx
+++ b/vcl/qa/cppunit/complextext.cxx
@@ -49,14 +49,12 @@ public:
/// Play with font measuring etc.
void testArabic();
- void testKashida();
void testTdf95650(); // Windows-only issue
void testCaching();
void testCachingSubstring();
CPPUNIT_TEST_SUITE(VclComplexTextTest);
CPPUNIT_TEST(testArabic);
- CPPUNIT_TEST(testKashida);
CPPUNIT_TEST(testTdf95650);
CPPUNIT_TEST(testCaching);
CPPUNIT_TEST(testCachingSubstring);
@@ -114,31 +112,6 @@ void VclComplexTextTest::testArabic()
#endif
}
-void VclComplexTextTest::testKashida()
-{
-#if HAVE_MORE_FONTS
- // Cache the glyph list of some Arabic text.
- ScopedVclPtrInstance<VirtualDevice> pOutputDevice;
- auto aText
- = OUString(u"عنصر الفوسفور عنصر فلزي صلب. تتكون الدورة الرابعة من 15 عنصرا.");
- std::unique_ptr<SalLayout> pLayout = pOutputDevice->ImplLayout(
- aText, 0, aText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
- SalLayoutGlyphs aGlyphs = pLayout->GetGlyphs();
- CPPUNIT_ASSERT(aGlyphs.IsValid());
- CPPUNIT_ASSERT(aGlyphs.Impl(0) != nullptr);
-
- // Now lay it out using the cached glyph list.
- vcl::text::ImplLayoutArgs aLayoutArgs(aText, 0, aText.getLength(), SalLayoutFlags::NONE,
- pOutputDevice->GetFont().GetLanguageTag(), nullptr);
- pLayout = pOutputDevice->GetGraphics()->GetTextLayout(0);
- CPPUNIT_ASSERT(pLayout->LayoutText(aLayoutArgs, aGlyphs.Impl(0)));
-
- // Without the accompanying fix in place, this test would have failed with 'assertion failed'.
- // The kashida justification flag was lost when going via the glyph cache.
- CPPUNIT_ASSERT(aLayoutArgs.mnFlags & SalLayoutFlags::KashidaJustification);
-#endif
-}
-
void VclComplexTextTest::testTdf95650()
{
static constexpr OUStringLiteral aTxt =
@@ -152,7 +125,7 @@ void VclComplexTextTest::testTdf95650()
OutputDevice *pOutDev = pWin->GetOutDev();
// Check that the following executes without failing assertion
- pOutDev->ImplLayout(aTxt, 9, 1, Point(), 0, {}, SalLayoutFlags::BiDiRtl);
+ pOutDev->ImplLayout(aTxt, 9, 1, Point(), 0, {}, {}, SalLayoutFlags::BiDiRtl);
}
static void checkCompareGlyphs( const SalLayoutGlyphs& aGlyphs1, const SalLayoutGlyphs& aGlyphs2,
@@ -190,11 +163,11 @@ static void testCachedGlyphs( const OUString& aText, const OUString& aFontName )
SalLayoutGlyphsCache::self()->clear();
// Get the glyphs for the text.
std::unique_ptr<SalLayout> pLayout1 = pOutputDevice->ImplLayout(
- aText, 0, aText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ aText, 0, aText.getLength(), Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly);
SalLayoutGlyphs aGlyphs1 = pLayout1->GetGlyphs();
// Reuse the cached glyphs to get glyphs again.
std::unique_ptr<SalLayout> pLayout2 = pOutputDevice->ImplLayout(
- aText, 0, aText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly, nullptr, &aGlyphs1);
+ aText, 0, aText.getLength(), Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly, nullptr, &aGlyphs1);
SalLayoutGlyphs aGlyphs2 = pLayout2->GetGlyphs();
checkCompareGlyphs(aGlyphs1, aGlyphs2, message + " (reuse)");
// Get cached glyphs from SalLayoutGlyphsCache.
@@ -228,7 +201,7 @@ static void testCachedGlyphsSubstring( const OUString& aText, const OUString& aF
SalLayoutGlyphsCache::self()->clear();
std::shared_ptr<const vcl::text::TextLayoutCache> layoutCache = OutputDevice::CreateTextLayoutCache(aText);
// Get the glyphs for the entire text once, to ensure the cache can built subsets from it.
- pOutputDevice->ImplLayout( aText, 0, aText.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly,
+ pOutputDevice->ImplLayout( aText, 0, aText.getLength(), Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly,
layoutCache.get());
// Now check for all subsets. Some of them possibly do not make sense in practice, but the code
// should cope with them.
@@ -237,7 +210,7 @@ static void testCachedGlyphsSubstring( const OUString& aText, const OUString& aF
{
std::string message = prefix + " (" + std::to_string(pos) + "/" + std::to_string(len) + ")";
std::unique_ptr<SalLayout> pLayout1 = pOutputDevice->ImplLayout(
- aText, pos, len, Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly, layoutCache.get());
+ aText, pos, len, Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly, layoutCache.get());
SalLayoutGlyphs aGlyphs1 = pLayout1->GetGlyphs();
const SalLayoutGlyphs* aGlyphs2 = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(
pOutputDevice, aText, pos, len, 0, layoutCache.get());
diff --git a/vcl/qa/cppunit/svm/svmtest.cxx b/vcl/qa/cppunit/svm/svmtest.cxx
index fcea61afb5a9..2f4f17d7beb4 100644
--- a/vcl/qa/cppunit/svm/svmtest.cxx
+++ b/vcl/qa/cppunit/svm/svmtest.cxx
@@ -860,7 +860,7 @@ void SvmTest::testTextArray()
ScopedVclPtrInstance<VirtualDevice> pVirtualDev;
setupBaseVirtualDevice(*pVirtualDev, aGDIMetaFile);
sal_Int32 const aDX[] = { 10, 15, 20, 25, 30, 35 };
- pVirtualDev->DrawTextArray(Point(4,6), "123456", aDX, 1, 4);
+ pVirtualDev->DrawTextArray(Point(4,6), "123456", aDX, {}, 1, 4);
checkTextArray(writeAndReadStream(aGDIMetaFile));
checkTextArray(readFile(u"textarray.svm"));
diff --git a/vcl/qa/cppunit/text.cxx b/vcl/qa/cppunit/text.cxx
index 668e84ef2aad..7a73ee3bc6e2 100644
--- a/vcl/qa/cppunit/text.cxx
+++ b/vcl/qa/cppunit/text.cxx
@@ -702,7 +702,7 @@ void VclTextTest::testImplLayoutArgs_PrepareFallback_precalculatedglyphs()
const OString sUTF8String(u8"Тхе яуицк\n ыумпед овер");
const OUString sTestString(OUString::fromUtf8(sUTF8String));
std::unique_ptr<SalLayout> pLayout
- = pVirDev->ImplLayout(sTestString, 0, sTestString.getLength(), Point(0, 0), 0, {},
+ = pVirDev->ImplLayout(sTestString, 0, sTestString.getLength(), Point(0, 0), 0, {}, {},
SalLayoutFlags::GlyphItemsOnly);
SalLayoutGlyphs aGlyphs = pLayout->GetGlyphs();
SalLayoutGlyphsImpl* pGlyphsImpl = aGlyphs.Impl(1);
diff --git a/vcl/source/control/imp_listbox.cxx b/vcl/source/control/imp_listbox.cxx
index 911770678667..fbd655eb04dd 100644
--- a/vcl/source/control/imp_listbox.cxx
+++ b/vcl/source/control/imp_listbox.cxx
@@ -590,7 +590,7 @@ SalLayoutGlyphs* ImplEntryType::GetTextGlyphs(const OutputDevice* pOutputDevice)
return &maStrGlyphs;
std::unique_ptr<SalLayout> pLayout = pOutputDevice->ImplLayout(
- maStr, 0, maStr.getLength(), Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ maStr, 0, maStr.getLength(), Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly);
if (!pLayout)
return nullptr;
diff --git a/vcl/source/filter/eps/eps.cxx b/vcl/source/filter/eps/eps.cxx
index bb25bdccb57e..797d6b887efc 100644
--- a/vcl/source/filter/eps/eps.cxx
+++ b/vcl/source/filter/eps/eps.cxx
@@ -201,7 +201,7 @@ private:
void ImplSetClipRegion( vcl::Region const & rRegion );
void ImplBmp( Bitmap const *, Bitmap const *, const Point &, double nWidth, double nHeight );
- void ImplText( const OUString& rUniString, const Point& rPos, o3tl::span<const sal_Int32> pDXArry, sal_Int32 nWidth, VirtualDevice const & rVDev );
+ void ImplText( const OUString& rUniString, const Point& rPos, o3tl::span<const sal_Int32> pDXArry, o3tl::span<const sal_Bool> pKashidaArry, sal_Int32 nWidth, VirtualDevice const & rVDev );
void ImplSetAttrForText( const Point & rPoint );
void ImplWriteCharacter( char );
void ImplWriteString( const OString&, VirtualDevice const & rVDev, o3tl::span<const sal_Int32> pDXArry, bool bStretch );
@@ -748,7 +748,7 @@ void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev )
OUString aUniStr = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
Point aPoint( pA->GetPoint() );
- ImplText( aUniStr, aPoint, {}, 0, rVDev );
+ ImplText( aUniStr, aPoint, {}, {}, 0, rVDev );
}
break;
@@ -764,7 +764,7 @@ void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev )
OUString aUniStr = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
Point aPoint( pA->GetPoint() );
- ImplText( aUniStr, aPoint, {}, pA->GetWidth(), rVDev );
+ ImplText( aUniStr, aPoint, {}, {}, pA->GetWidth(), rVDev );
}
break;
@@ -774,7 +774,7 @@ void PSWriter::ImplWriteActions( const GDIMetaFile& rMtf, VirtualDevice& rVDev )
OUString aUniStr = pA->GetText().copy( pA->GetIndex(), pA->GetLen() );
Point aPoint( pA->GetPoint() );
- ImplText( aUniStr, aPoint, pA->GetDXArray(), 0, rVDev );
+ ImplText( aUniStr, aPoint, pA->GetDXArray(), pA->GetKashidaArray(), 0, rVDev );
}
break;
@@ -1988,7 +1988,7 @@ void PSWriter::ImplWriteString( const OString& rString, VirtualDevice const & rV
}
}
-void PSWriter::ImplText( const OUString& rUniString, const Point& rPos, o3tl::span<const sal_Int32> pDXArry, sal_Int32 nWidth, VirtualDevice const & rVDev )
+void PSWriter::ImplText( const OUString& rUniString, const Point& rPos, o3tl::span<const sal_Int32> pDXArry, o3tl::span<const sal_Bool> pKashidaArry, sal_Int32 nWidth, VirtualDevice const & rVDev )
{
if ( rUniString.isEmpty() )
return;
@@ -2015,7 +2015,7 @@ void PSWriter::ImplText( const OUString& rUniString, const Point& rPos, o3tl::sp
bool bOldLineColor = bLineColor;
bLineColor = false;
std::vector<tools::PolyPolygon> aPolyPolyVec;
- if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniString, 0, 0, -1, nWidth, pDXArry ) )
+ if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniString, 0, 0, -1, nWidth, pDXArry, pKashidaArry ) )
{
// always adjust text position to match baseline alignment
ImplWriteLine( "pum" );
diff --git a/vcl/source/filter/svm/SvmConverter.cxx b/vcl/source/filter/svm/SvmConverter.cxx
index 4127d132557e..efc036cc264a 100644
--- a/vcl/source/filter/svm/SvmConverter.cxx
+++ b/vcl/source/filter/svm/SvmConverter.cxx
@@ -809,7 +809,7 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
if ( nUnicodeCommentActionNumber == i )
ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
ClampRange(aStr, nIndex, nLen, &aDXAry);
- rMtf.AddAction( new MetaTextArrayAction( aPt, aStr, std::move(aDXAry), nIndex, nLen ) );
+ rMtf.AddAction( new MetaTextArrayAction( aPt, aStr, std::move(aDXAry), {}, nIndex, nLen ) );
}
if (nActionSize < 24)
diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx
index 98364d4ae443..da7334352858 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -197,9 +197,9 @@ void GenericSalLayout::AdjustLayout(vcl::text::ImplLayoutArgs& rArgs)
SalLayout::AdjustLayout(rArgs);
if (rArgs.mpAltNaturalDXArray) // Used when "TextRenderModeForResolutionIndependentLayout" is set
- ApplyDXArray(rArgs.mpAltNaturalDXArray, rArgs.mnFlags);
+ ApplyDXArray(rArgs.mpAltNaturalDXArray, rArgs.mpKashidaArray);
else if (rArgs.mpDXArray) // Normal case
- ApplyDXArray(rArgs.mpDXArray, rArgs.mnFlags);
+ ApplyDXArray(rArgs.mpDXArray, rArgs.mpKashidaArray);
else if (rArgs.mnLayoutWidth)
Justify(rArgs.mnLayoutWidth);
// apply asian kerning if the glyphs are not already formatted
@@ -565,14 +565,6 @@ bool GenericSalLayout::LayoutText(vcl::text::ImplLayoutArgs& rArgs, const SalLay
if (u_isUWhiteSpace(aChar))
nGlyphFlags |= GlyphItemFlags::IS_SPACING;
- if (aSubRun.maScript == HB_SCRIPT_ARABIC &&
- HB_DIRECTION_IS_BACKWARD(aSubRun.maDirection) &&
- !(nGlyphFlags & GlyphItemFlags::IS_SPACING))
- {
- nGlyphFlags |= GlyphItemFlags::ALLOW_KASHIDA;
- rArgs.mnFlags |= SalLayoutFlags::KashidaJustification;
- }
-
#if HB_VERSION_ATLEAST(1, 5, 0)
if (hb_glyph_info_get_glyph_flags(&pHbGlyphInfos[i]) & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
nGlyphFlags |= GlyphItemFlags::IS_UNSAFE_TO_BREAK;
@@ -657,24 +649,12 @@ void GenericSalLayout::GetCharWidths(std::vector<DeviceCoordinate>& rCharWidths)
}
}
-// A note on how Kashida justification is implemented (because it took me 5
-// years to figure it out):
-// The decision to insert Kashidas, where and how much is taken by Writer.
-// This decision is communicated to us in a very indirect way; by increasing
-// the width of the character after which Kashidas should be inserted by the
-// desired amount.
-//
-// Writer eventually calls IsKashidaPosValid() to check whether it can insert a
-// Kashida between two characters or not.
-//
-// Here we do:
-// - In LayoutText() set KashidaJustification flag based on text script.
-// - In ApplyDXArray():
-// * Check the above flag to decide whether to insert Kashidas or not.
-// * For any RTL glyph that has DX adjustment, insert enough Kashidas to
-// fill in the added space.
+// - pDXArray: is the adjustments to glyph advances (usually due to
+// justification).
+// - pKashidaArray: is the places where kashidas are inserted (for Arabic
+// justification). The number of kashidas is calculated from the pDXArray.
template<typename DC>
-void GenericSalLayout::ApplyDXArray(const DC* pDXArray, SalLayoutFlags nLayoutFlags)
+void GenericSalLayout::ApplyDXArray(const DC* pDXArray, const sal_Bool* pKashidaArray)
{
int nCharCount = mnEndCharPos - mnMinCharPos;
std::vector<DeviceCoordinate> aOldCharWidths;
@@ -692,18 +672,6 @@ void GenericSalLayout::ApplyDXArray(const DC* pDXArray, SalLayoutFlags nLayoutFl
pNewCharWidths[i] = pDXArray[i] - pDXArray[i - 1];
}
- bool bKashidaJustify = false;
- DeviceCoordinate nKashidaWidth = 0;
- hb_codepoint_t nKashidaIndex = 0;
- if (nLayoutFlags & SalLayoutFlags::KashidaJustification)
- {
- hb_font_t *pHbFont = GetFont().GetHbFont();
- // Find Kashida glyph width and index.
- if (hb_font_get_glyph(pHbFont, 0x0640, 0, &nKashidaIndex))
- nKashidaWidth = GetFont().GetKashidaWidth();
- bKashidaJustify = nKashidaWidth != 0;
- }
-
// Map of Kashida insertion points (in the glyph items vector) and the
// requested width.
std::map<size_t, DeviceCoordinate> pKashidas;
@@ -743,15 +711,15 @@ void GenericSalLayout::ApplyDXArray(const DC* pDXArray, SalLayoutFlags nLayoutFl
// loop below.
i++;
}
- else
+ else // RTL
{
// Adjust the width and position of the first (rightmost) glyph in
- // the cluster.
- // For RTL, we put all the adjustment to the left of the glyph.
+ // the cluster. This is RTL, so we put all the adjustment to the
+ // left of the glyph.
m_GlyphItems[i].addNewWidth(nDiff);
m_GlyphItems[i].adjustLinearPosX(nDelta + nDiff);
- // Adjust the X position of all glyphs in the cluster.
+ // Adjust the X position of the rest of the glyphs in the cluster.
size_t j = i;
while (j > 0)
{
@@ -761,36 +729,44 @@ void GenericSalLayout::ApplyDXArray(const DC* pDXArray, SalLayoutFlags nLayoutFl
m_GlyphItems[j].adjustLinearPosX(nDelta + nDiff);
}
- // If this glyph is Kashida-justifiable, then mark this as a
- // Kashida position. Since this must be a RTL glyph, we mark the
- // last glyph in the cluster not the first as this would be the
- // base glyph.
- if (bKashidaJustify && m_GlyphItems[i].AllowKashida() &&
- nDiff > m_GlyphItems[i].charCount()) // Rounding errors, 1 pixel per character!
+ // Move any non-spacing marks to keep attached to this cluster.
+ while (j > 0)
{
- pKashidas[i] = nDiff;
- // Move any non-spacing marks attached to this cluster as well.
- // Looping backward because this is RTL glyph.
- while (j > 0)
- {
- if (!m_GlyphItems[j].IsDiacritic())
- break;
- m_GlyphItems[j--].adjustLinearPosX(nDiff);
- }
+ if (!m_GlyphItems[j].IsDiacritic())
+ break;
+ m_GlyphItems[j--].adjustLinearPosX(nDiff);
}
+
+ // This is a Kashida insertion position, mark it. Kashida glyphs
+ // will be inserted below.
+ if (pKashidaArray && pKashidaArray[nCharPos])
+ pKashidas[i] = nDiff;
+
i++;
}
// Increment the delta, the loop above makes sure we do so only once
// for every character (cluster) not for every glyph (otherwise we
- // would apply it multiple times for each glyphs belonging to the same
- // character which is wrong since DX adjustments are character based).
+ // would apply it multiple times for each glyph belonging to the same
+ // character which is wrong as DX adjustments are character based).
nDelta += nDiff;
}
// Insert Kashida glyphs.
- if (!bKashidaJustify || pKashidas.empty())
+ if (pKashidas.empty())
+ return;
+
+ // Find Kashida glyph width and index.
+ DeviceCoordinate nKashidaWidth = 0;
+ hb_codepoint_t nKashidaIndex = 0;
+ if (hb_font_get_glyph(GetFont().GetHbFont(), 0x0640, 0, &nKashidaIndex))
+ nKashidaWidth = GetFont().GetKashidaWidth();
+
+ if (nKashidaWidth <= 0)
+ {
+ SAL_WARN("vcl.gdi", "Asked to insert Kashidas in a font with zero-width Kashida");
return;
+ }
size_t nInserted = 0;
for (auto const& pKashida : pKashidas)
diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx
index 4d889f6d54d0..e15cf05b9cf5 100644
--- a/vcl/source/gdi/gdimtf.cxx
+++ b/vcl/source/gdi/gdimtf.cxx
@@ -978,7 +978,7 @@ void GDIMetaFile::Rotate( Degree10 nAngle10 )
{
MetaTextArrayAction* pAct = static_cast<MetaTextArrayAction*>(pAction);
aMtf.AddAction( new MetaTextArrayAction( ImplGetRotatedPoint( pAct->GetPoint(), aRotAnchor, aRotOffset, fSin, fCos ),
- pAct->GetText(), pAct->GetDXArray(), pAct->GetIndex(), pAct->GetLen() ) );
+ pAct->GetText(), pAct->GetDXArray(), pAct->GetKashidaArray(), pAct->GetIndex(), pAct->GetLen() ) );
}
break;
@@ -1452,7 +1452,7 @@ tools::Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference ) const
tools::Rectangle aRect;
// hdu said base = index
aMapVDev->GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
- 0, pAct->GetDXArray() );
+ 0, pAct->GetDXArray(), pAct->GetKashidaArray() );
Point aPt( pAct->GetPoint() );
aRect.Move( aPt.X(), aPt.Y() );
ImplActionBounds( aBound, OutputDevice::LogicToLogic( aRect, aMapVDev->GetMapMode(), GetPrefMapMode() ), aClipStack );
diff --git a/vcl/source/gdi/impglyphitem.cxx b/vcl/source/gdi/impglyphitem.cxx
index 51bff5966d32..6cbb245e922b 100644
--- a/vcl/source/gdi/impglyphitem.cxx
+++ b/vcl/source/gdi/impglyphitem.cxx
@@ -297,27 +297,6 @@ static SalLayoutGlyphs makeGlyphsSubset(const SalLayoutGlyphs& source,
// would assert on flags being different.
cloned->SetFlags(cloned->GetFlags()
| outputDevice->GetBiDiLayoutFlags(text, index, index + len));
- // SalLayoutFlags::KashidaJustification is set only if any glyph
- // in the range has GlyphItemFlags::ALLOW_KASHIDA (otherwise unset it).
- if (cloned->GetFlags() & SalLayoutFlags::KashidaJustification)
- {
- bool hasKashida = false;
- for (const GlyphItem& item : *cloned)
- {
- if (item.AllowKashida())
- {
- hasKashida = true;
- break;
- }
- }
- if (!hasKashida)
- cloned->SetFlags(cloned->GetFlags() & ~SalLayoutFlags::KashidaJustification);
- }
-#ifdef DBG_UTIL
- else
- for (const GlyphItem& item : *cloned)
- assert(!item.AllowKashida());
-#endif
ret.AppendImpl(cloned);
}
return ret;
@@ -433,7 +412,7 @@ SalLayoutGlyphsCache::GetLayoutGlyphs(VclPtr<const OutputDevice> outputDevice, c
// Check if the subset result really matches what we would get normally,
// to make sure corner cases are handled well (see SalLayoutGlyphsImpl::cloneCharRange()).
std::unique_ptr<SalLayout> layout
- = outputDevice->ImplLayout(text, nIndex, nLen, Point(0, 0), nLogicWidth, {},
+ = outputDevice->ImplLayout(text, nIndex, nLen, Point(0, 0), nLogicWidth, {}, {},
SalLayoutFlags::GlyphItemsOnly, layoutCache);
assert(layout);
checkGlyphsEqual(mLastTemporaryGlyphs, layout->GetGlyphs());
@@ -458,7 +437,7 @@ SalLayoutGlyphsCache::GetLayoutGlyphs(VclPtr<const OutputDevice> outputDevice, c
layoutCache = tmpLayoutCache.get();
}
std::unique_ptr<SalLayout> layout
- = outputDevice->ImplLayout(text, nIndex, nLen, Point(0, 0), nLogicWidth, {},
+ = outputDevice->ImplLayout(text, nIndex, nLen, Point(0, 0), nLogicWidth, {}, {},
SalLayoutFlags::GlyphItemsOnly, layoutCache);
if (layout)
{
diff --git a/vcl/source/gdi/metaact.cxx b/vcl/source/gdi/metaact.cxx
index 4d6705e39115..cd06b016d4be 100644
--- a/vcl/source/gdi/metaact.cxx
+++ b/vcl/source/gdi/metaact.cxx
@@ -601,6 +601,7 @@ MetaTextArrayAction::MetaTextArrayAction( const MetaTextArrayAction& rAction ) :
maStartPt ( rAction.maStartPt ),
maStr ( rAction.maStr ),
maDXAry ( rAction.maDXAry ),
+ maKashidaAry( rAction.maKashidaAry ),
mnIndex ( rAction.mnIndex ),
mnLen ( rAction.mnLen )
{
@@ -609,12 +610,14 @@ MetaTextArrayAction::MetaTextArrayAction( const MetaTextArrayAction& rAction ) :
MetaTextArrayAction::MetaTextArrayAction( const Point& rStartPt,
OUString aStr,
std::vector<sal_Int32> aDXAry,
+ std::vector<sal_Bool> aKashidaAry,
sal_Int32 nIndex,
sal_Int32 nLen ) :
MetaAction ( MetaActionType::TEXTARRAY ),
maStartPt ( rStartPt ),
maStr (std::move( aStr )),
maDXAry (std::move( aDXAry )),
+ maKashidaAry(std::move( aKashidaAry )),
mnIndex ( nIndex ),
mnLen ( nLen )
{
@@ -623,12 +626,14 @@ MetaTextArrayAction::MetaTextArrayAction( const Point& rStartPt,
MetaTextArrayAction::MetaTextArrayAction( const Point& rStartPt,
OUString aStr,
o3tl::span<const sal_Int32> pDXAry,
+ o3tl::span<const sal_Bool> pKashidaAry,
sal_Int32 nIndex,
sal_Int32 nLen ) :
MetaAction ( MetaActionType::TEXTARRAY ),
maStartPt ( rStartPt ),
maStr (std::move( aStr )),
maDXAry ( pDXAry.begin(), pDXAry.end() ),
+ maKashidaAry( pKashidaAry.begin(), pKashidaAry.end() ),
mnIndex ( nIndex ),
mnLen ( nLen )
{
@@ -640,7 +645,7 @@ MetaTextArrayAction::~MetaTextArrayAction()
void MetaTextArrayAction::Execute( OutputDevice* pOut )
{
- pOut->DrawTextArray( maStartPt, maStr, maDXAry, mnIndex, mnLen );
+ pOut->DrawTextArray( maStartPt, maStr, maDXAry, maKashidaAry, mnIndex, mnLen );
}
rtl::Reference<MetaAction> MetaTextArrayAction::Clone() const
@@ -669,6 +674,11 @@ void MetaTextArrayAction::SetDXArray(std::vector<sal_Int32> aArray)
maDXAry = std::move(aArray);
}
+void MetaTextArrayAction::SetKashidaArray(std::vector<sal_Bool> aArray)
+{
+ maKashidaAry = std::move(aArray);
+}
+
MetaStretchTextAction::MetaStretchTextAction() :
MetaAction ( MetaActionType::STRETCHTEXT ),
mnWidth ( 0 ),
diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx
index 1a8d407c7247..3e20c12f2720 100644
--- a/vcl/source/gdi/pdfwriter.cxx
+++ b/vcl/source/gdi/pdfwriter.cxx
@@ -82,10 +82,11 @@ void PDFWriter::DrawTextArray(
const Point& rStartPt,
const OUString& rStr,
o3tl::span<const sal_Int32> pDXAry,
+ o3tl::span<const sal_Bool> pKashidaAry,
sal_Int32 nIndex,
sal_Int32 nLen )
{
- xImplementation->drawTextArray( rStartPt, rStr, pDXAry, nIndex, nLen );
+ xImplementation->drawTextArray( rStartPt, rStr, pDXAry, pKashidaAry, nIndex, nLen );
}
void PDFWriter::DrawStretchText(
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index f16bdc090f03..f0413d635a54 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -6616,14 +6616,14 @@ void PDFWriterImpl::drawText( const Point& rPos, const OUString& rText, sal_Int3
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->
GetLayoutGlyphs( this, rText, nIndex, nLen );
std::unique_ptr<SalLayout> pLayout = ImplLayout( rText, nIndex, nLen, rPos,
- 0, {}, SalLayoutFlags::NONE, nullptr, layoutGlyphs );
+ 0, {}, {}, SalLayoutFlags::NONE, nullptr, layoutGlyphs );
if( pLayout )
{
drawLayout( *pLayout, rText, bTextLines );
}
}
-void PDFWriterImpl::drawTextArray( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, sal_Int32 nIndex, sal_Int32 nLen )
+void PDFWriterImpl::drawTextArray( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, o3tl::span<const sal_Bool> pKashidaArray, sal_Int32 nIndex, sal_Int32 nLen )
{
MARK( "drawText with array" );
@@ -6633,7 +6633,7 @@ void PDFWriterImpl::drawTextArray( const Point& rPos, const OUString& rText, o3t
// this also enforces font substitution and sets the font on SalGraphics
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->
GetLayoutGlyphs( this, rText, nIndex, nLen );
- std::unique_ptr<SalLayout> pLayout = ImplLayout( rText, nIndex, nLen, rPos, 0, pDXArray,
+ std::unique_ptr<SalLayout> pLayout = ImplLayout( rText, nIndex, nLen, rPos, 0, pDXArray, pKashidaArray,
SalLayoutFlags::NONE, nullptr, layoutGlyphs );
if( pLayout )
{
@@ -6652,7 +6652,7 @@ void PDFWriterImpl::drawStretchText( const Point& rPos, sal_uLong nWidth, const
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->
GetLayoutGlyphs( this, rText, nIndex, nLen, nWidth );
std::unique_ptr<SalLayout> pLayout = ImplLayout( rText, nIndex, nLen, rPos, nWidth,
- {}, SalLayoutFlags::NONE, nullptr, layoutGlyphs );
+ {}, {}, SalLayoutFlags::NONE, nullptr, layoutGlyphs );
if( pLayout )
{
drawLayout( *pLayout, rText, true );
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx
index f4c60a661684..cac3813cdedc 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -813,7 +813,7 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa
case MetaActionType::TEXTARRAY:
{
const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
- m_rOuterFace.DrawTextArray( pA->GetPoint(), pA->GetText(), pA->GetDXArray(), pA->GetIndex(), pA->GetLen() );
+ m_rOuterFace.DrawTextArray( pA->GetPoint(), pA->GetText(), pA->GetDXArray(), pA->GetKashidaArray(), pA->GetIndex(), pA->GetLen() );
}
break;
diff --git a/vcl/source/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx
index 416c68343f47..25bf47767ec7 100644
--- a/vcl/source/gdi/textlayout.cxx
+++ b/vcl/source/gdi/textlayout.cxx
@@ -209,7 +209,7 @@ namespace vcl
std::vector<sal_Int32> aCharWidths;
tools::Long nTextWidth = GetTextArray( _rText, &aCharWidths, _nStartIndex, _nLength );
- m_rTargetDevice.DrawTextArray( _rStartPoint, _rText, aCharWidths, _nStartIndex, _nLength );
+ m_rTargetDevice.DrawTextArray( _rStartPoint, _rText, aCharWidths, {}, _nStartIndex, _nLength );
m_aCompleteTextRect.Union( tools::Rectangle( _rStartPoint, Size( nTextWidth, m_rTargetDevice.GetTextHeight() ) ) );
}
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 2f7199fa3fa3..06f43fa2d3ea 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -872,7 +872,7 @@ void OutputDevice::DrawText( const Point& rStartPt, const OUString& rStr,
if(mpFontInstance->mpConversion)
pLayoutCache = nullptr;
- std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, {}, eDefaultLayout, nullptr, pLayoutCache);
+ std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, {}, {}, eDefaultLayout, nullptr, pLayoutCache);
if(pSalLayout)
{
ImplDrawText( *pSalLayout );
@@ -921,6 +921,7 @@ float OutputDevice::approximate_digit_width() const
void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr,
o3tl::span<const sal_Int32> pDXAry,
+ o3tl::span<const sal_Bool> pKashidaAry,
sal_Int32 nIndex, sal_Int32 nLen, SalLayoutFlags flags,
const SalLayoutGlyphs* pSalLayoutCache )
{
@@ -931,7 +932,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr,
nLen = rStr.getLength() - nIndex;
}
if ( mpMetaFile )
- mpMetaFile->AddAction( new MetaTextArrayAction( rStartPt, rStr, pDXAry, nIndex, nLen ) );
+ mpMetaFile->AddAction( new MetaTextArrayAction( rStartPt, rStr, pDXAry, pKashidaAry, nIndex, nLen ) );
if ( !IsDeviceOutputNecessary() )
return;
@@ -943,14 +944,14 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr,
if( mbOutputClipped )
return;
- std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, pDXAry, flags, nullptr, pSalLayoutCache);
+ std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, pDXAry, pKashidaAry, flags, nullptr, pSalLayoutCache);
if( pSalLayout )
{
ImplDrawText( *pSalLayout );
}
if( mpAlphaVDev )
- mpAlphaVDev->DrawTextArray( rStartPt, rStr, pDXAry, nIndex, nLen, flags );
+ mpAlphaVDev->DrawTextArray( rStartPt, rStr, pDXAry, pKashidaAry, nIndex, nLen, flags );
}
tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector<sal_Int32>* pDXAry,
@@ -968,7 +969,7 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector<sal_In
// do layout
std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen,
- Point(0,0), 0, {}, eDefaultLayout, pLayoutCache, pSalLayoutCache);
+ Point(0,0), 0, {}, {}, eDefaultLayout, pLayoutCache, pSalLayoutCache);
if( !pSalLayout )
{
// The caller expects this to init the elements of pDXAry.
@@ -1076,7 +1077,7 @@ void OutputDevice::GetCaretPositions( const OUString& rStr, sal_Int32* pCaretXAr
nLen = rStr.getLength() - nIndex;
// layout complex text
- std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, Point(0, 0), 0, {},
+ std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, Point(0, 0), 0, {}, {},
eDefaultLayout, nullptr, pGlyphs);
if( !pSalLayout )
{
@@ -1312,7 +1313,9 @@ OutputDevice::FontMappingUseData OutputDevice::FinishTrackingFontMappingUse()
std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr,
sal_Int32 nMinIndex, sal_Int32 nLen,
const Point& rLogicalPos, tools::Long nLogicalWidth,
- o3tl::span<const sal_Int32> pDXArray, SalLayoutFlags flags,
+ o3tl::span<const sal_Int32> pDXArray,
+ o3tl::span<const sal_Bool> pKashidaArray,
+ SalLayoutFlags flags,
vcl::text::TextLayoutCache const* pLayoutCache,
const SalLayoutGlyphs* pGlyphs) const
{
@@ -1427,6 +1430,9 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr,
}
}
+ if (!pKashidaArray.empty())
+ aLayoutArgs.SetKashidaArray(pKashidaArray.data());
+
// get matching layout object for base font
std::unique_ptr<SalLayout> pSalLayout = mpGraphics->GetTextLayout(0);
@@ -1505,7 +1511,7 @@ sal_Int32 OutputDevice::GetTextBreak( const OUString& rStr, tools::Long nTextWid
const SalLayoutGlyphs* pGlyphs) const
{
std::unique_ptr<SalLayout> pSalLayout = ImplLayout( rStr, nIndex, nLen,
- Point(0,0), 0, {}, eDefaultLayout, pLayoutCache, pGlyphs);
+ Point(0,0), 0, {}, {}, eDefaultLayout, pLayoutCache, pGlyphs);
sal_Int32 nRetVal = -1;
if( pSalLayout )
{
@@ -1539,7 +1545,7 @@ sal_Int32 OutputDevice::GetTextBreak( const OUString& rStr, tools::Long nTextWid
rHyphenPos = -1;
std::unique_ptr<SalLayout> pSalLayout = ImplLayout( rStr, nIndex, nLen,
- Point(0,0), 0, {}, eDefaultLayout, pLayoutCache, pGlyphs);
+ Point(0,0), 0, {}, {}, eDefaultLayout, pLayoutCache, pGlyphs);
sal_Int32 nRetVal = -1;
if( pSalLayout )
{
@@ -2397,6 +2403,7 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect,
const OUString& rStr, sal_Int32 nBase,
sal_Int32 nIndex, sal_Int32 nLen,
sal_uLong nLayoutWidth, o3tl::span<const sal_Int32> pDXAry,
+ o3tl::span<const sal_Bool> pKashidaAry,
const SalLayoutGlyphs* pGlyphs ) const
{
bool bRet = false;
@@ -2410,7 +2417,7 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect,
{
sal_Int32 nStart = std::min( nBase, nIndex );
sal_Int32 nOfsLen = std::max( nBase, nIndex ) - nStart;
- pSalLayout = ImplLayout( rStr, nStart, nOfsLen, aPoint, nLayoutWidth, pDXAry );
+ pSalLayout = ImplLayout( rStr, nStart, nOfsLen, aPoint, nLayoutWidth, pDXAry, pKashidaAry );
if( pSalLayout )
{
nXOffset = pSalLayout->GetTextWidth();
@@ -2421,7 +2428,7 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect,
}
}
- pSalLayout = ImplLayout(rStr, nIndex, nLen, aPoint, nLayoutWidth, pDXAry, eDefaultLayout,
+ pSalLayout = ImplLayout(rStr, nIndex, nLen, aPoint, nLayoutWidth, pDXAry, pKashidaAry, eDefaultLayout,
nullptr, pGlyphs);
if( pSalLayout )
{
@@ -2461,7 +2468,9 @@ bool OutputDevice::GetTextBoundRect( tools::Rectangle& rRect,
bool OutputDevice::GetTextOutlines( basegfx::B2DPolyPolygonVector& rVector,
const OUString& rStr, sal_Int32 nBase,
sal_Int32 nIndex, sal_Int32 nLen,
- sal_uLong nLayoutWidth, o3tl::span<const sal_Int32> pDXArray ) const
+ sal_uLong nLayoutWidth,
+ o3tl::span<const sal_Int32> pDXArray,
+ o3tl::span<const sal_Bool> pKashidaArray ) const
{
if (!InitFont())
return false;
@@ -2491,7 +2500,7 @@ bool OutputDevice::GetTextOutlines( basegfx::B2DPolyPolygonVector& rVector,
{
sal_Int32 nStart = std::min( nBase, nIndex );
sal_Int32 nOfsLen = std::max( nBase, nIndex ) - nStart;
- pSalLayout = ImplLayout( rStr, nStart, nOfsLen, Point(0,0), nLayoutWidth, pDXArray );
+ pSalLayout = ImplLayout( rStr, nStart, nOfsLen, Point(0,0), nLayoutWidth, pDXArray, pKashidaArray);
if( pSalLayout )
{
nXOffset = pSalLayout->GetTextWidth();
@@ -2502,7 +2511,7 @@ bool OutputDevice::GetTextOutlines( basegfx::B2DPolyPolygonVector& rVector,
}
}
- pSalLayout = ImplLayout( rStr, nIndex, nLen, Point(0,0), nLayoutWidth, pDXArray );
+ pSalLayout = ImplLayout( rStr, nIndex, nLen, Point(0,0), nLayoutWidth, pDXArray, pKashidaArray );
if( pSalLayout )
{
bRet = pSalLayout->GetOutline(rVector);
@@ -2548,14 +2557,15 @@ bool OutputDevice::GetTextOutlines( basegfx::B2DPolyPolygonVector& rVector,
bool OutputDevice::GetTextOutlines( PolyPolyVector& rResultVector,
const OUString& rStr, sal_Int32 nBase,
sal_Int32 nIndex, sal_Int32 nLen,
- sal_uLong nLayoutWidth, o3tl::span<const sal_Int32> pDXArray ) const
+ sal_uLong nLayoutWidth, o3tl::span<const sal_Int32> pDXArray,
+ o3tl::span<const sal_Bool> pKashidaArray ) const
{
rResultVector.clear();
// get the basegfx polypolygon vector
basegfx::B2DPolyPolygonVector aB2DPolyPolyVector;
if( !GetTextOutlines( aB2DPolyPolyVector, rStr, nBase, nIndex, nLen,
- nLayoutWidth, pDXArray ) )
+ nLayoutWidth, pDXArray, pKashidaArray ) )
return false;
// convert to a tool polypolygon vector
diff --git a/vcl/source/outdev/transparent.cxx b/vcl/source/outdev/transparent.cxx
index a4019ca94f85..536498703bb5 100644
--- a/vcl/source/outdev/transparent.cxx
+++ b/vcl/source/outdev/transparent.cxx
@@ -1193,7 +1193,7 @@ tools::Rectangle ImplCalcActionBounds( const MetaAction& rAct, const OutputDevic
// #105987# ImplLayout takes everything in logical coordinates
std::unique_ptr<SalLayout> pSalLayout = rOut.ImplLayout( rTextAct.GetText(), rTextAct.GetIndex(),
rTextAct.GetLen(), rTextAct.GetPoint(),
- 0, rTextAct.GetDXArray());
+ 0, rTextAct.GetDXArray(), rTextAct.GetKashidaArray() );
if( pSalLayout )
{
tools::Rectangle aBoundRect( rOut.ImplGetTextBoundRect( *pSalLayout ) );
diff --git a/vcl/source/text/ImplLayoutArgs.cxx b/vcl/source/text/ImplLayoutArgs.cxx
index 80e85a66dc26..45b951a9845d 100644
--- a/vcl/source/text/ImplLayoutArgs.cxx
+++ b/vcl/source/text/ImplLayoutArgs.cxx
@@ -39,6 +39,7 @@ ImplLayoutArgs::ImplLayoutArgs(const OUString& rStr, int nMinCharPos, int nEndCh
, m_pTextLayoutCache(pLayoutCache)
, mpDXArray(nullptr)
, mpAltNaturalDXArray(nullptr)
+ , mpKashidaArray(nullptr)
, mnLayoutWidth(0)
, mnOrientation(0)
{
@@ -97,6 +98,11 @@ void ImplLayoutArgs::SetAltNaturalDXArray(double const* pDXArray)
mpAltNaturalDXArray = pDXArray;
}
+void ImplLayoutArgs::SetKashidaArray(sal_Bool const* pKashidaArray)
+{
+ mpKashidaArray = pKashidaArray;
+}
+
void ImplLayoutArgs::SetOrientation(Degree10 nOrientation) { mnOrientation = nOrientation; }
void ImplLayoutArgs::ResetPos() { maRuns.ResetPos(); }
@@ -269,7 +275,6 @@ std::ostream& operator<<(std::ostream& s, vcl::text::ImplLayoutArgs const& rArgs
TEST(DisableKerning);
TEST(KerningAsian);
TEST(Vertical);
- TEST(KashidaJustification);
TEST(ForFallback);
#undef TEST
s << "}";
@@ -333,6 +338,31 @@ std::ostream& operator<<(std::ostream& s, vcl::text::ImplLayoutArgs const& rArgs
else
s << "NULL";
+ s << ",KashidaArray=";
+ if (rArgs.mpKashidaArray)
+ {
+ s << "[";
+ int count = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
+ lim = count;
+ if (lim > 10)
+ lim = 7;
+ for (int i = 0; i < lim; i++)
+ {
+ s << rArgs.mpKashidaArray[i];
+ if (i < lim - 1)
+ s << ",";
+ }
+ if (count > lim)
+ {
+ if (count > lim + 1)
+ s << "...";
+ s << rArgs.mpKashidaArray[count - 1];
+ }
+ s << "]";
+ }
+ else
+ s << "NULL";
+
s << ",LayoutWidth=" << rArgs.mnLayoutWidth;
s << "}";
diff --git a/vcl/source/window/menuitemlist.cxx b/vcl/source/window/menuitemlist.cxx
index 173a6204eb48..0efae5b43b8c 100644
--- a/vcl/source/window/menuitemlist.cxx
+++ b/vcl/source/window/menuitemlist.cxx
@@ -48,7 +48,7 @@ SalLayoutGlyphs* MenuItemData::GetTextGlyphs(const OutputDevice* pOutputDevice)
OUString aNonMnemonicString = OutputDevice::GetNonMnemonicString(aText);
std::unique_ptr<SalLayout> pLayout
= pOutputDevice->ImplLayout(aNonMnemonicString, 0, aNonMnemonicString.getLength(),
- Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly);
if (!pLayout)
return nullptr;
diff --git a/vcl/source/window/status.cxx b/vcl/source/window/status.cxx
index 8c701b496b14..81ce41db73e7 100644
--- a/vcl/source/window/status.cxx
+++ b/vcl/source/window/status.cxx
@@ -79,7 +79,7 @@ SalLayoutGlyphs* ImplStatusItem::GetTextGlyphs(const OutputDevice* outputDevice)
if(!mLayoutGlyphsCache.has_value())
{
std::unique_ptr<SalLayout> pSalLayout = outputDevice->ImplLayout(
- maText, 0, -1, Point(0, 0), 0, {}, SalLayoutFlags::GlyphItemsOnly);
+ maText, 0, -1, Point(0, 0), 0, {}, {}, SalLayoutFlags::GlyphItemsOnly);
mLayoutGlyphsCache = pSalLayout ? pSalLayout->GetGlyphs() : SalLayoutGlyphs();
}
return mLayoutGlyphsCache->IsValid() ? &mLayoutGlyphsCache.value() : nullptr;