diff options
author | Caolán McNamara <caolanm@redhat.com> | 2022-11-29 20:31:27 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2022-12-02 15:20:07 +0000 |
commit | f9395a123e8c85134bdd6e471bc93b2745e22a9d (patch) | |
tree | fd64e75a7ea36f28e9b993ae0c00480c480803df | |
parent | 1e222575a3b637398b5b2d8e3172f12538ff34e3 (diff) |
tdf#152094 retain more accuracy from RefDevMode::MSO1
do it like this to avoid adding another mapmode and to keep things
"the same" as much as possible
Change-Id: I1965aa545646f2d27b950d6335b2f608c3e4e04b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143475
Tested-by: Caolán McNamara <caolanm@redhat.com>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
56 files changed, 450 insertions, 307 deletions
diff --git a/canvas/source/cairo/cairo_textlayout.cxx b/canvas/source/cairo/cairo_textlayout.cxx index ebfcfe6dc11a..1a6f0143a60a 100644 --- a/canvas/source/cairo/cairo_textlayout.cxx +++ b/canvas/source/cairo/cairo_textlayout.cxx @@ -29,10 +29,10 @@ #include <cppuhelper/supportsservice.hxx> #include <comphelper/diagnose_ex.hxx> #include <utility> +#include <vcl/kernarray.hxx> #include <vcl/metric.hxx> #include <vcl/virdev.hxx> - #include "cairo_textlayout.hxx" using namespace ::cairo; @@ -265,8 +265,7 @@ namespace cairocanvas if (maLogicalAdvancements.hasElements()) { - std::vector<sal_Int32> aOffsets(maLogicalAdvancements.getLength()); - setupTextOffsets( aOffsets.data(), maLogicalAdvancements, viewState, renderState ); + KernArray aOffsets(setupTextOffsets(maLogicalAdvancements, viewState, renderState)); rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets, {}, ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition), @@ -312,14 +311,11 @@ namespace cairocanvas }; } - void TextLayout::setupTextOffsets( sal_Int32* outputOffsets, + KernArray TextLayout::setupTextOffsets( const uno::Sequence< double >& inputOffsets, const rendering::ViewState& viewState, const rendering::RenderState& renderState ) const { - ENSURE_OR_THROW( outputOffsets!=nullptr, - "TextLayout::setupTextOffsets offsets NULL" ); - ::basegfx::B2DHomMatrix aMatrix; ::canvas::tools::mergeViewAndRenderTransform(aMatrix, @@ -327,10 +323,11 @@ namespace cairocanvas renderState); // fill integer offsets - std::transform( inputOffsets.begin(), - inputOffsets.end(), - outputOffsets, - OffsetTransformer( aMatrix ) ); + KernArray outputOffsets; + OffsetTransformer aTransform(aMatrix); + std::for_each(inputOffsets.begin(), inputOffsets.end(), + [&outputOffsets, &aTransform](double n) {outputOffsets.push_back(aTransform(n)); } ); + return outputOffsets; } OUString SAL_CALL TextLayout::getImplementationName() diff --git a/canvas/source/cairo/cairo_textlayout.hxx b/canvas/source/cairo/cairo_textlayout.hxx index fb14e620c518..bec692e75707 100644 --- a/canvas/source/cairo/cairo_textlayout.hxx +++ b/canvas/source/cairo/cairo_textlayout.hxx @@ -85,7 +85,7 @@ namespace cairocanvas const css::rendering::ViewState& viewState, const css::rendering::RenderState& renderState ) const; - void setupTextOffsets( sal_Int32* outputOffsets, + KernArray setupTextOffsets( const css::uno::Sequence< double >& inputOffsets, const css::rendering::ViewState& viewState, const css::rendering::RenderState& renderState ) const; diff --git a/canvas/source/directx/dx_textlayout_drawhelper.cxx b/canvas/source/directx/dx_textlayout_drawhelper.cxx index 0ce689241b7e..9a8771428d93 100644 --- a/canvas/source/directx/dx_textlayout_drawhelper.cxx +++ b/canvas/source/directx/dx_textlayout_drawhelper.cxx @@ -34,6 +34,7 @@ #include <comphelper/diagnose_ex.hxx> #include <tools/poly.hxx> #include <vcl/canvastools.hxx> +#include <vcl/kernarray.hxx> #include <vcl/metric.hxx> #include <vcl/sysdata.hxx> #include <vcl/virdev.hxx> @@ -207,9 +208,10 @@ namespace dxcanvas { // create the DXArray const sal_Int32 nLen( rLogicalAdvancements.getLength() ); - std::vector<sal_Int32> DXArray( nLen ); + KernArray DXArray; + DXArray.reserve(nLen); for( sal_Int32 i=0; i<nLen; ++i ) - DXArray[i] = basegfx::fround( rLogicalAdvancements[i] ); + DXArray.push_back(basegfx::fround(rLogicalAdvancements[i])); // draw the String xVirtualDevice->DrawTextArray( aEmptyPoint, diff --git a/canvas/source/opengl/ogl_canvashelper.cxx b/canvas/source/opengl/ogl_canvashelper.cxx index 257bb21b3218..1b84879b005c 100644 --- a/canvas/source/opengl/ogl_canvashelper.cxx +++ b/canvas/source/opengl/ogl_canvashelper.cxx @@ -22,6 +22,7 @@ #include <rtl/math.hxx> #include <comphelper/diagnose_ex.hxx> #include <vcl/font.hxx> +#include <vcl/kernarray.hxx> #include <vcl/metric.hxx> #include <vcl/virdev.hxx> @@ -729,9 +730,10 @@ namespace oglcanvas { // create the DXArray const sal_Int32 nLen( aLogicalAdvancements.getLength() ); - std::vector<sal_Int32> aDXArray(nLen); + KernArray aDXArray; + aDXArray.resize(nLen); for( sal_Int32 i=0; i<nLen; ++i ) - aDXArray[i] = basegfx::fround( aLogicalAdvancements[i] ); + aDXArray.set(i, basegfx::fround(aLogicalAdvancements[i])); // get the glyphs pVDev->GetTextOutlines(rAct.maPolyPolys, diff --git a/canvas/source/vcl/textlayout.cxx b/canvas/source/vcl/textlayout.cxx index f350a38cd4eb..689720e4570a 100644 --- a/canvas/source/vcl/textlayout.cxx +++ b/canvas/source/vcl/textlayout.cxx @@ -31,6 +31,7 @@ #include <comphelper/sequence.hxx> #include <cppuhelper/supportsservice.hxx> #include <utility> +#include <vcl/kernarray.hxx> #include <vcl/metric.hxx> #include <vcl/virdev.hxx> @@ -117,8 +118,7 @@ namespace vclcanvas uno::Sequence<double>(4), rendering::CompositeOperation::SOURCE); - std::vector<sal_Int32> aOffsets(maLogicalAdvancements.getLength()); - setupTextOffsets(aOffsets.data(), maLogicalAdvancements, aViewState, aRenderState); + KernArray aOffsets(setupTextOffsets(maLogicalAdvancements, aViewState, aRenderState)); std::vector< uno::Reference< rendering::XPolyPolygon2D> > aOutlineSequence; ::basegfx::B2DPolyPolygonVector aOutlines; @@ -165,8 +165,7 @@ namespace vclcanvas uno::Sequence<double>(4), rendering::CompositeOperation::SOURCE); - std::unique_ptr< sal_Int32 []> aOffsets(new sal_Int32[maLogicalAdvancements.getLength()]); - setupTextOffsets(aOffsets.get(), maLogicalAdvancements, aViewState, aRenderState); + KernArray aOffsets(setupTextOffsets(maLogicalAdvancements, aViewState, aRenderState)); std::vector< ::tools::Rectangle > aMetricVector; uno::Sequence<geometry::RealRectangle2D> aBoundingBoxes; @@ -335,8 +334,7 @@ namespace vclcanvas if( maLogicalAdvancements.hasElements() ) { // TODO(P2): cache that - std::vector<sal_Int32> aOffsets(maLogicalAdvancements.getLength()); - setupTextOffsets( aOffsets.data(), maLogicalAdvancements, viewState, renderState ); + KernArray aOffsets(setupTextOffsets(maLogicalAdvancements, viewState, renderState)); // TODO(F3): ensure correct length and termination for DX // array (last entry _must_ contain the overall width) @@ -389,14 +387,11 @@ namespace vclcanvas }; } - void TextLayout::setupTextOffsets( sal_Int32* outputOffsets, + KernArray TextLayout::setupTextOffsets( const uno::Sequence< double >& inputOffsets, const rendering::ViewState& viewState, const rendering::RenderState& renderState ) const { - ENSURE_OR_THROW( outputOffsets!=nullptr, - "TextLayout::setupTextOffsets offsets NULL" ); - ::basegfx::B2DHomMatrix aMatrix; ::canvas::tools::mergeViewAndRenderTransform(aMatrix, @@ -404,10 +399,11 @@ namespace vclcanvas renderState); // fill integer offsets - std::transform( inputOffsets.begin(), - inputOffsets.end(), - outputOffsets, - OffsetTransformer( aMatrix ) ); + KernArray outputOffsets; + OffsetTransformer aTransform(aMatrix); + std::for_each(inputOffsets.begin(), inputOffsets.end(), + [&outputOffsets, &aTransform](double n) {outputOffsets.push_back(aTransform(n)); } ); + return outputOffsets; } OUString SAL_CALL TextLayout::getImplementationName() diff --git a/canvas/source/vcl/textlayout.hxx b/canvas/source/vcl/textlayout.hxx index 5a403c28070a..be8603d812f1 100644 --- a/canvas/source/vcl/textlayout.hxx +++ b/canvas/source/vcl/textlayout.hxx @@ -29,7 +29,6 @@ #include "canvasfont.hxx" #include "impltools.hxx" - /* Definition of TextLayout class */ namespace vclcanvas @@ -85,7 +84,7 @@ namespace vclcanvas const css::rendering::RenderState& renderState ) const; private: - void setupTextOffsets( sal_Int32* outputOffsets, + KernArray setupTextOffsets( const css::uno::Sequence< double >& inputOffsets, const css::rendering::ViewState& viewState, const css::rendering::RenderState& renderState ) const; diff --git a/cppcanvas/source/inc/implrenderer.hxx b/cppcanvas/source/inc/implrenderer.hxx index 44a168ee9225..edf4fcf9efba 100644 --- a/cppcanvas/source/inc/implrenderer.hxx +++ b/cppcanvas/source/inc/implrenderer.hxx @@ -194,7 +194,7 @@ namespace cppcanvas::internal const OUString& rString, int nIndex, int nLength, - o3tl::span<const sal_Int32> pCharWidths, + KernArraySpan pCharWidths, const ActionFactoryParameters& rParms, bool bSubsettable ); diff --git a/cppcanvas/source/mtfrenderer/implrenderer.cxx b/cppcanvas/source/mtfrenderer/implrenderer.cxx index 3046d880125e..130d19af95f7 100644 --- a/cppcanvas/source/mtfrenderer/implrenderer.cxx +++ b/cppcanvas/source/mtfrenderer/implrenderer.cxx @@ -846,7 +846,7 @@ namespace cppcanvas::internal const OUString& rString, int nIndex, int nLength, - o3tl::span<const sal_Int32> pCharWidths, + KernArraySpan pCharWidths, const ActionFactoryParameters& rParms, bool bSubsettableActions ) { @@ -984,16 +984,16 @@ namespace cppcanvas::internal { ::tools::Long nInterval = ( nWidth - nStrikeoutWidth * nLen ) / nLen; nStrikeoutWidth += nInterval; - std::vector<sal_Int32> aStrikeoutCharWidths(nLen); + KernArray aStrikeoutCharWidths; for ( int i = 0;i<nLen; i++) { - aStrikeoutCharWidths[i] = nStrikeoutWidth; + aStrikeoutCharWidths.push_back(nStrikeoutWidth); } for ( int i = 1;i< nLen; i++ ) { - aStrikeoutCharWidths[ i ] += aStrikeoutCharWidths[ i-1 ]; + aStrikeoutCharWidths.adjust(i, aStrikeoutCharWidths[i - 1]); } pStrikeoutTextAction = @@ -2554,7 +2554,7 @@ namespace cppcanvas::internal // generating a DX array, and uniformly // distributing the excess/insufficient width // to every logical character. - std::vector<sal_Int32> aDXArray; + KernArray aDXArray; rVDev.GetTextArray( pAct->GetText(), &aDXArray, pAct->GetIndex(), pAct->GetLen() ); @@ -2562,7 +2562,6 @@ namespace cppcanvas::internal const sal_Int32 nWidthDifference( pAct->GetWidth() - aDXArray[ nLen-1 ] ); // Last entry of pDXArray contains total width of the text - sal_Int32* p = aDXArray.data(); for (sal_Int32 i = 1; i <= nLen; ++i) { // calc ratio for every array entry, to @@ -2571,7 +2570,7 @@ namespace cppcanvas::internal // entry represents the 'end' position of // the corresponding character, thus, we // let i run from 1 to nLen. - *p++ += i * nWidthDifference / nLen; + aDXArray.adjust(i - 1, i * nWidthDifference / nLen); } createTextAction( diff --git a/cppcanvas/source/mtfrenderer/textaction.cxx b/cppcanvas/source/mtfrenderer/textaction.cxx index f7844c802452..4b945c2f2ce3 100644 --- a/cppcanvas/source/mtfrenderer/textaction.cxx +++ b/cppcanvas/source/mtfrenderer/textaction.cxx @@ -158,7 +158,7 @@ namespace cppcanvas::internal rLayoutWidth = *(std::max_element(rOffsets.begin(), rOffsets.end())); } - uno::Sequence< double > setupDXArray( o3tl::span<const sal_Int32> rCharWidths, + uno::Sequence< double > setupDXArray( KernArraySpan rCharWidths, sal_Int32 nLen, const OutDevState& rState ) { @@ -170,11 +170,10 @@ namespace cppcanvas::internal // array, by circumventing integer-based // OutDev-mapping const double nScale( rState.mapModeTransform.get(0,0) ); - sal_Int32 const * pCharWidths = rCharWidths.data(); for( int i = 0; i < nLen; ++i ) { // TODO(F2): use correct scale direction - *pOutputWidths++ = *pCharWidths++ * nScale; + *pOutputWidths++ = rCharWidths[i] * nScale; } return aCharWidthSeq; @@ -188,7 +187,7 @@ namespace cppcanvas::internal { // no external DX array given, create one from given // string - std::vector<sal_Int32> aCharWidths; + KernArray aCharWidths; rVDev.GetTextArray( rText, &aCharWidths, nStartPos, nLen ); @@ -1967,7 +1966,7 @@ namespace cppcanvas::internal const OUString& rText, sal_Int32 nStartPos, sal_Int32 nLen, - o3tl::span<const sal_Int32> pDXArray, + KernArraySpan pDXArray, VirtualDevice& rVDev, const CanvasSharedPtr& rCanvas, const OutDevState& rState, @@ -2097,7 +2096,7 @@ namespace cppcanvas::internal const OUString& rText, sal_Int32 nStartPos, sal_Int32 nLen, - o3tl::span<const sal_Int32> pDXArray, + KernArraySpan pDXArray, VirtualDevice& rVDev, const CanvasSharedPtr& rCanvas, const OutDevState& rState, diff --git a/cppcanvas/source/mtfrenderer/textaction.hxx b/cppcanvas/source/mtfrenderer/textaction.hxx index f59ed4115c76..66d08ca8cfa2 100644 --- a/cppcanvas/source/mtfrenderer/textaction.hxx +++ b/cppcanvas/source/mtfrenderer/textaction.hxx @@ -68,7 +68,7 @@ namespace cppcanvas::internal const OUString& rText, sal_Int32 nStartPos, sal_Int32 nLen, - o3tl::span<const sal_Int32> pDXArray, + KernArraySpan pDXArray, VirtualDevice& rVDev, const CanvasSharedPtr& rCanvas, const OutDevState& rState, diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index fcc9b401fa48..ea9fed02a20f 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -29,6 +29,7 @@ #include <osl/diagnose.h> #include <tools/gen.hxx> #include <vcl/canvastools.hxx> +#include <vcl/kernarray.hxx> #include <vcl/timer.hxx> #include <vcl/virdev.hxx> #include <vcl/font.hxx> @@ -231,12 +232,11 @@ void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPoly { OSL_ENSURE(nDXArrayCount == nTextLength, "DXArray size does not correspond to text portion size (!)"); - std::vector<sal_Int32> aIntegerDXArray(nDXArrayCount); + KernArray aIntegerDXArray; + aIntegerDXArray.reserve(nDXArrayCount); for (sal_uInt32 a(0); a < nDXArrayCount; a++) - { - aIntegerDXArray[a] = basegfx::fround(rDXArray[a]); - } + aIntegerDXArray.push_back(basegfx::fround(rDXArray[a])); mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, nLength, 0, aIntegerDXArray, rKashidaArray); @@ -307,10 +307,11 @@ std::vector<double> TextLayouterDevice::getTextArray(const OUString& rText, sal_ if (nTextLength) { - aRetval.reserve(nTextLength); - std::vector<sal_Int32> aArray; + KernArray aArray; mrDevice.GetTextArray(rText, &aArray, nIndex, nTextLength); - aRetval.assign(aArray.begin(), aArray.end()); + aRetval.reserve(aArray.size()); + for (size_t i = 0, nEnd = aArray.size(); i < nEnd; ++i) + aRetval.push_back(aArray[i]); } return aRetval; diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index e1d56f4da9b1..bd92921396ae 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -29,6 +29,7 @@ #include <utility> #include <vcl/glyphitemcache.hxx> #include <vcl/graph.hxx> +#include <vcl/kernarray.hxx> #include <vcl/outdev.hxx> #include <rtl/ustrbuf.hxx> #include <sal/log.hxx> @@ -282,7 +283,7 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D( } // create integer DXArray - std::vector<sal_Int32> aDXArray; + KernArray aDXArray; if (!rTextCandidate.getDXArray().empty()) { @@ -335,7 +336,7 @@ void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D( sal_Int32 nDX = aDXArray[0]; aDXArray.resize(nLen); for (sal_Int32 i = 1; i < nLen; ++i) - aDXArray[i] = aDXArray[i - 1] + nDX; + aDXArray.set(i, aDXArray[i - 1] + nDX); } } diff --git a/drawinglayer/source/tools/wmfemfhelper.cxx b/drawinglayer/source/tools/wmfemfhelper.cxx index 7b1f83b43195..4790465a7366 100644 --- a/drawinglayer/source/tools/wmfemfhelper.cxx +++ b/drawinglayer/source/tools/wmfemfhelper.cxx @@ -1797,7 +1797,7 @@ namespace wmfemfhelper { // prepare DXArray (if used) std::vector< double > aDXArray; - const std::vector<sal_Int32> & rDXArray = pA->GetDXArray(); + const KernArray& rDXArray = pA->GetDXArray(); std::vector< sal_Bool > aKashidaArray = pA->GetKashidaArray(); if(!rDXArray.empty()) diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 2d2a339658df..2ce9a60f3eee 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -838,7 +838,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) EditLine aSaveLine( *pLine ); SvxFont aTmpFont( pNode->GetCharAttribs().GetDefFont() ); - std::vector<sal_Int32> aCharPositionArray(pNode->Len()); + KernArray aCharPositionArray; bool bSameLineAgain = false; // For TextRanger, if the height changes. TabInfo aCurrentTab; @@ -1127,7 +1127,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) OUString aFieldValue = static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue(); // get size, but also DXArray to allow length information in line breaking below - std::vector<sal_Int32> aTmpDXArray; + KernArray aTmpDXArray; pPortion->SetSize(aTmpFont.QuickGetTextSize(GetRefDevice(), aFieldValue, 0, aFieldValue.getLength(), &aTmpDXArray)); @@ -1256,7 +1256,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // => Always simply quick inserts. size_t nPos = nTmpPos - pLine->GetStart(); EditLine::CharPosArrayType& rArray = pLine->GetCharPosArray(); - rArray.insert( rArray.begin() + nPos, aCharPositionArray.data(), aCharPositionArray.data() + nPortionLen); + assert(aCharPositionArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aCharPositionArray.get_subunit_array(); + rArray.insert( rArray.begin() + nPos, rKernArray.data(), rKernArray.data() + nPortionLen); // And now check for Compression: if ( !bContinueLastPortion && nPortionLen && GetAsianCompressionMode() != CharCompressType::NONE ) @@ -3462,7 +3464,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po sal_Int32 nTextLen = 0; o3tl::span<const sal_Int32> pDXArray; o3tl::span<const sal_Bool> pKashidaArray; - std::vector<sal_Int32> aTmpDXArray; + KernArray aTmpDXArray; if ( rTextPortion.GetKind() == PortionKind::TEXT ) { @@ -3604,7 +3606,9 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetPhysFont(*GetRefDevice()); aTmpFont.QuickGetTextSize( GetRefDevice(), aText, nTextStart, nTextLen, &aTmpDXArray ); - pDXArray = aTmpDXArray; + assert(aTmpDXArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aTmpDXArray.get_subunit_array(); + pDXArray = rKernArray; // add a meta file comment if we record to a metafile if( bMetafileValid ) @@ -3631,7 +3635,9 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetPhysFont(*GetRefDevice()); aTmpFont.QuickGetTextSize( GetRefDevice(), aText, 0, aText.getLength(), &aTmpDXArray ); - pDXArray = aTmpDXArray; + assert(aTmpDXArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aTmpDXArray.get_subunit_array(); + pDXArray = rKernArray; } tools::Long nTxtWidth = rTextPortion.GetSize().Width(); diff --git a/editeng/source/items/svxfont.cxx b/editeng/source/items/svxfont.cxx index b6f9617a4c27..b484a645a7f6 100644 --- a/editeng/source/items/svxfont.cxx +++ b/editeng/source/items/svxfont.cxx @@ -32,7 +32,7 @@ #include <sal/log.hxx> #include <limits> -static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr, std::vector<sal_Int32>* pDXAry, +static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr, KernArray* pDXAry, sal_Int32 nIndex, sal_Int32 nLen ) { @@ -441,7 +441,7 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const OUString &rTxt, if( IsFixKerning() && ( nLen > 1 ) ) { auto nKern = GetFixKerning(); - std::vector<sal_Int32> aDXArray; + KernArray aDXArray(nLen); GetTextArray(pOut, rTxt, &aDXArray, nIdx, nLen); tools::Long nOldValue = aDXArray[0]; sal_Int32 nSpaceCount = 0; @@ -475,13 +475,13 @@ Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut ) } Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, - const sal_Int32 nIdx, const sal_Int32 nLen, std::vector<sal_Int32>* pDXArray ) const + const sal_Int32 nIdx, const sal_Int32 nLen, KernArray* pDXArray ) const { if ( !IsCaseMap() && !IsFixKerning() ) return Size( GetTextArray( pOut, rTxt, pDXArray, nIdx, nLen ), pOut->GetTextHeight() ); - std::vector<sal_Int32> aDXArray; + KernArray aDXArray; // We always need pDXArray to count the number of kern spaces if (!pDXArray && IsFixKerning() && nLen > 1) @@ -503,7 +503,7 @@ Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, auto nKern = GetFixKerning(); tools::Long nOldValue = (*pDXArray)[0]; tools::Long nSpaceSum = nKern; - (*pDXArray)[0] += nSpaceSum; + pDXArray->adjust(0, nSpaceSum); for ( sal_Int32 i = 1; i < nLen; i++ ) { @@ -512,14 +512,14 @@ Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, nOldValue = (*pDXArray)[i]; nSpaceSum += nKern; } - (*pDXArray)[i] += nSpaceSum; + pDXArray->adjust(i, nSpaceSum); } // The last one is a nKern too big: nOldValue = (*pDXArray)[nLen - 1]; tools::Long nNewValue = nOldValue - nKern; for ( sal_Int32 i = nLen - 1; i >= 0 && (*pDXArray)[i] == nOldValue; --i) - (*pDXArray)[i] = nNewValue; + pDXArray->set(i, nNewValue); aTxtSize.AdjustWidth(nSpaceSum - nKern); } diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index 9254bae2ab77..84097ae2a14b 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -964,7 +964,7 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& if(bStrippingPortions) { const vcl::Font& aSvxFont(rOutDev.GetFont()); - std::vector<sal_Int32> aBuf; + KernArray aBuf; rOutDev.GetTextArray( pPara->GetText(), &aBuf ); if(bSymbol) @@ -974,7 +974,8 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& aTextPos.AdjustY( -(aMetric.GetDescent()) ); } - DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), aBuf, {}, + assert(aBuf.get_factor() == 1); + DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), aBuf.get_subunit_array(), {}, aSvxFont, nPara, bRightToLeftPara ? 1 : 0, nullptr, nullptr, false, false, true, nullptr, Color(), Color()); } else diff --git a/emfio/inc/mtftools.hxx b/emfio/inc/mtftools.hxx index b4fd6394c69b..f7a318f39d55 100644 --- a/emfio/inc/mtftools.hxx +++ b/emfio/inc/mtftools.hxx @@ -809,7 +809,7 @@ namespace emfio ); void DrawText(Point& rPosition, OUString const & rString, - std::vector<sal_Int32>* pDXArry = nullptr, + KernArray* pDXArry = nullptr, tools::Long* pDYArry = nullptr, bool bRecordPath = false, GraphicsMode nGraphicsMode = GraphicsMode::GM_COMPATIBLE); diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx index 207d8373e309..c24a053d3bc1 100644 --- a/emfio/source/reader/emfreader.cxx +++ b/emfio/source/reader/emfreader.cxx @@ -1817,7 +1817,7 @@ namespace emfio SAL_INFO("emfio", "\t\tText: " << aText); SAL_INFO("emfio", "\t\tDxBuffer:"); - std::vector<sal_Int32> aDXAry; + KernArray aDXAry; std::unique_ptr<tools::Long[]> pDYAry; sal_Int32 nDxSize; @@ -1857,7 +1857,7 @@ namespace emfio } } - aDXAry[i] = 0; + aDXAry.set(i, 0); if (nOptions & ETO_PDY) { pDYAry[i] = 0; @@ -1867,7 +1867,7 @@ namespace emfio { sal_Int32 nDxTmp = 0; mpInputStream->ReadInt32(nDxTmp); - aDXAry[i] = o3tl::saturating_add(aDXAry[i], nDxTmp); + aDXAry.set(i, o3tl::saturating_add(aDXAry[i], nDxTmp)); if (nOptions & ETO_PDY) { sal_Int32 nDyTmp = 0; diff --git a/emfio/source/reader/mtftools.cxx b/emfio/source/reader/mtftools.cxx index 7acb1a2b7c1f..2683151166b2 100644 --- a/emfio/source/reader/mtftools.cxx +++ b/emfio/source/reader/mtftools.cxx @@ -1644,7 +1644,7 @@ namespace emfio } } - void MtfTools::DrawText( Point& rPosition, OUString const & rText, std::vector<sal_Int32>* pDXArry, tools::Long* pDYArry, bool bRecordPath, GraphicsMode nGfxMode ) + void MtfTools::DrawText( Point& rPosition, OUString const & rText, KernArray* pDXArry, tools::Long* pDYArry, bool bRecordPath, GraphicsMode nGfxMode ) { UpdateClipRegion(); rPosition = ImplMap( rPosition ); @@ -1661,8 +1661,7 @@ namespace emfio // #i121382# Map DXArray using WorldTransform const Size aSizeX(ImplMap(Size(nSumX, 0))); const basegfx::B2DVector aVectorX(aSizeX.Width(), aSizeX.Height()); - (*pDXArry)[i] = basegfx::fround(aVectorX.getLength()); - (*pDXArry)[i] *= (nSumX >= 0 ? 1 : -1); + pDXArry->set(i, basegfx::fround(aVectorX.getLength()) * (nSumX >= 0 ? 1 : -1)); if (pDYArry) { @@ -1828,18 +1827,18 @@ 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] ), KernArraySpan(), {}, 0, 1 ) ); } } else { /* because text without dx array is badly scaled, we will create such an array if necessary */ - o3tl::span<const sal_Int32> pDX; - std::vector<sal_Int32> aMyDXArray; + KernArraySpan pDX; + KernArray aMyDXArray; if (pDXArry) { - pDX = { pDXArry->data(), pDXArry->size() }; + pDX = *pDXArry; // only useful when we have an imported DXArray if(!rText.isEmpty()) { diff --git a/emfio/source/reader/wmfreader.cxx b/emfio/source/reader/wmfreader.cxx index 92431e06d42b..8825fa5fdea1 100644 --- a/emfio/source/reader/wmfreader.cxx +++ b/emfio/source/reader/wmfreader.cxx @@ -726,7 +726,7 @@ namespace emfio IntersectClipRect( aRect ); } SAL_INFO( "emfio", "\t\t\t Text : " << aText ); - std::vector<sal_Int32> aDXAry; + KernArray aDXAry; std::unique_ptr<tools::Long[]> pDYAry; auto nDxArySize = nMaxStreamPos - mpInputStream->Tell(); auto nDxAryEntries = nDxArySize >> 1; @@ -773,7 +773,7 @@ namespace emfio } } - aDXAry[ i ] = nDx; + aDXAry.set(i, nDx); if ( nOptions & ETO_PDY ) { pDYAry[i] = nDy; @@ -1201,7 +1201,7 @@ namespace emfio { Point aPt; sal_uInt32 nStringLen, nDXCount; - std::vector<sal_Int32> aDXAry; + KernArray aDXAry; SvMemoryStream aMemoryStream( nEscLen ); aMemoryStream.WriteBytes(pData.get(), nEscLen); aMemoryStream.Seek( STREAM_SEEK_TO_BEGIN ); @@ -1224,7 +1224,7 @@ namespace emfio { sal_Int32 val; aMemoryStream.ReadInt32( val); - aDXAry[ i ] = val; + aDXAry.set(i, val); } aMemoryStream.ReadUInt32(mnSkipActions); DrawText( aPt, aString, aDXAry.empty() ? nullptr : &aDXAry ); diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index 10b81595f7f8..e4420dc27e71 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -2573,7 +2573,7 @@ void SVGActionWriter::ImplWriteMask(GDIMetaFile& rMtf, const Point& rDestPt, con void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, - o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth ) + KernArraySpan pDXArray, tools::Long nWidth ) { const FontMetric aMetric( mpVDev->GetFontMetric() ); @@ -2664,7 +2664,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, - o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth, + KernArraySpan pDXArray, tools::Long nWidth, Color aTextColor ) { sal_Int32 nLen = rText.getLength(); @@ -2681,18 +2681,17 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, ImplMap( rPos, aPos ); - std::vector<sal_Int32> aTmpArray(nLen); + KernArray aTmpArray; // get text sizes if( !pDXArray.empty() ) { aNormSize = Size( mpVDev->GetTextWidth( rText ), 0 ); - memcpy(aTmpArray.data(), pDXArray.data(), nLen * sizeof(sal_Int32)); + aTmpArray.assign(pDXArray); } else { aNormSize = Size( mpVDev->GetTextArray( rText, &aTmpArray ), 0 ); } - sal_Int32* pDX = aTmpArray.data(); // if text is rotated, set transform matrix at new g element if( rFont.GetOrientation() ) @@ -2740,7 +2739,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, { if( nLen > 1 ) { - aNormSize.setWidth( pDX[ nLen - 2 ] + mpVDev->GetTextWidth( OUString(rText[nLen - 1]) ) ); + aNormSize.setWidth( aTmpArray[ nLen - 2 ] + mpVDev->GetTextWidth( OUString(rText[nLen - 1]) ) ); if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) ) { @@ -2748,7 +2747,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, const double fFactor = static_cast<double>(nWidth) / aNormSize.Width(); for( i = 0; i < ( nLen - 1 ); i++ ) - pDX[ i ] = FRound( pDX[ i ] * fFactor ); + aTmpArray.set(i, FRound(aTmpArray[i] * fFactor)); } else { @@ -2784,7 +2783,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, if( bCont ) { // #118796# do NOT access pDXArray, it may be zero (!) - sal_Int32 nDXWidth = pDX[ nCurPos - 1 ]; + sal_Int32 nDXWidth = aTmpArray[ nCurPos - 1 ]; nDXWidth = ImplMap( nDXWidth ); nX = aPos.X() + nDXWidth; } diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx index d48d68bdec72..022c2585c5ab 100644 --- a/filter/source/svg/svgwriter.hxx +++ b/filter/source/svg/svgwriter.hxx @@ -346,8 +346,8 @@ private: static Color ImplGetColorWithIntensity( const Color& rColor, sal_uInt16 nIntensity ); static Color ImplGetGradientColor( const Color& rStartColor, const Color& rEndColor, double fOffset ); void ImplWriteMask( GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, sal_uInt32 nWriteFlags ); - void ImplWriteText( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth ); - void ImplWriteText( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth, Color aTextColor ); + void ImplWriteText( const Point& rPos, const OUString& rText, KernArraySpan pDXArray, tools::Long nWidth ); + void ImplWriteText( const Point& rPos, const OUString& rText, KernArraySpan pDXArray, tools::Long nWidth, Color aTextColor ); void ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const css::uno::Reference<css::drawing::XShape>* pShape); void ImplWriteActions( const GDIMetaFile& rMtf, diff --git a/include/editeng/svxfont.hxx b/include/editeng/svxfont.hxx index f4810ba25640..0968181327e8 100644 --- a/include/editeng/svxfont.hxx +++ b/include/editeng/svxfont.hxx @@ -30,6 +30,7 @@ // See i#1526# for full explanation #define SMALL_CAPS_PERCENTAGE 80 +class KernArray; class SvxDoCapitals; class OutputDevice; class Printer; @@ -95,7 +96,7 @@ public: Size QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, const sal_Int32 nIdx, const sal_Int32 nLen, - std::vector<sal_Int32>* pDXArray = nullptr ) const; + KernArray* pDXArray = nullptr ) const; void DrawPrev( OutputDevice* pOut, Printer* pPrinter, const Point &rPos, const OUString &rTxt, diff --git a/include/vcl/kernarray.hxx b/include/vcl/kernarray.hxx new file mode 100644 index 000000000000..096fd8be7e87 --- /dev/null +++ b/include/vcl/kernarray.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include <sal/config.h> +#include <o3tl/span.hxx> +#include <cmath> +#include <vector> + +class KernArraySpan final +{ +private: + int m_nSubUnitFactor; + o3tl::span<const sal_Int32> m_DXArray; + +public: + KernArraySpan() + : m_nSubUnitFactor(1) + { + } + + KernArraySpan(o3tl::span<const sal_Int32> DXArray, int nSubUnitFactor = 1) + : m_nSubUnitFactor(nSubUnitFactor) + , m_DXArray(DXArray) + { + } + size_t size() const { return m_DXArray.size(); } + bool empty() const { return m_DXArray.empty(); } + sal_Int32 operator[](size_t nIndex) const { return get(nIndex); } + sal_Int32 get(size_t nIndex) const { return std::round(m_DXArray[nIndex] / m_nSubUnitFactor); } + + int get_factor() const { return m_nSubUnitFactor; } + sal_Int32 get_subunit(size_t nIndex) const { return m_DXArray[nIndex]; } +}; + +class KernArray final +{ +private: + int m_nSubUnitFactor; + std::vector<sal_Int32> m_aDXArray; + +public: + KernArray(int nSubUnitFactor = 1) + : m_nSubUnitFactor(nSubUnitFactor) + { + } + + sal_Int32 operator[](size_t nIndex) const { return get(nIndex); } + sal_Int32 get(size_t nIndex) const { return std::round(m_aDXArray[nIndex] / m_nSubUnitFactor); } + + int get_factor() const { return m_nSubUnitFactor; } + sal_Int32 get_subunit(size_t nIndex) const { return m_aDXArray[nIndex]; } + + void set_subunit(size_t nIndex, sal_Int32 nValue) { m_aDXArray[nIndex] = nValue; } + std::vector<sal_Int32>& get_subunit_array() { return m_aDXArray; } + + void adjust(size_t nIndex, sal_Int32 nDiff) { m_aDXArray[nIndex] += nDiff * m_nSubUnitFactor; } + void set(size_t nIndex, sal_Int32 nValue) { m_aDXArray[nIndex] = nValue * m_nSubUnitFactor; } + void push_back(sal_Int32 nUnit) { m_aDXArray.push_back(nUnit * m_nSubUnitFactor); } + sal_Int32 back() const { return m_aDXArray.back() * m_nSubUnitFactor; } + size_t size() const { return m_aDXArray.size(); } + bool empty() const { return m_aDXArray.empty(); } + void clear() { m_aDXArray.clear(); } + void assign(KernArraySpan other) + { + m_nSubUnitFactor = other.get_factor(); + m_aDXArray.clear(); + size_t nLen = other.size(); + m_aDXArray.reserve(nLen); + for (size_t i = 0; i < nLen; ++i) + m_aDXArray.push_back(other.get_subunit(i)); + } + void resize(size_t nSize) { m_aDXArray.resize(nSize); } + void resize(size_t nSize, sal_Int32 nDefault) + { + m_aDXArray.resize(nSize, nDefault * m_nSubUnitFactor); + } + void reserve(size_t nCapacity) { m_aDXArray.reserve(nCapacity); } + + bool operator==(const KernArray& rOther) const + { + size_t nSize = size(); + if (nSize != rOther.size()) + return false; + for (size_t i = 0; i < nSize; ++i) + if (m_aDXArray[i] != rOther.m_aDXArray[i]) + return false; + return true; + } + + operator KernArraySpan() const { return KernArraySpan(m_aDXArray, m_nSubUnitFactor); } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/vcl/metaact.hxx b/include/vcl/metaact.hxx index 11caf48b2429..c820d93b560c 100644 --- a/include/vcl/metaact.hxx +++ b/include/vcl/metaact.hxx @@ -37,6 +37,7 @@ #include <vcl/gfxlink.hxx> #include <vcl/gradient.hxx> #include <vcl/hatch.hxx> +#include <vcl/kernarray.hxx> #include <vcl/lineinfo.hxx> #include <vcl/metaactiontypes.hxx> #include <vcl/region.hxx> @@ -506,7 +507,7 @@ private: Point maStartPt; OUString maStr; - std::vector<sal_Int32> maDXAry; + KernArray maDXAry; std::vector<sal_Bool> maKashidaAry; sal_Int32 mnIndex; sal_Int32 mnLen; @@ -517,12 +518,12 @@ public: MetaTextArrayAction(); MetaTextArrayAction( const MetaTextArrayAction& rAction ); MetaTextArrayAction( const Point& rStartPt, OUString aStr, - std::vector<sal_Int32> rDXAry, + KernArray rDXAry, std::vector<sal_Bool> pKashidaAry, sal_Int32 nIndex, sal_Int32 nLen ); MetaTextArrayAction( const Point& rStartPt, OUString aStr, - o3tl::span<const sal_Int32> pDXAry, + KernArraySpan pDXAry, o3tl::span<const sal_Bool> pKashidaAry, sal_Int32 nIndex, sal_Int32 nLen ); @@ -538,13 +539,13 @@ public: const OUString& GetText() const { return maStr; } sal_Int32 GetIndex() const { return mnIndex; } sal_Int32 GetLen() const { return mnLen; } - const std::vector<sal_Int32> & GetDXArray() const { return maDXAry; } + const KernArray& 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 SetDXArray(KernArray aArray); void SetKashidaArray(std::vector<sal_Bool> aArray); }; diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 11cfaa3c4dd3..b2053f412b49 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -32,6 +32,7 @@ #include <vcl/devicecoordinate.hxx> #include <vcl/dllapi.h> #include <vcl/font.hxx> +#include <vcl/kernarray.hxx> #include <vcl/region.hxx> #include <vcl/rendercontext/AddFontSubstituteFlags.hxx> #include <vcl/rendercontext/AntialiasingFlags.hxx> @@ -956,7 +957,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 = {}, + sal_uLong nLayoutWidth = 0, KernArraySpan aDXArray = KernArraySpan(), o3tl::span<const sal_Bool> pKashidaArray = {}, const SalLayoutGlyphs* pGlyphs = nullptr ) const; @@ -968,20 +969,20 @@ 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 = {}, + sal_uLong nLayoutWidth = 0, KernArraySpan aDXArray = KernArraySpan(), 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 = {}, + sal_uLong nLayoutWidth = 0, KernArraySpan aDXArray = KernArraySpan(), o3tl::span<const sal_Bool> pKashidaArray = {} ) const; OUString GetEllipsisString( const OUString& rStr, tools::Long nMaxWidth, DrawTextFlags nStyle = DrawTextFlags::EndEllipsis ) const; - tools::Long GetCtrlTextWidth( const OUString& rStr, + tools::Long GetCtrlTextWidth( const OUString& rStr, const SalLayoutGlyphs* pLayoutCache = nullptr ) const; /** Generate MetaTextActions for the text rect @@ -1035,13 +1036,13 @@ public: float approximate_digit_width() const; void DrawTextArray( const Point& rStartPt, const OUString& rStr, - o3tl::span<const sal_Int32> pDXAry, + KernArraySpan aKernArray, o3tl::span<const sal_Bool> pKashidaAry, sal_Int32 nIndex, sal_Int32 nLen, SalLayoutFlags flags = SalLayoutFlags::NONE, const SalLayoutGlyphs* pLayoutCache = nullptr); - tools::Long GetTextArray( const OUString& rStr, std::vector<sal_Int32>* pDXAry, + tools::Long GetTextArray( const OUString& rStr, KernArray* pDXAry, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, bool bCaret = false, vcl::text::TextLayoutCache const* = nullptr, SalLayoutGlyphs const*const pLayoutCache = nullptr) const; @@ -1224,7 +1225,7 @@ 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={}, + KernArraySpan aKernArray = KernArraySpan(), o3tl::span<const sal_Bool> pKashidaArray={}, SalLayoutFlags flags = SalLayoutFlags::NONE, vcl::text::TextLayoutCache const* = nullptr, diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx index 5d06b1b05c96..8aeade99f504 100644 --- a/include/vcl/pdfwriter.hxx +++ b/include/vcl/pdfwriter.hxx @@ -765,7 +765,7 @@ The following structure describes the permissions used in PDF security FontLineStyle eUnderline, FontLineStyle eOverline ); void DrawTextArray( const Point& rStartPt, const OUString& rStr, - o3tl::span<const sal_Int32> pDXAry, + KernArraySpan aKernArray, o3tl::span<const sal_Bool> pKashidaAry, sal_Int32 nIndex, sal_Int32 nLen ); diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index 28d448fc69b9..5f09c292c176 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -47,6 +47,7 @@ #include <svl/numformat.hxx> #include <svl/zforlist.hxx> #include <svl/zformat.hxx> +#include <vcl/kernarray.hxx> #include <vcl/svapp.hxx> #include <vcl/metric.hxx> #include <vcl/outdev.hxx> @@ -1522,7 +1523,7 @@ tools::Rectangle ScOutputData::LayoutStrings(bool bPixelToLogic, bool bPaint, co // before processing the cell value. std::vector<std::unique_ptr<ScPatternAttr> > aAltPatterns; - std::vector<sal_Int32> aDX; + KernArray aDX; tools::Long nPosY = nScrY; for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) { @@ -2107,7 +2108,7 @@ tools::Rectangle ScOutputData::LayoutStrings(bool bPixelToLogic, bool bPaint, co { double fMul = GetStretch(); for (size_t i = 0; i < nLen; ++i) - aDX[i] = static_cast<sal_Int32>(aDX[i] / fMul + 0.5); + aDX.set(i, static_cast<sal_Int32>(aDX[i] / fMul + 0.5)); } if (bPaint) diff --git a/starmath/source/accessibility.cxx b/starmath/source/accessibility.cxx index f94ee353ce58..a2a5641cdfee 100644 --- a/starmath/source/accessibility.cxx +++ b/starmath/source/accessibility.cxx @@ -30,6 +30,7 @@ #include <cppuhelper/supportsservice.hxx> #include <osl/diagnose.h> #include <comphelper/diagnose_ex.hxx> +#include <vcl/kernarray.hxx> #include <vcl/svapp.hxx> #include <vcl/unohelp2.hxx> #include <vcl/settings.hxx> @@ -472,7 +473,7 @@ awt::Rectangle SAL_CALL SmGraphicAccessible::getCharacterBounds( sal_Int32 nInde weld::DrawingArea* pDrawingArea = pWin->GetDrawingArea(); OutputDevice& rDevice = pDrawingArea->get_ref_device(); - std::vector<sal_Int32> aXAry; + KernArray aXAry; rDevice.SetFont( pNode->GetFont() ); rDevice.GetTextArray( aNodeText, &aXAry, 0, aNodeText.getLength() ); aTLPos.AdjustX(nNodeIndex > 0 ? aXAry[nNodeIndex - 1] : 0 ); @@ -544,7 +545,7 @@ sal_Int32 SAL_CALL SmGraphicAccessible::getIndexAtPoint( const awt::Point& aPoin tools::Long nNodeX = pNode->GetLeft(); - std::vector<sal_Int32> aXAry; + KernArray aXAry; rDevice.SetFont( pNode->GetFont() ); rDevice.GetTextArray( aTxt, &aXAry, 0, aTxt.getLength() ); for (sal_Int32 i = 0; i < aTxt.getLength() && nRes == -1; ++i) diff --git a/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx b/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx index 657532a10e62..e8e3bd026cd1 100644 --- a/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx +++ b/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx @@ -21,6 +21,7 @@ #include <svl/itemset.hxx> #include <svx/svddef.hxx> #include <svx/svdopath.hxx> +#include <vcl/kernarray.hxx> #include <vcl/metric.hxx> #include <svx/sdasitm.hxx> #include <svx/sdtfsitm.hxx> @@ -363,7 +364,7 @@ static void GetTextAreaOutline( } else { - std::vector<sal_Int32> aDXArry; + KernArray aDXArry; if ( ( nCharScaleWidth != 100 ) && nCharScaleWidth ) { // applying character spacing pVirDev->GetTextArray( rText, &aDXArry); diff --git a/sw/qa/core/txtnode/justify.cxx b/sw/qa/core/txtnode/justify.cxx index 1565703f1f9e..6a8afd2b52ef 100644 --- a/sw/qa/core/txtnode/justify.cxx +++ b/sw/qa/core/txtnode/justify.cxx @@ -23,11 +23,11 @@ class SwCoreJustifyTest : public SwModelTestBase class CharWidthArray { public: - std::vector<sal_Int32> maArray; - template <typename... Args> - CharWidthArray(Args&&... args) - : maArray{ std::forward<Args>(args)... } + KernArray maArray; + template <typename... Args> CharWidthArray(Args&&... args) { + for (auto arg : { args... }) + maArray.push_back(arg); } template <typename Function> void InvokeWithKernArray(Function f); void ConvertToKernArray(); @@ -41,7 +41,7 @@ inline bool operator==(const CharWidthArray& lhs, const CharWidthArray& rhs) std::ostream& operator<<(std::ostream& rStrm, const CharWidthArray& rCharWidthArray) { - const std::vector<sal_Int32>& rArray(rCharWidthArray.maArray); + const KernArray& rArray(rCharWidthArray.maArray); sal_Int32 nLen = rArray.size(); rStrm << "{ "; for (sal_Int32 i = 0; i < nLen; ++i) @@ -56,13 +56,13 @@ std::ostream& operator<<(std::ostream& rStrm, const CharWidthArray& rCharWidthAr void CharWidthArray::ConvertToKernArray() { for (std::size_t i = 1; i < maArray.size(); ++i) - maArray[i] += maArray[i - 1]; + maArray.adjust(i, maArray[i - 1]); } void CharWidthArray::ConvertToCharWidths() { for (sal_Int32 i = maArray.size() - 1; i > 0; --i) - maArray[i] -= maArray[i - 1]; + maArray.adjust(i, -maArray[i - 1]); } /// Convert maArray to kern array values, then invoke the function, and convert it back. diff --git a/sw/source/core/inc/scriptinfo.hxx b/sw/source/core/inc/scriptinfo.hxx index 9fdaa9073eb8..21c3c2240cc4 100644 --- a/sw/source/core/inc/scriptinfo.hxx +++ b/sw/source/core/inc/scriptinfo.hxx @@ -272,7 +272,7 @@ public: // HIDDEN TEXT STUFF END // modifies the kerning array according to a given compress value - tools::Long Compress( sal_Int32* pKernArray, TextFrameIndex nIdx, TextFrameIndex nLen, + tools::Long Compress( KernArray& rKernArray, TextFrameIndex nIdx, TextFrameIndex nLen, const sal_uInt16 nCompress, const sal_uInt16 nFontHeight, const bool bCentered, Point* pPoint = nullptr ) const; @@ -291,7 +291,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_Bool* pKashidaArray, + sal_Int32 KashidaJustify( KernArray* pKernArray, sal_Bool* pKashidaArray, TextFrameIndex nStt, TextFrameIndex nLen, tools::Long nSpaceAdd = 0) const; /** Clears array of kashidas marked as invalid @@ -362,7 +362,7 @@ public: The value which has to be added to the cells. @return The number of extra spaces in the given range */ - static TextFrameIndex ThaiJustify( std::u16string_view aText, sal_Int32* pKernArray, + static TextFrameIndex ThaiJustify( std::u16string_view aText, KernArray* pKernArray, TextFrameIndex nIdx, TextFrameIndex nLen, TextFrameIndex nNumberOfBlanks = TextFrameIndex(0), @@ -371,7 +371,7 @@ public: static TextFrameIndex CountCJKCharacters(const OUString &rText, TextFrameIndex nPos, TextFrameIndex nEnd, LanguageType aLang); - static void CJKJustify( const OUString& rText, sal_Int32* pKernArray, + static void CJKJustify( const OUString& rText, KernArray& rKernArray, TextFrameIndex nStt, TextFrameIndex nLen, LanguageType aLang, tools::Long nSpaceAdd, bool bIsSpaceStop ); diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx index 29080e7e785a..8705ac6ecbd1 100644 --- a/sw/source/core/text/porlay.cxx +++ b/sw/source/core/text/porlay.cxx @@ -65,6 +65,7 @@ #include <docsh.hxx> #include <unobookmark.hxx> #include <unocrsrhelper.hxx> +#include <vcl/kernarray.hxx> #include <com/sun/star/rdf/Statement.hpp> #include <com/sun/star/rdf/URI.hpp> #include <com/sun/star/rdf/URIs.hpp> @@ -2195,7 +2196,7 @@ size_t SwScriptInfo::HasKana(TextFrameIndex const nStart, TextFrameIndex const n return SAL_MAX_SIZE; } -tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, TextFrameIndex nLen, +tools::Long SwScriptInfo::Compress(KernArray& rKernArray, TextFrameIndex nIdx, TextFrameIndex nLen, const sal_uInt16 nCompress, const sal_uInt16 nFontHeight, bool bCenter, Point* pPoint ) const @@ -2231,7 +2232,7 @@ tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, T return 0; tools::Long nSub = 0; - tools::Long nLast = nI ? pKernArray[ nI - 1 ] : 0; + tools::Long nLast = nI ? rKernArray[ nI - 1 ] : 0; do { const CompType nType = GetCompType( nCompIdx ); @@ -2243,7 +2244,7 @@ tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, T nCompLen = nLen; // are we allowed to compress the character? - if ( pKernArray[ nI ] - nLast < nMinWidth ) + if ( rKernArray[ nI ] - nLast < nMinWidth ) { nIdx++; nI++; } @@ -2254,7 +2255,7 @@ tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, T SAL_WARN_IF( SwScriptInfo::NONE == nType, "sw.core", "None compression?!" ); // nLast is width of current character - nLast -= pKernArray[ nI ]; + nLast -= rKernArray[ nI ]; nLast *= nCompress; tools::Long nMove = 0; @@ -2277,10 +2278,11 @@ tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, T else nLast /= 100000; nSub -= nLast; - nLast = pKernArray[ nI ]; + nLast = rKernArray[ nI ]; if( nI && nMove ) - pKernArray[ nI - 1 ] += nMove; - pKernArray[ nI++ ] -= nSub; + rKernArray.adjust(nI - 1, nMove); + rKernArray.adjust(nI, -nSub); + ++nI; ++nIdx; } } @@ -2299,8 +2301,9 @@ tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, T while( nIdx < nTmpChg ) { - nLast = pKernArray[ nI ]; - pKernArray[ nI++ ] -= nSub; + nLast = rKernArray[ nI ]; + rKernArray.adjust(nI, -nSub); + ++nI; ++nIdx; } } while( nIdx < nLen ); @@ -2312,7 +2315,7 @@ tools::Long SwScriptInfo::Compress(sal_Int32* pKernArray, TextFrameIndex nIdx, T // total number of kashida positions, or the number of kashida positions after some positions // have been dropped, depending on the state of the m_KashidaInvalid set. -sal_Int32 SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, +sal_Int32 SwScriptInfo::KashidaJustify( KernArray* pKernArray, sal_Bool* pKashidaArray, TextFrameIndex const nStt, TextFrameIndex const nLen, @@ -2387,7 +2390,7 @@ sal_Int32 SwScriptInfo::KashidaJustify( sal_Int32* pKernArray, while ( nArrayPos < nArrayEnd ) { - pKernArray[ sal_Int32(nArrayPos) ] += nKashAdd; + pKernArray->adjust(sal_Int32(nArrayPos), nKashAdd); ++nArrayPos; } nKashAdd += nSpaceAdd; @@ -2574,7 +2577,7 @@ void SwScriptInfo::MarkKashidasInvalid(sal_Int32 const nCnt, } } -TextFrameIndex SwScriptInfo::ThaiJustify( std::u16string_view aText, sal_Int32* pKernArray, +TextFrameIndex SwScriptInfo::ThaiJustify( std::u16string_view aText, KernArray* pKernArray, TextFrameIndex const nStt, TextFrameIndex const nLen, TextFrameIndex nNumberOfBlanks, @@ -2606,7 +2609,8 @@ TextFrameIndex SwScriptInfo::ThaiJustify( std::u16string_view aText, sal_Int32* ++nCnt; } - if ( pKernArray ) pKernArray[ nI ] += nSpaceSum; + if (pKernArray) + pKernArray->adjust(nI, nSpaceSum); } return nCnt; @@ -2901,12 +2905,12 @@ TextFrameIndex SwScriptInfo::CountCJKCharacters(const OUString &rText, return nCount; } -void SwScriptInfo::CJKJustify( const OUString& rText, sal_Int32* pKernArray, +void SwScriptInfo::CJKJustify( const OUString& rText, KernArray& rKernArray, TextFrameIndex const nStt, TextFrameIndex const nLen, LanguageType aLang, tools::Long nSpaceAdd, bool bIsSpaceStop ) { - assert( pKernArray != nullptr && sal_Int32(nStt) >= 0 ); + assert( sal_Int32(nStt) >= 0 ); if (sal_Int32(nLen) <= 0) return; @@ -2924,7 +2928,7 @@ void SwScriptInfo::CJKJustify( const OUString& rText, sal_Int32* pKernArray, if (nNext < sal_Int32(nStt + nLen) || !bIsSpaceStop) nSpaceSum += nSpaceAdd; } - pKernArray[ nI ] += nSpaceSum; + rKernArray.adjust(nI, nSpaceSum); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index 5b26029b36dd..20ed476398d8 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -22,6 +22,7 @@ #include <i18nlangtag/mslangid.hxx> #include <officecfg/Office/Common.hxx> #include <vcl/outdev.hxx> +#include <vcl/kernarray.hxx> #include <vcl/lineinfo.hxx> #include <vcl/metric.hxx> #include <vcl/svapp.hxx> @@ -169,12 +170,12 @@ struct CalcLinePosData const bool bSwitchH2VLRBT; const bool bSwitchL2R; tools::Long nHalfSpace; - sal_Int32* pKernArray; + KernArray& rKernArray; const bool bBidiPor; CalcLinePosData( SwDrawTextInfo& _rInf, vcl::Font& _rFont, TextFrameIndex const _nCnt, const bool _bSwitchH2V, const bool _bSwitchH2VLRBT, const bool _bSwitchL2R, - tools::Long _nHalfSpace, sal_Int32* _pKernArray, const bool _bBidiPor) : + tools::Long _nHalfSpace, KernArray& _rKernArray, const bool _bBidiPor) : rInf( _rInf ), rFont( _rFont ), nCnt( _nCnt ), @@ -182,7 +183,7 @@ struct CalcLinePosData bSwitchH2VLRBT( _bSwitchH2VLRBT ), bSwitchL2R( _bSwitchL2R ), nHalfSpace( _nHalfSpace ), - pKernArray( _pKernArray ), + rKernArray( _rKernArray ), bBidiPor( _bBidiPor ) { } @@ -209,8 +210,8 @@ static void lcl_calcLinePos( const CalcLinePosData &rData, } // determine start, end and length of wave line - sal_Int32 nKernStart = nStart ? rData.pKernArray[sal_Int32(nStart) - 1] : 0; - sal_Int32 nKernEnd = rData.pKernArray[sal_Int32(nEnd) - 1]; + sal_Int32 nKernStart = nStart ? rData.rKernArray[sal_Int32(nStart) - 1] : 0; + sal_Int32 nKernEnd = rData.rKernArray[sal_Int32(nEnd) - 1]; const Degree10 nDir = rData.bBidiPor ? 1800_deg10 : UnMapDirection(rData.rFont.GetOrientation(), @@ -731,7 +732,7 @@ static void lcl_DrawLineForWrongListData( rInf.GetOut().Pop(); } -static void GetTextArray(const OutputDevice& rDevice, const OUString& rStr, std::vector<sal_Int32>& rDXAry, +static void GetTextArray(const OutputDevice& rDevice, const OUString& rStr, KernArray& rDXAry, sal_Int32 nIndex, sal_Int32 nLen, bool bCaret = false, const vcl::text::TextLayoutCache* layoutCache = nullptr) { @@ -740,14 +741,14 @@ static void GetTextArray(const OutputDevice& rDevice, const OUString& rStr, std: rDevice.GetTextArray(rStr, &rDXAry, nIndex, nLen, bCaret, layoutCache, pLayoutCache); } -static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry, +static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, KernArray& rDXAry, bool bCaret = false) { return GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), rInf.GetLen().get(), bCaret, rInf.GetVclCache()); } -static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry, +static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, KernArray& rDXAry, sal_Int32 nLen, bool bCaret = false) { // Substring is fine. @@ -928,7 +929,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) tools::Long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR; // kerning array - gives the absolute position of end of each character - std::vector<sal_Int32> aKernArray; + KernArray aKernArray; if ( m_pPrinter ) GetTextArray(*m_pPrinter, rInf, aKernArray); @@ -982,7 +983,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) // Simple kerning is handled by DrawStretchText if( rInf.GetSpace() || rInf.GetKanaComp() ) { - std::vector<sal_Int32> aKernArray; + KernArray aKernArray; GetTextArray(rInf.GetOut(), rInf, aKernArray); std::vector<sal_Bool> aKashidaArray; @@ -1007,7 +1008,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) tools::Long nSum = nDiff; for( sal_Int32 i = 0; i < nZwi; ) { - aKernArray[ i ] += nSum; + aKernArray.adjust(i, nSum); if( ++i == nRest ) nDiff += nAdd; nSum += nDiff; @@ -1029,7 +1030,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) pSI && pSI->CountCompChg() && lcl_IsMonoSpaceFont( rInf.GetOut() ) ) { - pSI->Compress( aKernArray.data(), rInf.GetIdx(), rInf.GetLen(), + pSI->Compress( aKernArray, rInf.GetIdx(), rInf.GetLen(), rInf.GetKanaComp(), o3tl::narrowing<sal_uInt16>(m_aFont.GetFontSize().Height()), lcl_IsFullstopCentered( rInf.GetOut() ), &aTextOriginPos ); bSpecialJust = true; @@ -1042,7 +1043,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) if (!MsLangId::isKorean(aLang)) { - SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), + SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray, rInf.GetIdx(), rInf.GetLen(), aLang, nSpaceAdd, rInf.IsSpaceStop() ); bSpecialJust = true; @@ -1057,7 +1058,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) { aKashidaArray.resize(aKernArray.size(), false); if ( pSI && pSI->CountKashida() && - pSI->KashidaJustify( aKernArray.data(), aKashidaArray.data(), rInf.GetIdx(), + pSI->KashidaJustify( &aKernArray, aKashidaArray.data(), rInf.GetIdx(), rInf.GetLen(), nSpaceAdd ) != -1 ) { bSpecialJust = true; @@ -1077,7 +1078,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) { // Use rInf.GetSpace() because it has more precision than // nSpaceAdd: - SwScriptInfo::ThaiJustify( rInf.GetText(), aKernArray.data(), + SwScriptInfo::ThaiJustify( rInf.GetText(), &aKernArray, rInf.GetIdx(), rInf.GetLen(), rInf.GetNumberOfBlanks(), rInf.GetSpace() ); @@ -1098,7 +1099,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) { if (CH_BLANK == rInf.GetText()[sal_Int32(rInf.GetIdx()) + i]) nKernSum += nSpaceAdd; - aKernArray[i] += nKernSum; + aKernArray.adjust(i, nKernSum); } // In case of underlined/strike-through justified text @@ -1109,14 +1110,15 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) // If it is a single underlined space, output 2 spaces: if (TextFrameIndex(1) == rInf.GetLen()) { - aKernArray[0] = rInf.GetWidth() + nSpaceAdd; + aKernArray.set(0, rInf.GetWidth() + nSpaceAdd); rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(), aKernArray, aKashidaArray, sal_Int32(rInf.GetIdx()), 1 ); } else { - aKernArray[ sal_Int32(rInf.GetLen()) - 2 ] += nSpaceAdd; + sal_Int32 nIndex(sal_Int32(rInf.GetLen()) - 2); + aKernArray.adjust(nIndex, nSpaceAdd); rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(), aKernArray, aKashidaArray, sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); } @@ -1190,9 +1192,10 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) bool bBullet = rInf.GetBullet(); if( m_bSymbol ) bBullet = false; - std::vector<sal_Int32> aKernArray; CreateScrFont( *rInf.GetShell(), rInf.GetOut() ); + VclPtr<OutputDevice> xFormattingDevice; + // OLE: no printer available // OSL_ENSURE( pPrinter, "DrawText needs pPrinter" ) if ( m_pPrinter ) @@ -1203,12 +1206,27 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) ) m_pPrinter->SetFont( *m_pPrtFont ); } - GetTextArray(*m_pPrinter, rInf, aKernArray); + xFormattingDevice = m_pPrinter; } else { - GetTextArray(rInf.GetOut(), rInf, aKernArray); + xFormattingDevice = &rInf.GetOut(); + } + + //tdf#152094 see if we can retain a subpixel factor + int nSubPixels = 1; + MapMode aMapMode(xFormattingDevice->GetMapMode()); + if (aMapMode.IsSimple() && aMapMode.GetMapUnit() == MapUnit::MapTwip) + { + if (xFormattingDevice->GetDPIX() == xFormattingDevice->GetDPIY()) + { + int nRatio = xFormattingDevice->GetDPIX() / 1440; + if (nRatio * 1440 == xFormattingDevice->GetDPIX()) + nSubPixels = nRatio; + } } + KernArray aKernArray(nSubPixels); + GetTextArray(*xFormattingDevice, rInf, aKernArray); std::vector<sal_Bool> aKashidaArray; @@ -1227,7 +1245,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) pSI && pSI->CountCompChg() && lcl_IsMonoSpaceFont( rInf.GetOut() ) ) { - pSI->Compress( aKernArray.data(), rInf.GetIdx(), rInf.GetLen(), + pSI->Compress( aKernArray, rInf.GetIdx(), rInf.GetLen(), rInf.GetKanaComp(), o3tl::narrowing<sal_uInt16>(m_aFont.GetFontSize().Height()), lcl_IsFullstopCentered( rInf.GetOut() ), &aTextOriginPos ); } @@ -1239,7 +1257,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) if (!MsLangId::isKorean(aLang)) { - SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), + SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray, rInf.GetIdx(), rInf.GetLen(), aLang, nSpaceAdd, rInf.IsSpaceStop() ); nSpaceAdd = 0; @@ -1253,7 +1271,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) { aKashidaArray.resize(aKernArray.size(), false); if ( pSI && pSI->CountKashida() && - pSI->KashidaJustify( aKernArray.data(), aKashidaArray.data(), rInf.GetIdx(), + pSI->KashidaJustify( &aKernArray, aKashidaArray.data(), rInf.GetIdx(), rInf.GetLen(), nSpaceAdd ) != -1 ) nSpaceAdd = 0; else @@ -1271,7 +1289,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) if ( LANGUAGE_THAI == aLang ) { - SwScriptInfo::ThaiJustify( rInf.GetText(), aKernArray.data(), + SwScriptInfo::ThaiJustify( rInf.GetText(), &aKernArray, rInf.GetIdx(), rInf.GetLen(), rInf.GetNumberOfBlanks(), @@ -1326,9 +1344,9 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) // have to output 2 spaces: if ((nCnt == TextFrameIndex(1)) && rInf.GetSpace() && (cChPrev == CH_BLANK)) { - aKernArray[0] = rInf.GetWidth() + + aKernArray.set(0, rInf.GetWidth() + rInf.GetKern() + - ( rInf.GetSpace() / SPACING_PRECISION_FACTOR ); + (rInf.GetSpace() / SPACING_PRECISION_FACTOR)); if ( bSwitchL2R ) rInf.GetFrame()->SwitchLTRtoRTL( aTextOriginPos ); @@ -1427,7 +1445,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) const tools::Long nHalfSpace = bNoHalfSpace ? 0 : nSpaceAdd / 2; CalcLinePosData aCalcLinePosData(rInf, GetFont(), nCnt, bSwitchH2V, bSwitchH2VLRBT, bSwitchL2R, nHalfSpace, - aKernArray.data(), bBidiPor); + aKernArray, bBidiPor); SwForbidden aForbidden; // draw line for smart tag data @@ -1488,9 +1506,9 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) for( sal_Int32 i = 1 ; i < nLen ; ++i ) { if ( aBulletOverlay[ i ] == CH_BULLET ) - aKernArray [ i - 1 ] += nShift ; + aKernArray.adjust(i - 1, nShift); if ( nAdd ) - aKernArray [ i - 1 ] -= nAdd; + aKernArray.adjust(i - 1, -nAdd); } } rInf.GetOut().DrawTextArray( aTextOriginPos, aBulletOverlay, aKernArray, @@ -1559,7 +1577,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) aTextSize.setHeight( pOutDev->GetTextHeight() + GetFontLeading( rInf.GetShell(), rInf.GetOut() ) ); - std::vector<sal_Int32> aKernArray; + KernArray aKernArray; GetTextArray(*pOutDev, rInf, aKernArray, sal_Int32(nLn), bCaret); if (pGrid->IsSnapToChars()) { @@ -1591,7 +1609,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) // This is the part used e.g., for cursor travelling // See condition for DrawText or DrawTextArray (bDirectPrint) - std::vector<sal_Int32> aKernArray; + KernArray aKernArray; if ( m_pPrinter && m_pPrinter.get() != rInf.GetpOut() ) { if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) ) @@ -1616,7 +1634,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) if (bCompress) { - rInf.SetKanaDiff(rInf.GetScriptInfo()->Compress(aKernArray.data(), rInf.GetIdx(), nLn, rInf.GetKanaComp(), + rInf.SetKanaDiff(rInf.GetScriptInfo()->Compress(aKernArray, rInf.GetIdx(), nLn, rInf.GetKanaComp(), o3tl::narrowing<sal_uInt16>(m_aFont.GetFontSize().Height()), lcl_IsFullstopCentered(rInf.GetOut()))); } else @@ -1660,7 +1678,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) if( 0 != nCharacterSpacing ) nKern -= nCharacterSpacing; - std::vector<sal_Int32> aKernArray; + KernArray aKernArray; // be sure to have the correct layout mode at the printer if ( m_pPrinter ) @@ -1709,7 +1727,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) pSI && pSI->CountCompChg() && lcl_IsMonoSpaceFont( rInf.GetOut() ) ) { - pSI->Compress( aKernArray.data(), rInf.GetIdx(), rInf.GetLen(), + pSI->Compress( aKernArray, rInf.GetIdx(), rInf.GetLen(), rInf.GetKanaComp(), o3tl::narrowing<sal_uInt16>(m_aFont.GetFontSize().Height()), lcl_IsFullstopCentered( rInf.GetOut() ) ); @@ -1722,7 +1740,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) if (!MsLangId::isKorean(aLang)) { - SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray.data(), + SwScriptInfo::CJKJustify( rInf.GetText(), aKernArray, rInf.GetIdx(), rInf.GetLen(), aLang, nSpaceAdd, rInf.IsSpaceStop() ); nSpaceAdd = 0; @@ -1736,7 +1754,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) ) { if ( pSI && pSI->CountKashida() && - pSI->KashidaJustify( aKernArray.data(), nullptr, rInf.GetIdx(), rInf.GetLen(), + pSI->KashidaJustify( &aKernArray, nullptr, rInf.GetIdx(), rInf.GetLen(), nSpaceAdd ) != -1 ) nSpaceAdd = 0; } @@ -1749,7 +1767,7 @@ TextFrameIndex SwFntObj::GetModelPositionForViewPoint(SwDrawTextInfo &rInf) if ( LANGUAGE_THAI == aLang ) { - SwScriptInfo::ThaiJustify( rInf.GetText(), aKernArray.data(), + SwScriptInfo::ThaiJustify( rInf.GetText(), &aKernArray, rInf.GetIdx(), rInf.GetLen(), rInf.GetNumberOfBlanks(), rInf.GetSpace() ); @@ -1956,7 +1974,7 @@ TextFrameIndex SwFont::GetTextBreak(SwDrawTextInfo const & rInf, tools::Long nTe const SwDoc* pDoc = rInf.GetShell()->GetDoc(); const sal_uInt16 nGridWidth = GetGridWidth(*pGrid, *pDoc); - std::vector<sal_Int32> aKernArray; + KernArray aKernArray; GetTextArray( rInf.GetOut(), rInf.GetText(), aKernArray, sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); @@ -2084,10 +2102,10 @@ TextFrameIndex SwFont::GetTextBreak(SwDrawTextInfo const & rInf, tools::Long nTe nLn = TextFrameIndex(1); else if (nLn > nTextBreak2 + nTextBreak2) nLn = nTextBreak2 + nTextBreak2; - std::vector<sal_Int32> aKernArray; + KernArray aKernArray; GetTextArray( rInf.GetOut(), rInf.GetText(), aKernArray, sal_Int32(rInf.GetIdx()), sal_Int32(nLn)); - if( rInf.GetScriptInfo()->Compress( aKernArray.data(), rInf.GetIdx(), nLn, + if( rInf.GetScriptInfo()->Compress( aKernArray, rInf.GetIdx(), nLn, rInf.GetKanaComp(), o3tl::narrowing<sal_uInt16>(GetHeight( m_nActual )), lcl_IsFullstopCentered( rInf.GetOut() ) ) ) { diff --git a/sw/source/core/txtnode/justify.cxx b/sw/source/core/txtnode/justify.cxx index b59c5d8787b9..40ded5663f17 100644 --- a/sw/source/core/txtnode/justify.cxx +++ b/sw/source/core/txtnode/justify.cxx @@ -9,6 +9,7 @@ #include <vector> #include <sal/types.h> +#include <vcl/kernarray.hxx> #include <swfont.hxx> #include "justify.hxx" @@ -73,7 +74,7 @@ tools::Long lcl_OffsetFromGridEdge(tools::Long nMinWidth, tools::Long nCharWidth namespace sw::Justify { -sal_Int32 GetModelPosition(const std::vector<sal_Int32>& rKernArray, sal_Int32 nLen, tools::Long nX) +sal_Int32 GetModelPosition(const KernArray& rKernArray, sal_Int32 nLen, tools::Long nX) { tools::Long nLeft = 0, nRight = 0; sal_Int32 nLast = 0, nIdx = 0; @@ -97,9 +98,8 @@ sal_Int32 GetModelPosition(const std::vector<sal_Int32>& rKernArray, sal_Int32 n return nIdx; } -void SpaceDistribution(std::vector<sal_Int32>& rKernArray, std::u16string_view aText, - sal_Int32 nStt, sal_Int32 nLen, tools::Long nSpaceAdd, tools::Long nKern, - bool bNoHalfSpace) +void SpaceDistribution(KernArray& rKernArray, std::u16string_view aText, sal_Int32 nStt, + sal_Int32 nLen, tools::Long nSpaceAdd, tools::Long nKern, bool bNoHalfSpace) { assert(nStt + nLen <= sal_Int32(aText.size())); assert(nLen <= sal_Int32(rKernArray.size())); @@ -152,26 +152,29 @@ void SpaceDistribution(std::vector<sal_Int32>& rKernArray, std::u16string_view a } cChPrev = nCh; - rKernArray[nPrevIdx] += nKernSum + nSpaceSum; + rKernArray.adjust(nPrevIdx, nKernSum + nSpaceSum); // In word line mode and for Arabic, we disabled the half space trick. If a portion // ends with a blank, the full nSpaceAdd value has been added to the character in // front of the blank. This leads to painting artifacts, therefore we remove the // nSpaceAdd value again: if (bNoHalfSpace && i + 1 == nLen && nCh == CH_BLANK) - rKernArray[nPrevIdx] = rKernArray[nPrevIdx] - nSpaceAdd; + rKernArray.adjust(nPrevIdx, -nSpaceAdd); // Advance nPrevIdx and assign kern values to previous cluster. for (tools::Long nValue = rKernArray[nPrevIdx++]; nPrevIdx < i; ++nPrevIdx) - rKernArray[nPrevIdx] = nValue; + rKernArray.set(nPrevIdx, nValue); } // the layout engine requires the total width of the output while (nPrevIdx < nLen) - rKernArray[nPrevIdx++] += nKernSum + nSpaceSum; + { + rKernArray.adjust(nPrevIdx, nKernSum + nSpaceSum); + ++nPrevIdx; + } } -tools::Long SnapToGrid(std::vector<sal_Int32>& rKernArray, std::u16string_view aText, - sal_Int32 nStt, sal_Int32 nLen, tools::Long nGridWidth, bool bForceLeft) +tools::Long SnapToGrid(KernArray& rKernArray, std::u16string_view aText, sal_Int32 nStt, + sal_Int32 nLen, tools::Long nGridWidth, bool bForceLeft) { assert(nStt + nLen <= sal_Int32(aText.size())); assert(nLen <= sal_Int32(rKernArray.size())); @@ -195,16 +198,22 @@ tools::Long SnapToGrid(std::vector<sal_Int32>& rKernArray, std::u16string_view a nEdge += nMinWidth; while (nLast < i) - rKernArray[nLast++] = nX; + { + rKernArray.set(nLast, nX); + ++nLast; + } } while (nLast < nLen) - rKernArray[nLast++] = nEdge; + { + rKernArray.set(nLast, nEdge); + ++nLast; + } return nDelta; } -void SnapToGridEdge(std::vector<sal_Int32>& rKernArray, sal_Int32 nLen, tools::Long nGridWidth, +void SnapToGridEdge(KernArray& rKernArray, sal_Int32 nLen, tools::Long nGridWidth, tools::Long nSpace, tools::Long nKern) { assert(nLen <= sal_Int32(rKernArray.size())); @@ -222,13 +231,19 @@ void SnapToGridEdge(std::vector<sal_Int32>& rKernArray, sal_Int32 nLen, tools::L nCharWidth = rKernArray[i] - rKernArray[nLast]; tools::Long nMinWidth = lcl_MinGridWidth(nGridWidth, nCharWidth + nKern); while (nLast < i) - rKernArray[nLast++] = nEdge; + { + rKernArray.set(nLast, nEdge); + ++nLast; + } nEdge += nMinWidth + nSpace; } while (nLast < nLen) - rKernArray[nLast++] = nEdge; + { + rKernArray.set(nLast, nEdge); + ++nLast; + } } } diff --git a/sw/source/core/txtnode/justify.hxx b/sw/source/core/txtnode/justify.hxx index 9a7ff5f126ab..454b6c259001 100644 --- a/sw/source/core/txtnode/justify.hxx +++ b/sw/source/core/txtnode/justify.hxx @@ -16,7 +16,7 @@ namespace sw::Justify /// @param rKernArray text positions from OutDev::GetTextArray(). /// @param nLen number of elements to process in rKernArray. /// @param nX the visual position -SW_DLLPUBLIC sal_Int32 GetModelPosition(const std::vector<sal_Int32>& rKernArray, sal_Int32 nLen, +SW_DLLPUBLIC sal_Int32 GetModelPosition(const KernArray& rKernArray, sal_Int32 nLen, tools::Long nX); /// Distribute space between words and letters. /// @param[in,out] rKernArray text positions from OutDev::GetTextArray(). @@ -28,7 +28,7 @@ SW_DLLPUBLIC sal_Int32 GetModelPosition(const std::vector<sal_Int32>& rKernArray /// @param bNoHalfSpace whether to split the space into two halves. /// Split spaces are inserted before and after CH_BLANK. /// Set to true in word line mode and for Arabic text to avoid splitting. -SW_DLLPUBLIC void SpaceDistribution(std::vector<sal_Int32>& rKernArray, std::u16string_view aText, +SW_DLLPUBLIC void SpaceDistribution(KernArray& rKernArray, std::u16string_view aText, sal_Int32 nStt, sal_Int32 nLen, tools::Long nSpaceAdd, tools::Long nKern, bool bNoHalfSpace); @@ -47,7 +47,7 @@ SW_DLLPUBLIC void SpaceDistribution(std::vector<sal_Int32>& rKernArray, std::u16 /// @param bForceLeft for align to the left edge of the grid disregard of the punctuation type. /// This is useful for calculate text width, line break, and conversion model position. /// @return the delta offset of first glyph so text origin can be updated accordingly. -SW_DLLPUBLIC tools::Long SnapToGrid(std::vector<sal_Int32>& rKernArray, std::u16string_view aText, +SW_DLLPUBLIC tools::Long SnapToGrid(KernArray& rKernArray, std::u16string_view aText, sal_Int32 nStt, sal_Int32 nLen, tools::Long nGridWidth, bool bForceLeft); @@ -58,8 +58,8 @@ SW_DLLPUBLIC tools::Long SnapToGrid(std::vector<sal_Int32>& rKernArray, std::u16 /// @param nGridWidth width of a text grid /// @param nSpace amount of space distributed under justify text alignment mode. /// @param nKern letter spacing. -SW_DLLPUBLIC void SnapToGridEdge(std::vector<sal_Int32>& rKernArray, sal_Int32 nLen, - tools::Long nGridWidth, tools::Long nSpace, tools::Long nKern); +SW_DLLPUBLIC void SnapToGridEdge(KernArray& rKernArray, sal_Int32 nLen, tools::Long nGridWidth, + tools::Long nSpace, tools::Long nKern); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/toolkit/source/awt/vclxfont.cxx b/toolkit/source/awt/vclxfont.cxx index e84fe338c5b6..866a362e710f 100644 --- a/toolkit/source/awt/vclxfont.cxx +++ b/toolkit/source/awt/vclxfont.cxx @@ -25,12 +25,11 @@ #include <toolkit/awt/vclxfont.hxx> #include <toolkit/helper/vclunohelper.hxx> +#include <vcl/kernarray.hxx> #include <vcl/metric.hxx> #include <vcl/outdev.hxx> #include <vcl/svapp.hxx> - - VCLXFont::VCLXFont() { mpFontMetric = nullptr; @@ -156,10 +155,12 @@ sal_Int32 VCLXFont::getStringWidthArray( const OUString& str, css::uno::Sequence { vcl::Font aOldFont = pOutDev->GetFont(); pOutDev->SetFont( maFont ); - std::vector<sal_Int32> aDXA; + KernArray aDXA; nRet = pOutDev->GetTextArray( str, &aDXA ); - // I don't know if size of aDXA is guaranteed same as length of str, so use arrayToSequence - rDXArray = comphelper::arrayToSequence<sal_Int32>(aDXA.data(), str.getLength()); + rDXArray.realloc(aDXA.size()); + sal_Int32* pArray = rDXArray.getArray(); + for (size_t i = 0, nLen = aDXA.size(); i < nLen; ++i) + pArray[i] = aDXA[i]; pOutDev->SetFont( aOldFont ); } return nRet; diff --git a/toolkit/source/awt/vclxgraphics.cxx b/toolkit/source/awt/vclxgraphics.cxx index 673c44eb09f2..3707f573b064 100644 --- a/toolkit/source/awt/vclxgraphics.cxx +++ b/toolkit/source/awt/vclxgraphics.cxx @@ -26,6 +26,7 @@ #include <vcl/svapp.hxx> #include <vcl/outdev.hxx> #include <vcl/image.hxx> +#include <vcl/kernarray.hxx> #include <vcl/gradient.hxx> #include <vcl/metric.hxx> #include <tools/debug.hxx> @@ -463,12 +464,11 @@ void VCLXGraphics::drawTextArray( sal_Int32 x, sal_Int32 y, const OUString& rTex if( mpOutputDevice ) { InitOutputDevice( InitOutDevFlags::COLORS|InitOutDevFlags::FONT ); - std::vector<sal_Int32> aDXA(rText.getLength()); - for(int i = 0; i < rText.getLength(); i++) - { - aDXA[i] = rLongs[i]; - } - mpOutputDevice->DrawTextArray( Point( x, y ), rText, aDXA , {}, 0, rText.getLength()); + KernArray aDXA; + aDXA.reserve(rText.getLength()); + for(int i = 0; i < rText.getLength(); ++i) + aDXA.push_back(rLongs[i]); + mpOutputDevice->DrawTextArray( Point( x, y ), rText, aDXA, {}, 0, rText.getLength()); } } diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx index 6f68478f2f61..e8ce5163177f 100644 --- a/vcl/inc/pdf/pdfwriter_impl.hxx +++ b/vcl/inc/pdf/pdfwriter_impl.hxx @@ -1230,7 +1230,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, o3tl::span<const sal_Bool> pKashidaArray, sal_Int32 nIndex, sal_Int32 nLen ); + void drawTextArray( const Point& rPos, const OUString& rText, KernArraySpan 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/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx index 92f537b1b73a..1e82a70e9546 100644 --- a/vcl/qa/cppunit/complextext.cxx +++ b/vcl/qa/cppunit/complextext.cxx @@ -78,10 +78,10 @@ void VclComplexTextTest::testArabic() // absolute character widths AKA text array. std::vector<sal_Int32> aRefCharWidths {6, 9, 16, 16, 22, 22, 26, 29, 32, 32, 36, 40, 49, 53, 56, 63, 63, 66, 72, 72}; - std::vector<sal_Int32> aCharWidths(aOneTwoThree.getLength(), 0); + KernArray aCharWidths; tools::Long nTextWidth = pOutDev->GetTextArray(aOneTwoThree, &aCharWidths); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); // this sporadically returns 75 or 74 on some of the windows tinderboxes eg. tb73 CPPUNIT_ASSERT_EQUAL(tools::Long(72), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); @@ -246,7 +246,8 @@ void VclComplexTextTest::testCaret() pOutDev->SetFont( aFont ); OUString aText; - std::vector<sal_Int32> aCharWidths, aRefCharWidths; + KernArray aCharWidths; + std::vector<sal_Int32> aRefCharWidths; tools::Long nTextWidth, nTextWidth2; // A. RTL text @@ -255,20 +256,16 @@ void VclComplexTextTest::testCaret() // 1) Regular DX array, the ligature width is given to the first components // and the next ones are all zero width. aRefCharWidths = { 114, 114, 178, 234, 353, 353 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/false); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(353), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); // 2) Caret placement DX array, ligature width is distributed over its // components. aRefCharWidths = { 57, 114, 178, 234, 293, 353 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(353), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); @@ -276,14 +273,12 @@ void VclComplexTextTest::testCaret() // component count. aText = u"لَاَ بلَاَ"; aRefCharWidths = { 57, 57, 114, 114, 178, 234, 293, 293, 353, 353 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth2 = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true); CPPUNIT_ASSERT_EQUAL(aCharWidths[0], aCharWidths[1]); CPPUNIT_ASSERT_EQUAL(aCharWidths[2], aCharWidths[3]); CPPUNIT_ASSERT_EQUAL(aCharWidths[6], aCharWidths[7]); CPPUNIT_ASSERT_EQUAL(aCharWidths[8], aCharWidths[9]); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(353), nTextWidth2); CPPUNIT_ASSERT_EQUAL(nTextWidth, nTextWidth2); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); @@ -294,20 +289,16 @@ void VclComplexTextTest::testCaret() // 1) Regular DX array, the ligature width is given to the first components // and the next ones are all zero width. aRefCharWidths = { 126, 126, 190, 316, 316, 380, 573, 573, 573, 637, 830, 830, 830 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/false); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(830), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); // 2) Caret placement DX array, ligature width is distributed over its // components. aRefCharWidths = { 63, 126, 190, 253, 316, 380, 444, 508, 573, 637, 701, 765, 830 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(830), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); #endif @@ -322,7 +313,8 @@ void VclComplexTextTest::testGdefCaret() vcl::Font aFont; OUString aText; - std::vector<sal_Int32> aCharWidths, aRefCharWidths; + KernArray aCharWidths; + std::vector<sal_Int32> aRefCharWidths; tools::Long nTextWidth, nTextWidth2; // A. RTL text @@ -333,21 +325,17 @@ void VclComplexTextTest::testGdefCaret() // 1) Regular DX array, the ligature width is given to the first components // and the next ones are all zero width. - aRefCharWidths = { 104, 104, 148, 203, 325, 325 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); + aRefCharWidths= { 104, 104, 148, 203, 325, 325 }; nTextWidth = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/false); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(325), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); // 2) Caret placement DX array, ligature width is distributed over its // components. aRefCharWidths = { 53, 104, 148, 203, 265, 325 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(325), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); @@ -355,14 +343,12 @@ void VclComplexTextTest::testGdefCaret() // component count. aText = u"لَاَ بلَاَ"; aRefCharWidths = { 53, 53, 104, 104, 148, 203, 265, 265, 325, 325 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth2 = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true); CPPUNIT_ASSERT_EQUAL(aCharWidths[0], aCharWidths[1]); CPPUNIT_ASSERT_EQUAL(aCharWidths[2], aCharWidths[3]); CPPUNIT_ASSERT_EQUAL(aCharWidths[6], aCharWidths[7]); CPPUNIT_ASSERT_EQUAL(aCharWidths[8], aCharWidths[9]); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(325), nTextWidth2); CPPUNIT_ASSERT_EQUAL(nTextWidth, nTextWidth2); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); @@ -377,10 +363,8 @@ void VclComplexTextTest::testGdefCaret() // and the next ones are all zero width. aRefCharWidths = { 104, 104, 162, 321, 321, 321, 379, 487, 487, 545, 708, 708, 708, 766, 926, 926, 984, 1198, 1198, 1198 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/false); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(1198), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); @@ -388,10 +372,8 @@ void VclComplexTextTest::testGdefCaret() // components. aRefCharWidths = { 53, 104, 162, 215, 269, 321, 379, 433, 487, 545, 599, 654, 708, 766, 826, 926, 984, 1038, 1097, 1198 }; - aCharWidths.resize(aText.getLength()); - std::fill(aCharWidths.begin(), aCharWidths.end(), 0); nTextWidth = pOutDev->GetTextArray(aText, &aCharWidths, 0, -1, /*bCaret*/true); - CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths); + CPPUNIT_ASSERT_EQUAL(aRefCharWidths, aCharWidths.get_subunit_array()); CPPUNIT_ASSERT_EQUAL(tools::Long(1198), nTextWidth); CPPUNIT_ASSERT_EQUAL(sal_Int32(nTextWidth), aCharWidths.back()); #endif diff --git a/vcl/qa/cppunit/svm/svmtest.cxx b/vcl/qa/cppunit/svm/svmtest.cxx index abc4414c1566..3c92ea3d7d7f 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", KernArraySpan(aDX), {}, 1, 4); checkTextArray(writeAndReadStream(aGDIMetaFile)); checkTextArray(readFile(u"textarray.svm")); diff --git a/vcl/source/control/calendar.cxx b/vcl/source/control/calendar.cxx index 44d6fc56ab70..421e159eee81 100644 --- a/vcl/source/control/calendar.cxx +++ b/vcl/source/control/calendar.cxx @@ -20,6 +20,7 @@ #include <vcl/builder.hxx> #include <vcl/svapp.hxx> #include <vcl/help.hxx> +#include <vcl/kernarray.hxx> #include <vcl/menu.hxx> #include <vcl/settings.hxx> #include <vcl/event.hxx> @@ -707,7 +708,7 @@ void Calendar::ImplDraw(vcl::RenderContext& rRenderContext) rRenderContext.SetLineColor(rStyleSettings.GetWindowTextColor()); Point aStartPos(nDayX, nDeltaY); rRenderContext.DrawLine(aStartPos, Point(nDayX + (7 * mnDayWidth), nDeltaY)); - std::vector<sal_Int32> aTmp; + KernArray aTmp; for (int k=0; k<7; ++k) aTmp.push_back(mnDayOfWeekAry[k+1]); rRenderContext.DrawTextArray(Point(nDayX + mnDayOfWeekAry[0], nDayY), maDayOfWeekText, aTmp, {}, 0, aTmp.size()); diff --git a/vcl/source/filter/eps/eps.cxx b/vcl/source/filter/eps/eps.cxx index 797d6b887efc..9da4f666b238 100644 --- a/vcl/source/filter/eps/eps.cxx +++ b/vcl/source/filter/eps/eps.cxx @@ -201,10 +201,10 @@ 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, o3tl::span<const sal_Bool> pKashidaArry, sal_Int32 nWidth, VirtualDevice const & rVDev ); + void ImplText( const OUString& rUniString, const Point& rPos, KernArraySpan 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 ); + void ImplWriteString( const OString&, VirtualDevice const & rVDev, KernArraySpan pDXArry, bool bStretch ); void ImplDefineFont( const char*, const char* ); void ImplClosePathDraw(); @@ -1958,7 +1958,7 @@ void PSWriter::ImplWriteCharacter( char nChar ) ImplWriteByte( static_cast<sal_uInt8>(nChar), PS_NONE ); } -void PSWriter::ImplWriteString( const OString& rString, VirtualDevice const & rVDev, o3tl::span<const sal_Int32> pDXArry, bool bStretch ) +void PSWriter::ImplWriteString( const OString& rString, VirtualDevice const & rVDev, KernArraySpan pDXArry, bool bStretch ) { sal_Int32 nLen = rString.getLength(); if ( !nLen ) @@ -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, o3tl::span<const sal_Bool> pKashidaArry, sal_Int32 nWidth, VirtualDevice const & rVDev ) +void PSWriter::ImplText( const OUString& rUniString, const Point& rPos, KernArraySpan pDXArry, o3tl::span<const sal_Bool> pKashidaArry, sal_Int32 nWidth, VirtualDevice const & rVDev ) { if ( rUniString.isEmpty() ) return; @@ -2036,7 +2036,7 @@ void PSWriter::ImplText( const OUString& rUniString, const Point& rPos, o3tl::sp else if ( ( mnTextMode == 1 ) || ( mnTextMode == 2 ) ) // normal text output { if ( mnTextMode == 2 ) // forcing output one complete text packet, by - pDXArry = {}; // ignoring the kerning array + pDXArry = {}; // ignoring the kerning array ImplSetAttrForText( rPos ); OString aStr(OUStringToOString(rUniString, maFont.GetCharSet())); diff --git a/vcl/source/filter/svm/SvmConverter.cxx b/vcl/source/filter/svm/SvmConverter.cxx index 0729a41c767e..60fa48f2927d 100644 --- a/vcl/source/filter/svm/SvmConverter.cxx +++ b/vcl/source/filter/svm/SvmConverter.cxx @@ -251,7 +251,7 @@ namespace } void ClampRange(std::u16string_view rStr, sal_Int32& rIndex, sal_Int32& rLength, - std::vector<sal_Int32>* pDXAry = nullptr) + KernArray* pDXAry = nullptr) { const sal_Int32 nStrLength = rStr.size(); @@ -738,7 +738,7 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf ) OUString aStr(OStringToOUString(aByteStr, eActualCharSet)); - std::vector<sal_Int32> aDXAry; + KernArray aDXAry; if (nAryLen > 0) { const size_t nMinRecordSize = sizeof(sal_Int32); @@ -770,7 +770,7 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf ) for (sal_Int32 j = 0; j < nAryLen; ++j) { rIStm.ReadInt32( nTmp ); - aDXAry[ j ] = nTmp; + aDXAry.set(j, nTmp); } // #106172# Add last DX array elem, if missing @@ -778,7 +778,7 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf ) { if (nAryLen+1 == nStrLen && nIndex >= 0) { - std::vector<sal_Int32> aTmpAry; + KernArray aTmpAry; aFontVDev->GetTextArray( aStr, &aTmpAry, nIndex, nLen ); @@ -794,9 +794,9 @@ void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf ) // difference to last elem and store // in very last. if( nStrLen > 1 ) - aDXAry[ nStrLen-1 ] = aDXAry[ nStrLen-2 ] + aTmpAry[ nStrLen-1 ] - aTmpAry[ nStrLen-2 ]; + aDXAry.set(nStrLen-1, aDXAry[ nStrLen-2 ] + aTmpAry[ nStrLen-1 ] - aTmpAry[ nStrLen-2 ]); else - aDXAry[ nStrLen-1 ] = aTmpAry[ nStrLen-1 ]; // len=1: 0th position taken to be 0 + aDXAry.set(nStrLen-1, aTmpAry[ nStrLen-1 ]); // len=1: 0th position taken to be 0 } } #ifdef DBG_UTIL diff --git a/vcl/source/filter/svm/SvmReader.cxx b/vcl/source/filter/svm/SvmReader.cxx index 253f89e91d79..e2b6e87c0ce0 100644 --- a/vcl/source/filter/svm/SvmReader.cxx +++ b/vcl/source/filter/svm/SvmReader.cxx @@ -631,7 +631,7 @@ rtl::Reference<MetaAction> SvmReader::TextArrayHandler(const ImplMetaReadData* p { rtl::Reference<MetaTextArrayAction> pAction(new MetaTextArrayAction); - std::vector<sal_Int32> aArray; + KernArray aArray; VersionCompatRead aCompat(mrStream); TypeSerializer aSerializer(mrStream); @@ -670,17 +670,16 @@ rtl::Reference<MetaAction> SvmReader::TextArrayHandler(const ImplMetaReadData* p { try { - aArray.resize(nTmpLen); sal_Int32 i; sal_Int32 val(0); for (i = 0; i < nAryLen; i++) { mrStream.ReadInt32(val); - aArray[i] = val; + aArray.push_back(val); } // #106172# setup remainder for (; i < nTmpLen; i++) - aArray[i] = 0; + aArray.push_back(0); } catch (std::bad_alloc&) { diff --git a/vcl/source/filter/svm/SvmWriter.cxx b/vcl/source/filter/svm/SvmWriter.cxx index e79df6a756bd..c1913b048b27 100644 --- a/vcl/source/filter/svm/SvmWriter.cxx +++ b/vcl/source/filter/svm/SvmWriter.cxx @@ -984,7 +984,7 @@ void SvmWriter::TextArrayHandler(const MetaTextArrayAction* pAction, const ImplM { mrStream.WriteUInt16(static_cast<sal_uInt16>(pAction->GetType())); - const std::vector<sal_Int32>& rDXArray = pAction->GetDXArray(); + const KernArray& rDXArray = pAction->GetDXArray(); const sal_Int32 nAryLen = !rDXArray.empty() ? pAction->GetLen() : 0; diff --git a/vcl/source/filter/wmf/emfwr.cxx b/vcl/source/filter/wmf/emfwr.cxx index b2782847b1b1..a82c45de8d8e 100644 --- a/vcl/source/filter/wmf/emfwr.cxx +++ b/vcl/source/filter/wmf/emfwr.cxx @@ -861,7 +861,7 @@ void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt, } -void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, sal_uInt32 nWidth ) +void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, KernArraySpan pDXArray, sal_uInt32 nWidth ) { sal_Int32 nLen = rText.getLength(), i; @@ -869,8 +869,8 @@ void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, o return; sal_uInt32 nNormWidth; - std::vector<sal_Int32> aOwnArray; - o3tl::span<const sal_Int32> pDX; + KernArray aOwnArray; + KernArraySpan pDX; // get text sizes if( !pDXArray.empty() ) @@ -892,13 +892,13 @@ void EMFWriter::ImplWriteTextRecord( const Point& rPos, const OUString& rText, o { if (!pDXArray.empty()) { - aOwnArray.insert(aOwnArray.begin(), pDXArray.begin(), pDXArray.end()); + aOwnArray.assign(pDXArray); pDX = aOwnArray; } const double fFactor = static_cast<double>(nWidth) / nNormWidth; for( i = 0; i < ( nLen - 1 ); i++ ) - aOwnArray[ i ] = FRound( aOwnArray[ i ] * fFactor ); + aOwnArray.set(i, FRound(aOwnArray[i] * fFactor)); } } diff --git a/vcl/source/filter/wmf/emfwr.hxx b/vcl/source/filter/wmf/emfwr.hxx index 10ecd7f09f6d..4298096ff68c 100644 --- a/vcl/source/filter/wmf/emfwr.hxx +++ b/vcl/source/filter/wmf/emfwr.hxx @@ -74,7 +74,7 @@ private: void ImplWritePolygonRecord( const tools::Polygon& rPoly, bool bClose ); void ImplWritePolyPolygonRecord( const tools::PolyPolygon& rPolyPoly ); void ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt, const Size& rSz, sal_uInt32 nROP ); - void ImplWriteTextRecord( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, sal_uInt32 nWidth ); + void ImplWriteTextRecord( const Point& rPos, const OUString& rText, KernArraySpan pDXArray, sal_uInt32 nWidth ); void Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon); void ImplWrite( const GDIMetaFile& rMtf ); diff --git a/vcl/source/filter/wmf/wmfwr.cxx b/vcl/source/filter/wmf/wmfwr.cxx index 7c209b3a02ee..2c52aa7f5946 100644 --- a/vcl/source/filter/wmf/wmfwr.cxx +++ b/vcl/source/filter/wmf/wmfwr.cxx @@ -442,7 +442,7 @@ void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_In /* if return value is true, then a complete unicode string and also a polygon replacement has been written, so there is no more action necessary */ -bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const OUString& rUniStr, o3tl::span<const sal_Int32> pDXAry ) +bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const OUString& rUniStr, KernArraySpan pDXAry ) { bool bEscapeUsed = false; @@ -547,7 +547,7 @@ bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const OUString& r void WMFWriter::WMFRecord_ExtTextOut( const Point& rPoint, std::u16string_view rString, - o3tl::span<const sal_Int32> pDXAry ) + KernArraySpan pDXAry ) { sal_Int32 nOriginalTextLen = rString.size(); @@ -562,7 +562,7 @@ void WMFWriter::WMFRecord_ExtTextOut( const Point& rPoint, } void WMFWriter::TrueExtTextOut( const Point& rPoint, std::u16string_view rString, - const OString& rByteString, o3tl::span<const sal_Int32> pDXAry ) + const OString& rByteString, KernArraySpan pDXAry ) { WriteRecordHeader( 0, W_META_EXTTEXTOUT ); WritePointYX( rPoint ); @@ -1197,7 +1197,7 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF ) pVirDev->SetFont( aSrcFont ); const sal_Int32 nLen = aTemp.getLength(); - std::vector<sal_Int32> aDXAry; + KernArray aDXAry; const sal_Int32 nNormSize = pVirDev->GetTextArray( aTemp, nLen ? &aDXAry : nullptr ); if (nLen && nNormSize == 0) { @@ -1206,7 +1206,7 @@ void WMFWriter::WriteRecords( const GDIMetaFile & rMTF ) else { for ( sal_Int32 i = 0; i < ( nLen - 1 ); i++ ) - aDXAry[ i ] = aDXAry[ i ] * static_cast<sal_Int32>(pA->GetWidth()) / nNormSize; + aDXAry.set(i, aDXAry[i] * static_cast<sal_Int32>(pA->GetWidth()) / nNormSize); if ( ( nLen <= 1 ) || ( static_cast<sal_Int32>(pA->GetWidth()) == nNormSize ) ) aDXAry.clear(); aSrcLineInfo = LineInfo(); diff --git a/vcl/source/filter/wmf/wmfwr.hxx b/vcl/source/filter/wmf/wmfwr.hxx index 3b423e4fe682..b22d3d295c59 100644 --- a/vcl/source/filter/wmf/wmfwr.hxx +++ b/vcl/source/filter/wmf/wmfwr.hxx @@ -141,11 +141,11 @@ private: void WMFRecord_DeleteObject(sal_uInt16 nObjectHandle); void WMFRecord_Ellipse(const tools::Rectangle& rRect); void WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData ); - bool WMFRecord_Escape_Unicode( const Point& rPoint, const OUString& rStr, o3tl::span<const sal_Int32> pDXAry ); - void WMFRecord_ExtTextOut(const Point& rPoint, std::u16string_view rString, o3tl::span<const sal_Int32> pDXAry); + bool WMFRecord_Escape_Unicode( const Point& rPoint, const OUString& rStr, KernArraySpan pDXAry ); + void WMFRecord_ExtTextOut(const Point& rPoint, std::u16string_view rString, KernArraySpan pDXAry); void TrueExtTextOut(const Point& rPoint, std::u16string_view rString, - const OString& rByteString, o3tl::span<const sal_Int32> pDXAry); + const OString& rByteString, KernArraySpan pDXAry); void TrueTextOut(const Point& rPoint, const OString& rString); void WMFRecord_LineTo(const Point & rPoint); void WMFRecord_MoveTo(const Point & rPoint); diff --git a/vcl/source/gdi/metaact.cxx b/vcl/source/gdi/metaact.cxx index 0c426d1f930d..c072a27a7864 100644 --- a/vcl/source/gdi/metaact.cxx +++ b/vcl/source/gdi/metaact.cxx @@ -609,7 +609,7 @@ MetaTextArrayAction::MetaTextArrayAction( const MetaTextArrayAction& rAction ) : MetaTextArrayAction::MetaTextArrayAction( const Point& rStartPt, OUString aStr, - std::vector<sal_Int32> aDXAry, + KernArray aDXAry, std::vector<sal_Bool> aKashidaAry, sal_Int32 nIndex, sal_Int32 nLen ) : @@ -625,18 +625,18 @@ MetaTextArrayAction::MetaTextArrayAction( const Point& rStartPt, MetaTextArrayAction::MetaTextArrayAction( const Point& rStartPt, OUString aStr, - o3tl::span<const sal_Int32> pDXAry, + KernArraySpan 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 ) { + maDXAry.assign(pDXAry); } MetaTextArrayAction::~MetaTextArrayAction() @@ -665,11 +665,11 @@ void MetaTextArrayAction::Scale( double fScaleX, double fScaleY ) if ( !maDXAry.empty() && mnLen ) { for ( sal_uInt16 i = 0, nCount = mnLen; i < nCount; i++ ) - maDXAry[ i ] = FRound( maDXAry[ i ] * fabs(fScaleX) ); + maDXAry.set(i, FRound(maDXAry[i] * fabs(fScaleX))); } } -void MetaTextArrayAction::SetDXArray(std::vector<sal_Int32> aArray) +void MetaTextArrayAction::SetDXArray(KernArray aArray) { maDXAry = std::move(aArray); } diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx index efea6a987f5b..8b206debfbc1 100644 --- a/vcl/source/gdi/pdfwriter.cxx +++ b/vcl/source/gdi/pdfwriter.cxx @@ -81,7 +81,7 @@ void PDFWriter::DrawTextLine( void PDFWriter::DrawTextArray( const Point& rStartPt, const OUString& rStr, - o3tl::span<const sal_Int32> pDXAry, + KernArraySpan pDXAry, o3tl::span<const sal_Bool> pKashidaAry, sal_Int32 nIndex, sal_Int32 nLen ) diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 18f9032529c9..5958a202e29e 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -64,6 +64,7 @@ #include <vcl/cvtgrf.hxx> #include <vcl/fontcharmap.hxx> #include <vcl/glyphitemcache.hxx> +#include <vcl/kernarray.hxx> #include <vcl/lineinfo.hxx> #include <vcl/metric.hxx> #include <vcl/mnemonic.hxx> @@ -6970,7 +6971,7 @@ void PDFWriterImpl::drawText( const Point& rPos, const OUString& rText, sal_Int3 } } -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 ) +void PDFWriterImpl::drawTextArray( const Point& rPos, const OUString& rText, KernArraySpan pDXArray, o3tl::span<const sal_Bool> pKashidaArray, sal_Int32 nIndex, sal_Int32 nLen ) { MARK( "drawText with array" ); diff --git a/vcl/source/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx index 2d0219041ba2..0ee1c9ba5faf 100644 --- a/vcl/source/gdi/textlayout.cxx +++ b/vcl/source/gdi/textlayout.cxx @@ -18,6 +18,7 @@ */ #include <vcl/ctrl.hxx> +#include <vcl/kernarray.hxx> #include <vcl/outdev.hxx> #include <textlayout.hxx> @@ -86,7 +87,7 @@ namespace vcl tools::Rectangle GetTextRect( const tools::Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, Size* o_pDeviceSize ); private: - tools::Long GetTextArray( const OUString& _rText, std::vector<sal_Int32>* _pDXAry, sal_Int32 _nStartIndex, sal_Int32 _nLength ) const; + tools::Long GetTextArray( const OUString& _rText, KernArray* _pDXAry, sal_Int32 _nStartIndex, sal_Int32 _nLength ) const; OutputDevice& m_rTargetDevice; OutputDevice& m_rReferenceDevice; @@ -159,7 +160,7 @@ namespace vcl } } - tools::Long ReferenceDeviceTextLayout::GetTextArray( const OUString& _rText, std::vector<sal_Int32>* _pDXAry, sal_Int32 _nStartIndex, sal_Int32 _nLength ) const + tools::Long ReferenceDeviceTextLayout::GetTextArray( const OUString& _rText, KernArray* _pDXAry, sal_Int32 _nStartIndex, sal_Int32 _nLength ) const { if ( !lcl_normalizeLength( _rText, _nStartIndex, _nLength ) ) return 0; @@ -207,7 +208,7 @@ namespace vcl return; } - std::vector<sal_Int32> aCharWidths; + KernArray aCharWidths; tools::Long nTextWidth = GetTextArray( _rText, &aCharWidths, _nStartIndex, _nLength ); m_rTargetDevice.DrawTextArray( _rStartPoint, _rText, aCharWidths, {}, _nStartIndex, _nLength ); diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 029a49cc9acf..f66ece92d48b 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -921,7 +921,7 @@ float OutputDevice::approximate_digit_width() const } void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, - o3tl::span<const sal_Int32> pDXAry, + KernArraySpan pDXAry, o3tl::span<const sal_Bool> pKashidaAry, sal_Int32 nIndex, sal_Int32 nLen, SalLayoutFlags flags, const SalLayoutGlyphs* pSalLayoutCache ) @@ -955,7 +955,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, mpAlphaVDev->DrawTextArray( rStartPt, rStr, pDXAry, pKashidaAry, nIndex, nLen, flags ); } -tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector<sal_Int32>* pDXAry, +tools::Long OutputDevice::GetTextArray( const OUString& rStr, KernArray* pKernArray, sal_Int32 nIndex, sal_Int32 nLen, bool bCaret, vcl::text::TextLayoutCache const*const pLayoutCache, SalLayoutGlyphs const*const pSalLayoutCache) const @@ -968,6 +968,8 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector<sal_In nLen = rStr.getLength() - nIndex; } + std::vector<sal_Int32>* pDXAry = pKernArray ? &pKernArray->get_subunit_array() : nullptr; + // do layout std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, Point(0,0), 0, {}, {}, eDefaultLayout, pLayoutCache, pSalLayoutCache); @@ -1035,14 +1037,24 @@ tools::Long OutputDevice::GetTextArray( const OUString& rStr, std::vector<sal_In (*pDXAry)[ i ] += (*pDXAry)[ i-1 ]; // convert from font units to logical units - if( mbMap ) + if (pDXAry) { - if( pDXAry ) - for( int i = 0; i < nLen; ++i ) - (*pDXAry)[i] = ImplDevicePixelToLogicWidth( (*pDXAry)[i] ); - nWidth = ImplDevicePixelToLogicWidth( nWidth ); + int nSubPixelFactor = pKernArray->get_factor(); + if (mbMap) + { + for (int i = 0; i < nLen; ++i) + (*pDXAry)[i] = ImplDevicePixelToLogicWidth( (*pDXAry)[i] * nSubPixelFactor ); + } + else if (nSubPixelFactor) + { + for (int i = 0; i < nLen; ++i) + (*pDXAry)[i] *= nSubPixelFactor; + } } + if (mbMap) + nWidth = ImplDevicePixelToLogicWidth( nWidth ); + return nWidth; #endif /* VCL_FLOAT_DEVICE_PIXEL */ } @@ -1290,7 +1302,7 @@ 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, + KernArraySpan pDXArray, o3tl::span<const sal_Bool> pKashidaArray, SalLayoutFlags flags, vcl::text::TextLayoutCache const* pLayoutCache, @@ -1360,13 +1372,14 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, { // convert from logical units to font units without rounding, // keeping accuracy for lower levels + int nSubPixels = pDXArray.get_factor(); for (int i = 0; i < nLen; ++i) - xNaturalDXPixelArray[i] = ImplLogicWidthToDeviceSubPixel(pDXArray[i]); + xNaturalDXPixelArray[i] = ImplLogicWidthToDeviceSubPixel(pDXArray.get_subunit(i)) / nSubPixels; } else { for(int i = 0; i < nLen; ++i) - xNaturalDXPixelArray[i] = pDXArray[i]; + xNaturalDXPixelArray[i] = pDXArray.get(i); } aLayoutArgs.SetNaturalDXArray(xNaturalDXPixelArray.get()); @@ -2310,7 +2323,7 @@ tools::Long OutputDevice::GetCtrlTextWidth( const OUString& rStr, const SalLayou 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, + sal_uLong nLayoutWidth, KernArraySpan pDXAry, o3tl::span<const sal_Bool> pKashidaAry, const SalLayoutGlyphs* pGlyphs ) const { @@ -2361,7 +2374,7 @@ 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, + KernArraySpan pDXArray, o3tl::span<const sal_Bool> pKashidaArray ) const { if (!InitFont()) @@ -2442,7 +2455,7 @@ 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, + sal_uLong nLayoutWidth, KernArraySpan pDXArray, o3tl::span<const sal_Bool> pKashidaArray ) const { rResultVector.clear(); diff --git a/vcl/workben/vcldemo.cxx b/vcl/workben/vcldemo.cxx index 4588b4e73a8e..05897bce5f6d 100644 --- a/vcl/workben/vcldemo.cxx +++ b/vcl/workben/vcldemo.cxx @@ -47,6 +47,7 @@ #include <vcl/toolbox.hxx> #include <vcl/toolkit/floatwin.hxx> #include <vcl/help.hxx> +#include <vcl/kernarray.hxx> #include <vcl/menu.hxx> #include <vcl/ImageTree.hxx> #include <vcl/BitmapEmbossGreyFilter.hxx> @@ -633,7 +634,7 @@ public: } // DX array rendering - std::vector<sal_Int32> aItems; + KernArray aItems; rDev.GetTextArray(aText, &aItems); for (tools::Long j = 0; j < aText.getLength(); ++j) { |