diff options
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/ImplLayoutArgs.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/impglyphitem.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/pdf/pdfwriter_impl.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/sallayout.hxx | 2 | ||||
-rw-r--r-- | vcl/qa/cppunit/complextext.cxx | 37 | ||||
-rw-r--r-- | vcl/qa/cppunit/svm/svmtest.cxx | 2 | ||||
-rw-r--r-- | vcl/qa/cppunit/text.cxx | 2 | ||||
-rw-r--r-- | vcl/source/control/imp_listbox.cxx | 2 | ||||
-rw-r--r-- | vcl/source/filter/eps/eps.cxx | 12 | ||||
-rw-r--r-- | vcl/source/filter/svm/SvmConverter.cxx | 2 | ||||
-rw-r--r-- | vcl/source/gdi/CommonSalLayout.cxx | 98 | ||||
-rw-r--r-- | vcl/source/gdi/gdimtf.cxx | 4 | ||||
-rw-r--r-- | vcl/source/gdi/impglyphitem.cxx | 25 | ||||
-rw-r--r-- | vcl/source/gdi/metaact.cxx | 12 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter.cxx | 3 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 8 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl2.cxx | 2 | ||||
-rw-r--r-- | vcl/source/gdi/textlayout.cxx | 2 | ||||
-rw-r--r-- | vcl/source/outdev/text.cxx | 42 | ||||
-rw-r--r-- | vcl/source/outdev/transparent.cxx | 2 | ||||
-rw-r--r-- | vcl/source/text/ImplLayoutArgs.cxx | 32 | ||||
-rw-r--r-- | vcl/source/window/menuitemlist.cxx | 2 | ||||
-rw-r--r-- | vcl/source/window/status.cxx | 2 |
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; |