LibreOffice Module sw (master)  1
porglue.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <swrect.hxx>
21 #include <viewopt.hxx>
22 #include "porglue.hxx"
23 #include "inftxt.hxx"
24 #include "porlay.hxx"
25 #include "porfly.hxx"
26 #include <comphelper/string.hxx>
27 
28 SwGluePortion::SwGluePortion( const sal_uInt16 nInitFixWidth )
29  : m_nFixWidth( nInitFixWidth )
30 {
33 }
34 
36 {
37  // FIXME why nOfst > GetLen() ? is that supposed to be > Width() ?
38  if( !GetLen() || nOfst > sal_Int32(GetLen()) || !Width() )
40  else
41  return TextFrameIndex(nOfst / (Width() / sal_Int32(GetLen())));
42 }
43 
45 {
46  if (TextFrameIndex(1) >= GetLen() || rInf.GetLen() > GetLen() || !Width() || !GetLen())
47  return SwPosSize(*this);
48  else
49  return SwPosSize((Width() / sal_Int32(GetLen())) * sal_Int32(rInf.GetLen()), Height());
50 }
51 
52 bool SwGluePortion::GetExpText( const SwTextSizeInfo &rInf, OUString &rText ) const
53 {
54  if( GetLen() && rInf.OnWin() &&
55  rInf.GetOpt().IsBlank() && rInf.IsNoSymbol() )
56  {
57  OUStringBuffer aBuf(GetLen().get());
59  rText = aBuf.makeStringAndClear();
60  return true;
61  }
62  return false;
63 }
64 
65 void SwGluePortion::Paint( const SwTextPaintInfo &rInf ) const
66 {
67  if( !GetLen() )
68  return;
69 
70  if( rInf.GetFont()->IsPaintBlank() )
71  {
72  const sal_Int32 nCount = GetFixWidth() / sal_Int32(GetLen());
73  OUStringBuffer aBuf(nCount);
74  comphelper::string::padToLength(aBuf, nCount, ' ');
75  OUString aText(aBuf.makeStringAndClear());
76  SwTextPaintInfo aInf( rInf, &aText );
77  aInf.DrawText(*this, TextFrameIndex(aText.getLength()), true);
78  }
79 
80  if( !(rInf.OnWin() && rInf.GetOpt().IsBlank() && rInf.IsNoSymbol()) )
81  return;
82 
83 #if OSL_DEBUG_LEVEL > 0
84  const sal_Unicode cChar = rInf.GetChar( rInf.GetIdx() );
85  OSL_ENSURE( CH_BLANK == cChar || CH_BULLET == cChar,
86  "SwGluePortion::Paint: blank expected" );
87 #endif
88  if (TextFrameIndex(1) == GetLen())
89  {
90  OUString aBullet( CH_BULLET );
91  SwPosSize aBulletSize( rInf.GetTextSize( aBullet ) );
92  Point aPos( rInf.GetPos() );
93  aPos.AdjustX((Width()/2) - (aBulletSize.Width()/2) );
94  SwTextPaintInfo aInf( rInf, &aBullet );
95  aInf.SetPos( aPos );
96  SwTextPortion aBulletPor;
97  aBulletPor.Width( aBulletSize.Width() );
98  aBulletPor.Height( aBulletSize.Height() );
99  aBulletPor.SetAscent( GetAscent() );
100  aInf.DrawText(aBulletPor, TextFrameIndex(aBullet.getLength()), true);
101  }
102  else
103  {
104  SwTextSlot aSlot( &rInf, this, true, false );
105  rInf.DrawText( *this, rInf.GetLen(), true );
106  }
107 }
108 
109 void SwGluePortion::MoveGlue( SwGluePortion *pTarget, const tools::Long nPrtGlue )
110 {
111  auto nPrt = std::min( nPrtGlue, GetPrtGlue() );
112  if( 0 < nPrt )
113  {
114  pTarget->AddPrtWidth( nPrt ); //TODO: overflow
115  SubPrtWidth( nPrt ); //TODO: overflow
116  }
117 }
118 
120 {
121  // The GluePortion is extracted and flushed away ...
122  AddPrtWidth( pVictim->PrtWidth() );
123  SetLen( pVictim->GetLen() + GetLen() );
124  if( Height() < pVictim->Height() )
125  Height( pVictim->Height() );
126 
127  AdjFixWidth();
128  Cut( pVictim );
129  delete pVictim;
130 }
131 
132 void SwGluePortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText,
133  TextFrameIndex& nOffset) const
134 {
135  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwGluePortion"));
136  dumpAsXmlAttributes(pWriter, rText, nOffset);
137  nOffset += GetLen();
138 
139  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("fix-width"), BAD_CAST(OString::number(m_nFixWidth).getStr()));
140 
141  (void)xmlTextWriterEndElement(pWriter);
142 }
143 
148  :SwGluePortion( sal_uInt16(rRect.Width()) ), m_nFix( sal_uInt16(rRect.Left()) )
149 {
150  Height( sal_uInt16(rRect.Height()) );
152 }
153 
155  : SwGluePortion(0), m_nFix(0)
156 {
158 }
159 
160 void SwFixPortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex& nOffset) const
161 {
162  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwFixPortion"));
163  dumpAsXmlAttributes(pWriter, rText, nOffset);
164  nOffset += GetLen();
165 
166  (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("fix"),
167  BAD_CAST(OString::number(m_nFix).getStr()));
168 
169  (void)xmlTextWriterEndElement(pWriter);
170 }
171 
173  :SwGluePortion( 0 )
174 {
176 }
177 
189 {
190  SwGluePortion *pRight = nullptr;
191  bool bNoMove = nullptr != pCurr->GetpKanaComp();
192  while( pRight != this )
193  {
194 
195  // 1) We search for the left Glue
196  SwLinePortion *pPos = this;
197  SwGluePortion *pLeft = nullptr;
198  while( pPos )
199  {
200  if( pPos->InFixMargGrp() )
201  pLeft = static_cast<SwGluePortion*>(pPos);
202  pPos = pPos->GetNextPortion();
203  if( pPos == pRight)
204  pPos = nullptr;
205  }
206 
207  // Two adjoining FlyPortions are merged
208  if( pRight && pLeft && pLeft->GetNextPortion() == pRight )
209  {
210  pRight->MoveAllGlue( pLeft );
211  pRight = nullptr;
212  }
213  auto nRightGlue = pRight && 0 < pRight->GetPrtGlue()
214  ? pRight->GetPrtGlue() : 0;
215  // 2) balance left and right Glue
216  // But not for tabs ...
217  if( pLeft && nRightGlue && !pRight->InTabGrp() )
218  {
219  // pPrev is the portion immediately before pRight
220  SwLinePortion *pPrev = pRight->FindPrevPortion( pLeft );
221 
222  if ( pRight->IsFlyPortion() && pRight->GetLen() )
223  {
224  SwFlyPortion *pFly = static_cast<SwFlyPortion *>(pRight);
225  if ( pFly->GetBlankWidth() < nRightGlue )
226  {
227  // Creating new TextPortion, that takes over the
228  // Blank previously swallowed by the Fly.
229  nRightGlue = nRightGlue - pFly->GetBlankWidth();
230  pFly->SubPrtWidth( pFly->GetBlankWidth() );
231  pFly->SetLen(TextFrameIndex(0));
232  SwTextPortion *pNewPor = new SwTextPortion;
233  pNewPor->SetLen(TextFrameIndex(1));
234  pNewPor->Height( pFly->Height() );
235  pNewPor->Width( pFly->GetBlankWidth() );
236  pFly->Insert( pNewPor );
237  }
238  else
239  pPrev = pLeft;
240  }
241  while( pPrev != pLeft )
242  {
243  if( bNoMove || pPrev->PrtWidth() >= nRightGlue ||
244  pPrev->InHyphGrp() || pPrev->IsKernPortion() )
245  {
246  // The portion before the pRight cannot be moved
247  // because no Glue is remaining.
248  // We set the break condition:
249  pPrev = pLeft;
250  }
251  else
252  {
253  nRightGlue = nRightGlue - pPrev->PrtWidth();
254  // pPrev is moved behind pRight. For this the
255  // Glue value between pRight and pLeft gets balanced.
256  pRight->MoveGlue( pLeft, pPrev->PrtWidth() );
257  // Now fix the linking of our portions.
258  SwLinePortion *pPrevPrev = pPrev->FindPrevPortion( pLeft );
259  pPrevPrev->SetNextPortion( pRight );
260  pPrev->SetNextPortion( pRight->GetNextPortion() );
261  pRight->SetNextPortion( pPrev );
262  if ( pPrev->GetNextPortion() && pPrev->InTextGrp()
263  && pPrev->GetNextPortion()->IsHolePortion() )
264  {
265  SwHolePortion *pHolePor =
266  static_cast<SwHolePortion*>(pPrev->GetNextPortion());
267  if ( !pHolePor->GetNextPortion() ||
268  !pHolePor->GetNextPortion()->InFixMargGrp() )
269  {
270  pPrev->AddPrtWidth( pHolePor->GetBlankWidth() );
271  pPrev->SetLen(pPrev->GetLen() + TextFrameIndex(1));
272  pPrev->SetNextPortion( pHolePor->GetNextPortion() );
273  delete pHolePor;
274  }
275  }
276  pPrev = pPrevPrev;
277  }
278  }
279  }
280  // If no left Glue remains, we set the break condition.
281  pRight = pLeft ? pLeft : this;
282  }
283 }
284 
285 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void MoveAllGlue(SwGluePortion *pTarget)
Definition: porglue.hxx:80
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
SwTwips PrtWidth() const
Definition: porlin.hxx:83
void AdjFixWidth()
Definition: porglue.hxx:74
std::deque< sal_uInt16 > * GetpKanaComp() const
Definition: porlay.hxx:202
void dumpAsXml(xmlTextWriterPtr pWriter, const OUString &rText, TextFrameIndex &nOffset) const override
Definition: porglue.cxx:132
SwFont * GetFont()
Definition: inftxt.hxx:231
void SetPos(const Point &rNew)
Definition: inftxt.hxx:430
long Long
void dumpAsXmlAttributes(xmlTextWriterPtr writer, std::u16string_view rText, TextFrameIndex nOffset) const
Definition: porlin.cxx:330
void MoveGlue(SwGluePortion *pTarget, const tools::Long nPrtGlue)
Definition: porglue.cxx:109
aBuf
void SetLen(TextFrameIndex const nLen)
Definition: porlin.hxx:77
sal_uInt16 m_nFix
Definition: porglue.hxx:53
const sal_Unicode CH_BULLET
Definition: swfont.hxx:46
void DrawText(const OUString &rText, const SwLinePortion &rPor, TextFrameIndex nIdx=TextFrameIndex(0), TextFrameIndex nLen=TextFrameIndex(COMPLETE_STRING), const bool bKern=false) const
Definition: inftxt.hxx:747
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
SwPosSize GetTextSize(OutputDevice *pOut, const SwScriptInfo *pSI, const OUString &rText, TextFrameIndex nIdx, TextFrameIndex nLen) const
Definition: inftxt.cxx:382
sal_uInt16 sal_Unicode
bool InHyphGrp() const
Definition: porlin.hxx:105
sal_Unicode GetChar(TextFrameIndex const nPos) const
Definition: inftxt.hxx:240
tools::Long GetPrtGlue() const
Definition: porglue.hxx:70
int nCount
bool IsBlank(bool bHard=false) const
Definition: viewopt.hxx:225
bool InFixMargGrp() const
Definition: porlin.hxx:112
This portion represents a part of the paragraph string.
Definition: portxt.hxx:26
void Join(SwGluePortion *pVictim)
Definition: porglue.cxx:119
const SwViewOption & GetOpt() const
Definition: inftxt.hxx:238
void dumpAsXml(xmlTextWriterPtr pWriter, const OUString &rText, TextFrameIndex &nOffset) const override
Definition: porglue.cxx:160
virtual TextFrameIndex GetModelPositionForViewPoint(sal_uInt16 nOfst) const
the parameter is actually SwTwips apparently?
Definition: porlin.cxx:223
virtual bool GetExpText(const SwTextSizeInfo &rInf, OUString &rText) const override
Definition: porglue.cxx:52
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:78
void PrtWidth(SwTwips nNewWidth)
Definition: porlin.hxx:82
void SetWhichPor(const PortionType nNew)
Definition: porlin.hxx:98
bool IsFlyPortion() const
Definition: porlin.hxx:131
const sal_Unicode CH_BLANK
Definition: swfont.hxx:42
bool IsKernPortion() const
Definition: porlin.hxx:138
SwGluePortion(const sal_uInt16 nInitFixWidth)
Definition: porglue.cxx:28
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porglue.cxx:65
TextFrameIndex GetIdx() const
Definition: inftxt.hxx:272
sal_uInt16 GetBlankWidth() const
Definition: porfly.hxx:37
SwTwips Height() const
Definition: possiz.hxx:49
virtual SwPosSize GetTextSize(const SwTextSizeInfo &rInfo) const override
Definition: porglue.cxx:44
SwLinePortion * Cut(SwLinePortion *pVictim)
Definition: porlin.cxx:201
TextFrameIndex GetLen() const
Definition: porlin.hxx:76
bool InTabGrp() const
Definition: porlin.hxx:104
bool IsNoSymbol() const
Definition: inftxt.hxx:279
bool IsPaintBlank() const
Definition: swfont.hxx:261
bool IsHolePortion() const
Definition: porlin.hxx:132
SwTwips & GetAscent()
Definition: porlin.hxx:79
const Point & GetPos() const
Definition: inftxt.hxx:429
sal_uInt16 GetBlankWidth() const
Definition: portxt.hxx:68
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:51
SwTwips Width() const
Definition: possiz.hxx:51
For the text replacement and restoration of SwTextSizeInfo.
Definition: inftxt.hxx:674
bool OnWin() const
Definition: inftxt.hxx:192
TextFrameIndex GetLen() const
Definition: inftxt.hxx:274
void AddPrtWidth(const SwTwips nNew)
Definition: porlin.hxx:84
SwLinePortion * FindPrevPortion(const SwLinePortion *pRoot)
Definition: porlin.cxx:210
bool InTextGrp() const
Definition: porlin.hxx:102
void SetNextPortion(SwLinePortion *pNew)
Definition: porlin.hxx:78
struct _xmlTextWriter * xmlTextWriterPtr
Left
void SubPrtWidth(const SwTwips nNew)
Definition: porlin.hxx:85
void AdjustRight(const SwLineLayout *pCurr)
In the outer loop all portions are inspected - the GluePortions at the end are processed first...
Definition: porglue.cxx:188
sal_uInt16 GetFixWidth() const
Definition: porglue.hxx:37
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:74
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
void Height(tools::Long nNew)
Definition: swrect.hxx:193
virtual SwLinePortion * Insert(SwLinePortion *pPortion)
Definition: porlin.cxx:169
virtual TextFrameIndex GetModelPositionForViewPoint(sal_uInt16 nOfst) const override
the parameter is actually SwTwips apparently?
Definition: porglue.cxx:35
SwPosSize(const SwTwips nW=0, const SwTwips nH=0)
Definition: possiz.hxx:30
void SetAscent(const SwTwips nNewAsc)
Definition: porlin.hxx:81
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, char cFill= '\0')
sal_uInt16 m_nFixWidth
Definition: porglue.hxx:30
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo