summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
Diffstat (limited to 'vcl')
-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
23 files changed, 140 insertions, 161 deletions
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;