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
28SwGluePortion::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
52bool 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
65void 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);
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
109void 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
132void 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
160void 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: */
struct _xmlTextWriter * xmlTextWriterPtr
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 dumpAsXml(xmlTextWriterPtr pWriter, const OUString &rText, TextFrameIndex &nOffset) const override
Definition: porglue.cxx:160
sal_uInt16 m_nFix
Definition: porglue.hxx:53
sal_uInt16 GetBlankWidth() const
Definition: porfly.hxx:37
bool IsPaintBlank() const
Definition: swfont.hxx:261
virtual void Paint(const SwTextPaintInfo &rInf) const override
Definition: porglue.cxx:65
tools::Long GetPrtGlue() const
Definition: porglue.hxx:70
void dumpAsXml(xmlTextWriterPtr pWriter, const OUString &rText, TextFrameIndex &nOffset) const override
Definition: porglue.cxx:132
virtual TextFrameIndex GetModelPositionForViewPoint(sal_uInt16 nOfst) const override
the parameter is actually SwTwips apparently?
Definition: porglue.cxx:35
void MoveAllGlue(SwGluePortion *pTarget)
Definition: porglue.hxx:80
void Join(SwGluePortion *pVictim)
Definition: porglue.cxx:119
sal_uInt16 GetFixWidth() const
Definition: porglue.hxx:37
void MoveGlue(SwGluePortion *pTarget, const tools::Long nPrtGlue)
Definition: porglue.cxx:109
void AdjFixWidth()
Definition: porglue.hxx:74
virtual SwPosSize GetTextSize(const SwTextSizeInfo &rInfo) const override
Definition: porglue.cxx:44
sal_uInt16 m_nFixWidth
Definition: porglue.hxx:30
SwGluePortion(const sal_uInt16 nInitFixWidth)
Definition: porglue.cxx:28
virtual bool GetExpText(const SwTextSizeInfo &rInf, OUString &rText) const override
Definition: porglue.cxx:52
sal_uInt16 GetBlankWidth() const
Definition: portxt.hxx:68
Collection of SwLinePortion instances, representing one line of text.
Definition: porlay.hxx:79
std::deque< sal_uInt16 > * GetpKanaComp() const
Definition: porlay.hxx:202
Base class for anything that can be part of a line in the Writer layout.
Definition: porlin.hxx:52
void PrtWidth(SwTwips nNewWidth)
Definition: porlin.hxx:83
void dumpAsXmlAttributes(xmlTextWriterPtr writer, std::u16string_view rText, TextFrameIndex nOffset) const
Definition: porlin.cxx:330
bool InTextGrp() const
Definition: porlin.hxx:105
virtual TextFrameIndex GetModelPositionForViewPoint(sal_uInt16 nOfst) const
the parameter is actually SwTwips apparently?
Definition: porlin.cxx:223
SwLinePortion * GetNextPortion() const
Definition: porlin.hxx:75
void SetAscent(const SwTwips nNewAsc)
Definition: porlin.hxx:82
void SetNextPortion(SwLinePortion *pNew)
Definition: porlin.hxx:79
SwLinePortion * Cut(SwLinePortion *pVictim)
Definition: porlin.cxx:201
TextFrameIndex GetLen() const
Definition: porlin.hxx:77
bool IsKernPortion() const
Definition: porlin.hxx:141
void SubPrtWidth(const SwTwips nNew)
Definition: porlin.hxx:86
bool InHyphGrp() const
Definition: porlin.hxx:108
void AddPrtWidth(const SwTwips nNew)
Definition: porlin.hxx:85
SwTwips & GetAscent()
Definition: porlin.hxx:80
bool InTabGrp() const
Definition: porlin.hxx:107
SwLinePortion * FindPrevPortion(const SwLinePortion *pRoot)
Definition: porlin.cxx:210
void SetLen(TextFrameIndex const nLen)
Definition: porlin.hxx:78
bool IsHolePortion() const
Definition: porlin.hxx:135
bool IsFlyPortion() const
Definition: porlin.hxx:134
SwTwips PrtWidth() const
Definition: porlin.hxx:84
void SetWhichPor(const PortionType nNew)
Definition: porlin.hxx:101
bool InFixMargGrp() const
Definition: porlin.hxx:115
virtual SwLinePortion * Insert(SwLinePortion *pPortion)
Definition: porlin.cxx:169
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
SwTwips Width() const
Definition: possiz.hxx:51
SwPosSize(const SwTwips nW=0, const SwTwips nH=0)
Definition: possiz.hxx:30
SwTwips Height() const
Definition: possiz.hxx:49
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
void Height(tools::Long nNew)
Definition: swrect.hxx:193
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:751
void SetPos(const Point &rNew)
Definition: inftxt.hxx:433
const Point & GetPos() const
Definition: inftxt.hxx:432
This portion represents a part of the paragraph string.
Definition: portxt.hxx:27
const SwViewOption & GetOpt() const
Definition: inftxt.hxx:239
SwFont * GetFont()
Definition: inftxt.hxx:232
bool OnWin() const
Definition: inftxt.hxx:193
SwPosSize GetTextSize(OutputDevice *pOut, const SwScriptInfo *pSI, const OUString &rText, TextFrameIndex nIdx, TextFrameIndex nLen) const
Definition: inftxt.cxx:385
sal_Unicode GetChar(TextFrameIndex const nPos) const
Definition: inftxt.hxx:241
TextFrameIndex GetLen() const
Definition: inftxt.hxx:275
bool IsNoSymbol() const
Definition: inftxt.hxx:282
TextFrameIndex GetIdx() const
Definition: inftxt.hxx:273
For the text replacement and restoration of SwTextSizeInfo.
Definition: inftxt.hxx:678
bool IsBlank(bool bHard=false) const
Definition: viewopt.hxx:295
int nCount
aBuf
OStringBuffer & padToLength(OStringBuffer &rBuffer, sal_Int32 nLength, char cFill='\0')
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
long Long
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
const sal_Unicode CH_BLANK
Definition: swfont.hxx:42
const sal_Unicode CH_BULLET
Definition: swfont.hxx:46
Left
sal_uInt16 sal_Unicode