Skip to content

Commit

Permalink
tdf#30731: Improve caret travelling in Writer
Browse files Browse the repository at this point in the history
Previously, when measuring caret position, Writer would measure the
width of the substring before the caret (i.e. layout it independent of
the text after the caret and measure its width).

This is incorrect, though. It assumes cutting the string laying it out
would result in the same width as when laid out as part of a bigger
string, which is invalid assumption when e.g. cutting inside a ligature
or between letters that have different shapes when next to each other,
etc.

This appears to work when the width of the substring laid out alone is
close enough to its width when laid out with the full text. But in cases
where is widths are largely different, like the extreme case in the bug
report, the caret will be jumping around as it is positioned based on
the unligated glyphs not the ligated, rendered glyphs.

This change introduces a special mode of measuring text width for caret
positioning, that will layout the whole string that return the width of
the requested substring.

Fields and small caps text are trickier to handle, so old behaviour is
retained for them. Now one will probably notice but if they do, it can
be dealt with then.

This also tries to be conservative and keep other pleases using the
existing behaviour which might be desirable (e.g. when measuring text
width for line breaking, we want the unligated width), but there might
be other places that should use the new behaviour.

To handle caret inside ligatures, the grapheme clusters in the ligature
are counted and the width of the whole ligature is distributed on them
evenly. A further improvement would be using HarfBuzz API to get
ligature caret positions for fonts that provide them, which helps when
the ligature components have different widths.

Change-Id: I02062e2e2e1b1a35c8f84307c0a8f5d743059ab5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138889
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <[email protected]>
  • Loading branch information
khaledhosny authored and vmiklos committed Aug 31, 2022
1 parent d325edf commit 8cb4db9
Show file tree
Hide file tree
Showing 15 changed files with 253 additions and 44 deletions.
2 changes: 1 addition & 1 deletion editeng/source/items/svxfont.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static tools::Long GetTextArray( const OutputDevice* pOut, const OUString& rStr,

{
const SalLayoutGlyphs* layoutGlyphs = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(pOut, rStr, nIndex, nLen);
return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, nullptr, layoutGlyphs);
return pOut->GetTextArray( rStr, pDXAry, nIndex, nLen, false, nullptr, layoutGlyphs);
}

SvxFont::SvxFont()
Expand Down
2 changes: 1 addition & 1 deletion include/vcl/outdev.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ public:
SalLayoutFlags flags = SalLayoutFlags::NONE,
const SalLayoutGlyphs* pLayoutCache = nullptr);
tools::Long GetTextArray( const OUString& rStr, std::vector<sal_Int32>* pDXAry,
sal_Int32 nIndex = 0, sal_Int32 nLen = -1,
sal_Int32 nIndex = 0, sal_Int32 nLen = -1, bool bCaret = false,
vcl::text::TextLayoutCache const* = nullptr,
SalLayoutGlyphs const*const pLayoutCache = nullptr) const;

Expand Down
6 changes: 4 additions & 2 deletions include/vcl/vcllayout.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#pragma once

#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <i18nlangtag/languagetag.hxx>
#include <tools/gen.hxx>
#include <tools/degree.hxx>

Expand Down Expand Up @@ -94,8 +95,8 @@ public:

// methods using string indexing
virtual sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const = 0;
virtual DeviceCoordinate FillDXArray( std::vector<DeviceCoordinate>* pDXArray ) const = 0;
virtual DeviceCoordinate GetTextWidth() const { return FillDXArray( nullptr ); }
virtual DeviceCoordinate FillDXArray( std::vector<DeviceCoordinate>* pDXArray, const OUString& rStr ) const = 0;
virtual DeviceCoordinate GetTextWidth() const { return FillDXArray( nullptr, {} ); }
virtual void GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const = 0;
virtual bool IsKashidaPosValid ( int /*nCharPos*/, int /*nNextCharPos*/ ) const = 0; // i60594

Expand All @@ -119,6 +120,7 @@ private:
protected:
int mnMinCharPos;
int mnEndCharPos;
LanguageTag maLanguageTag;

int mnUnitsPerPixel;
Degree10 mnOrientation;
Expand Down
7 changes: 5 additions & 2 deletions osx/soffice.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXFileReference section */
29FD821128BC548D00159078 /* text */ = {isa = PBXFileReference; lastKnownFileType = folder; name = text; path = ../sw/source/core/text; sourceTree = "<group>"; };
29FD821228BC54AB00159078 /* txtnode */ = {isa = PBXFileReference; lastKnownFileType = folder; name = txtnode; path = ../sw/source/core/txtnode; sourceTree = "<group>"; };
456E58CF277CB9C700FA12D2 /* unoshap2.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = unoshap2.cxx; path = ../svx/source/unodraw/unoshap2.cxx; sourceTree = "<group>"; };
456E58D1277CC33E00FA12D2 /* unopage.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = unopage.cxx; path = ../svx/source/unodraw/unopage.cxx; sourceTree = "<group>"; };
BE017B8725AF2ABE00244ED8 /* autostyl.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = autostyl.cxx; path = ../sc/source/ui/docshell/autostyl.cxx; sourceTree = "<group>"; };
Expand Down Expand Up @@ -123,7 +125,6 @@
BE017BF825AF568900244ED8 /* solveroptions.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = solveroptions.cxx; path = ../sc/source/ui/miscdlgs/solveroptions.cxx; sourceTree = "<group>"; };
BE017BF925AF568900244ED8 /* mtrindlg.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = mtrindlg.cxx; path = ../sc/source/ui/miscdlgs/mtrindlg.cxx; sourceTree = "<group>"; };
BE017BFA25AF568900244ED8 /* linkarea.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = linkarea.cxx; path = ../sc/source/ui/miscdlgs/linkarea.cxx; sourceTree = "<group>"; };
BE017BFB25AF568900244ED8 /* shtabdlg.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = shtabdlg.cxx; path = ../sc/source/ui/miscdlgs/shtabdlg.cxx; sourceTree = "<group>"; };
BE017BFB25AF568900244ED8 /* gototabdlg.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = gototabdlg.cxx; path = ../sc/source/ui/miscdlgs/gototabdlg.cxx; sourceTree = "<group>"; };
BE017BFC25AF568900244ED8 /* inscodlg.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = inscodlg.cxx; path = ../sc/source/ui/miscdlgs/inscodlg.cxx; sourceTree = "<group>"; };
BE017BFD25AF568A00244ED8 /* crdlg.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = crdlg.cxx; path = ../sc/source/ui/miscdlgs/crdlg.cxx; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1281,7 +1282,7 @@
BE017C1D25AF568B00244ED8 /* retypepassdlg.cxx */,
BE017C0125AF568A00244ED8 /* scuiautofmt.cxx */,
BE017C1C25AF568B00244ED8 /* sharedocdlg.cxx */,
BE017BFB25AF568900244ED8 /* shtabdlg.cxx */,
BE017BFB25AF568900244ED8 /* gototabdlg.cxx */,
BE017C1F25AF568B00244ED8 /* simpref.cxx */,
BE017BF825AF568900244ED8 /* solveroptions.cxx */,
BE017C0C25AF568A00244ED8 /* solverutil.cxx */,
Expand Down Expand Up @@ -2365,6 +2366,8 @@
BEBF3E662465907000415E87 /* sw */ = {
isa = PBXGroup;
children = (
29FD821228BC54AB00159078 /* txtnode */,
29FD821128BC548D00159078 /* text */,
BEBF3E6E246593A300415E87 /* ui */,
BEBF3E672465907D00415E87 /* uibase */,
);
Expand Down
13 changes: 13 additions & 0 deletions sw/source/core/inc/drawfont.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class SW_DLLPUBLIC SwDrawTextInfo
tools::Long m_nKanaDiff;
TextFrameIndex m_nIdx;
TextFrameIndex m_nLen;
TextFrameIndex m_nMeasureLen;
/// this is not a string index
sal_Int32 m_nOfst;
sal_uInt16 m_nWidth;
Expand Down Expand Up @@ -127,6 +128,7 @@ public:
m_aText = rText;
m_nIdx = nIdx;
m_nLen = nLen;
m_nMeasureLen = TextFrameIndex(COMPLETE_STRING);
m_nKern = 0;
m_nCompress = 0;
m_nWidth = nWidth;
Expand Down Expand Up @@ -274,6 +276,11 @@ public:
return m_nLen;
}

TextFrameIndex GetMeasureLen() const
{
return m_nMeasureLen;
}

sal_Int32 GetOffset() const
{
#ifdef DBG_UTIL
Expand Down Expand Up @@ -488,6 +495,12 @@ public:
m_nLen = nNew;
}

void SetMeasureLen(TextFrameIndex const nNew)
{
assert( nNew == TextFrameIndex(COMPLETE_STRING) || nNew <= m_nLen );
m_nMeasureLen = nNew;
}

void SetOffset( sal_Int32 nNew )
{
m_nOfst = nNew;
Expand Down
12 changes: 11 additions & 1 deletion sw/source/core/text/inftxt.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ SwTextSizeInfo::SwTextSizeInfo()
, m_pText(nullptr)
, m_nIdx(0)
, m_nLen(0)
, m_nMeasureLen(COMPLETE_STRING)
, m_nKanaIdx(0)
, m_bOnWin (false)
, m_bNotEOL (false)
Expand Down Expand Up @@ -221,6 +222,7 @@ SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew )
m_pText(&rNew.GetText()),
m_nIdx(rNew.GetIdx()),
m_nLen(rNew.GetLen()),
m_nMeasureLen(rNew.GetMeasureLen()),
m_nKanaIdx( rNew.GetKanaIdx() ),
m_bOnWin( rNew.OnWin() ),
m_bNotEOL( rNew.NotEOL() ),
Expand Down Expand Up @@ -309,7 +311,7 @@ void SwTextSizeInfo::CtorInitTextSizeInfo( OutputDevice* pRenderContext, SwTextF
m_pText = &m_pFrame->GetText();

m_nIdx = nNewIdx;
m_nLen = TextFrameIndex(COMPLETE_STRING);
m_nLen = m_nMeasureLen = TextFrameIndex(COMPLETE_STRING);
m_bNotEOL = false;
m_bStopUnderflow = m_bFootnoteInside = m_bOtherThanFootnoteInside = false;
m_bMulti = m_bFirstMulti = m_bRuby = m_bHanging = m_bScriptSpace =
Expand All @@ -332,6 +334,7 @@ SwTextSizeInfo::SwTextSizeInfo( const SwTextSizeInfo &rNew, const OUString* pTex
m_pText(pText),
m_nIdx(nIndex),
m_nLen(COMPLETE_STRING),
m_nMeasureLen(COMPLETE_STRING),
m_nKanaIdx( rNew.GetKanaIdx() ),
m_bOnWin( rNew.OnWin() ),
m_bNotEOL( rNew.NotEOL() ),
Expand Down Expand Up @@ -407,6 +410,7 @@ SwPosSize SwTextSizeInfo::GetTextSize() const
0 ;

SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rSI, *m_pText, m_nIdx, m_nLen );
aDrawInf.SetMeasureLen( m_nMeasureLen );
aDrawInf.SetFrame( m_pFrame );
aDrawInf.SetFont( m_pFnt );
aDrawInf.SetSnapToGrid( SnapToGrid() );
Expand Down Expand Up @@ -1826,6 +1830,7 @@ SwTextSlot::SwTextSlot(
, m_pOldGrammarCheckList(nullptr)
, nIdx(0)
, nLen(0)
, nMeasureLen(0)
, pInf(nullptr)
{
if( rCh.isEmpty() )
Expand All @@ -1845,11 +1850,15 @@ SwTextSlot::SwTextSlot(
pInf = const_cast<SwTextSizeInfo*>(pNew);
nIdx = pInf->GetIdx();
nLen = pInf->GetLen();
nMeasureLen = pInf->GetMeasureLen();
pOldText = &(pInf->GetText());
m_pOldCachedVclData = pInf->GetCachedVclData();
pInf->SetText( aText );
pInf->SetIdx(TextFrameIndex(0));
pInf->SetLen(bTextLen ? TextFrameIndex(pInf->GetText().getLength()) : pPor->GetLen());
if (nMeasureLen != TextFrameIndex(COMPLETE_STRING))
pInf->SetMeasureLen(TextFrameIndex(COMPLETE_STRING));

pInf->SetCachedVclData(nullptr);

// ST2
Expand Down Expand Up @@ -1923,6 +1932,7 @@ SwTextSlot::~SwTextSlot()
pInf->SetText( *pOldText );
pInf->SetIdx( nIdx );
pInf->SetLen( nLen );
pInf->SetMeasureLen( nMeasureLen );

// ST2
// Restore old smart tag list
Expand Down
4 changes: 4 additions & 0 deletions sw/source/core/text/inftxt.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ protected:
const OUString *m_pText;
TextFrameIndex m_nIdx;
TextFrameIndex m_nLen;
TextFrameIndex m_nMeasureLen;
sal_uInt16 m_nKanaIdx;
bool m_bOnWin : 1;
bool m_bNotEOL : 1;
Expand Down Expand Up @@ -273,6 +274,8 @@ public:
void SetIdx(const TextFrameIndex nNew) { m_nIdx = nNew; }
TextFrameIndex GetLen() const { return m_nLen; }
void SetLen(const TextFrameIndex nNew) { m_nLen = nNew; }
TextFrameIndex GetMeasureLen() const { return m_nMeasureLen; }
void SetMeasureLen(const TextFrameIndex nNew) { m_nMeasureLen = nNew; }
void SetText( const OUString &rNew ){ m_pText = &rNew; }

// No Bullets for the symbol font!
Expand Down Expand Up @@ -682,6 +685,7 @@ class SwTextSlot final
std::unique_ptr<sw::WrongListIterator> m_pTempIter;
TextFrameIndex nIdx;
TextFrameIndex nLen;
TextFrameIndex nMeasureLen;
bool bOn;
SwTextSizeInfo *pInf;

Expand Down
29 changes: 26 additions & 3 deletions sw/source/core/text/itrcrsr.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -907,9 +907,21 @@ void SwTextCursor::GetCharRect_( SwRect* pOrig, TextFrameIndex const nOfst,
}
if ( pPor->PrtWidth() )
{
// tdf#30731: To get the correct nOfst width, we need
// to send the whole portion string to GetTextSize()
// and ask it to return the width of nOfst by calling
// SetMeasureLen(). Cutting the string at nOfst can
// give the wrong width if nOfst is in e.g. the middle
// of a ligature. See SwFntObj::DrawText().
TextFrameIndex const nOldLen = pPor->GetLen();
pPor->SetLen( nOfst - aInf.GetIdx() );
aInf.SetLen( pPor->GetLen() );
pPor->SetLen( nOfst - aInf.GetIdx() );
aInf.SetMeasureLen(pPor->GetLen());
if (aInf.GetLen() < aInf.GetMeasureLen())
{
pPor->SetLen(aInf.GetMeasureLen());
aInf.SetLen(pPor->GetLen());
}
if( nX || !pPor->InNumberGrp() )
{
SeekAndChg( aInf );
Expand All @@ -925,7 +937,12 @@ void SwTextCursor::GetCharRect_( SwRect* pOrig, TextFrameIndex const nOfst,
if( bWidth )
{
pPor->SetLen(pPor->GetLen() + TextFrameIndex(1));
aInf.SetLen( pPor->GetLen() );
aInf.SetMeasureLen(pPor->GetLen());
if (aInf.GetLen() < aInf.GetMeasureLen())
{
pPor->SetLen(aInf.GetMeasureLen());
aInf.SetLen(pPor->GetLen());
}
aInf.SetOnWin( false ); // no BULLETs!
nTmp += pPor->GetTextSize( aInf ).Width();
aInf.SetOnWin( bOldOnWin );
Expand Down Expand Up @@ -1102,8 +1119,14 @@ void SwTextCursor::GetCharRect_( SwRect* pOrig, TextFrameIndex const nOfst,
{
const bool bOldOnWin = aInf.OnWin();
TextFrameIndex const nOldLen = pPor->GetLen();
pPor->SetLen( TextFrameIndex(1) );
aInf.SetLen( pPor->GetLen() );
pPor->SetLen( TextFrameIndex(1) );
aInf.SetMeasureLen(pPor->GetLen());
if (aInf.GetLen() < aInf.GetMeasureLen())
{
pPor->SetLen(aInf.GetMeasureLen());
aInf.SetLen(pPor->GetLen());
}
SeekAndChg( aInf );
aInf.SetOnWin( false ); // no BULLETs!
aInf.SetKanaComp( pKanaComp );
Expand Down
41 changes: 27 additions & 14 deletions sw/source/core/txtnode/fntcache.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -732,23 +732,27 @@ static void lcl_DrawLineForWrongListData(
}

static void GetTextArray(const OutputDevice& rDevice, const OUString& rStr, std::vector<sal_Int32>& rDXAry,
sal_Int32 nIndex, sal_Int32 nLen, const vcl::text::TextLayoutCache* layoutCache = nullptr)
sal_Int32 nIndex, sal_Int32 nLen, bool bCaret = false,
const vcl::text::TextLayoutCache* layoutCache = nullptr)
{
const SalLayoutGlyphs* pLayoutCache = SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&rDevice, rStr, nIndex, nLen,
0, layoutCache);
rDevice.GetTextArray(rStr, &rDXAry, nIndex, nLen, layoutCache, pLayoutCache);
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, std::vector<sal_Int32>& rDXAry,
bool bCaret = false)
{
return GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), rInf.GetLen().get(), rInf.GetVclCache());
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, sal_Int32 nLen)
static void GetTextArray(const OutputDevice& rOutputDevice, const SwDrawTextInfo& rInf, std::vector<sal_Int32>& rDXAry,
sal_Int32 nLen, bool bCaret = false)
{
// Substring is fine.
assert( nLen <= rInf.GetLen().get());
return GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), nLen, rInf.GetVclCache());
return GetTextArray(rOutputDevice, rInf.GetText(), rDXAry, rInf.GetIdx().get(), nLen, bCaret, rInf.GetVclCache());
}

void SwFntObj::DrawText( SwDrawTextInfo &rInf )
Expand Down Expand Up @@ -1529,6 +1533,15 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
? rInf.GetLen()
: TextFrameIndex(rInf.GetText().getLength());

const TextFrameIndex nMsrLn = (TextFrameIndex(COMPLETE_STRING) != rInf.GetMeasureLen())
? rInf.GetMeasureLen()
: nLn;

// If the measure length is different from the length, then we are
// measuring substring width for caret positioning, see SetMeasureLength()
// use in TextCursor::GetCharRect_().
bool bCaret(nMsrLn != nLn);

// be sure to have the correct layout mode at the printer
if ( m_pPrinter )
{
Expand Down Expand Up @@ -1566,7 +1579,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
GetFontLeading( rInf.GetShell(), rInf.GetOut() ) );

std::vector<sal_Int32> aKernArray;
GetTextArray(*pOutDev, rInf, aKernArray, sal_Int32(rInf.GetLen()));
GetTextArray(*pOutDev, rInf, aKernArray, sal_Int32(nLn), bCaret);
if (pGrid->IsSnapToChars())
{
sw::Justify::SnapToGrid(aKernArray, rInf.GetText(), sal_Int32(rInf.GetIdx()),
Expand All @@ -1579,7 +1592,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
rInf.GetKern());
}

aTextSize.setWidth(aKernArray[sal_Int32(rInf.GetLen()) - 1]);
aTextSize.setWidth(aKernArray[sal_Int32(nMsrLn) - 1]);
rInf.SetKanaDiff( 0 );
return aTextSize;
}
Expand Down Expand Up @@ -1609,15 +1622,15 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
rInf.GetOut().SetFont( *m_pScrFont );

GetTextArray(*m_pPrinter, rInf.GetText(), aKernArray,
sal_Int32(rInf.GetIdx()), sal_Int32(nLn));
sal_Int32(rInf.GetIdx()), sal_Int32(nLn), bCaret);
}
else
{
if( !m_pPrtFont->IsSameInstance( rInf.GetOut().GetFont() ) )
rInf.GetOut().SetFont( *m_pPrtFont );
aTextSize.setHeight( rInf.GetOut().GetTextHeight() );

GetTextArray(rInf.GetOut(), rInf, aKernArray, nLn.get());
GetTextArray(rInf.GetOut(), rInf, aKernArray, nLn.get(), bCaret);
}

if (bCompress)
Expand All @@ -1628,16 +1641,16 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
else
rInf.SetKanaDiff( 0 );

if (nLn)
if (nMsrLn)
{
aTextSize.setWidth(aKernArray[sal_Int32(nLn) - 1]);
aTextSize.setWidth(aKernArray[sal_Int32(nMsrLn) - 1]);

// Note that we can't simply use sal_Int(nLn) - 1 as nSpaceCount
// Note that we can't simply use sal_Int(nMsrLn) - 1 as nSpaceCount
// because a glyph may be made up of more than one characters.
sal_Int32 nSpaceCount = 0;
tools::Long nOldValue = aKernArray[0];

for(sal_Int32 i = 1; i < sal_Int32(nLn); ++i)
for(sal_Int32 i = 1; i < sal_Int32(nMsrLn); ++i)
{
if (nOldValue != aKernArray[i])
{
Expand Down
Loading

0 comments on commit 8cb4db9

Please sign in to comment.