Coverage Report

Created: 2026-06-13 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwps/src/lib/WPSParagraph.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* libwps
3
 * Version: MPL 2.0 / LGPLv2.1+
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
 * Major Contributor(s):
10
 * Copyright (C) 2009, 2011 Alonso Laurent (alonso@loria.fr)
11
 * Copyright (C) 2006, 2007 Andrew Ziem
12
 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
13
 * Copyright (C) 2004 Marc Maurer (uwog@uwog.net)
14
 * Copyright (C) 2003-2005 William Lachance (william.lachance@sympatico.ca)
15
 *
16
 * For minor contributions see the git repository.
17
 *
18
 * Alternatively, the contents of this file may be used under the terms
19
 * of the GNU Lesser General Public License Version 2.1 or later
20
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
21
 * applicable instead of those above.
22
 *
23
 * For further information visit http://libwps.sourceforge.net
24
 */
25
#include <iomanip>
26
#include <sstream>
27
28
#include <librevenge/librevenge.h>
29
30
#include "libwps_internal.h"
31
32
#include "WPSContentListener.h"
33
#include "WPSList.h"
34
35
#include "WPSParagraph.h"
36
37
void WPSTabStop::addTo(librevenge::RVNGPropertyListVector &propList, double decalX) const
38
3.23M
{
39
3.23M
  librevenge::RVNGPropertyList tab;
40
41
  // type
42
3.23M
  switch (m_alignment)
43
3.23M
  {
44
15.6k
  case RIGHT:
45
15.6k
    tab.insert("style:type", "right");
46
15.6k
    break;
47
10.8k
  case CENTER:
48
10.8k
    tab.insert("style:type", "center");
49
10.8k
    break;
50
79.5k
  case DECIMAL:
51
79.5k
    tab.insert("style:type", "char");
52
79.5k
    tab.insert("style:char", "."); // Assume a decimal point for now
53
79.5k
    break;
54
0
  case BAR: // BAR is not handled in OOo
55
3.12M
  case LEFT:
56
3.12M
  default:
57
3.12M
    break;
58
3.23M
  }
59
60
  // leader character
61
3.23M
  if (m_leaderCharacter != 0x0000)
62
22.4k
  {
63
22.4k
    librevenge::RVNGString sLeader;
64
22.4k
    sLeader.sprintf("%c", m_leaderCharacter);
65
22.4k
    tab.insert("style:leader-text", sLeader);
66
22.4k
    tab.insert("style:leader-style", "solid");
67
22.4k
  }
68
69
  // position
70
3.23M
  double position = m_position+decalX;
71
3.23M
  if (position < 0.00005 && position > -0.00005)
72
238k
    position = 0.0;
73
3.23M
  tab.insert("style:position", position);
74
75
3.23M
  propList.append(tab);
76
3.23M
}
77
78
//! operator<<
79
std::ostream &operator<<(std::ostream &o, WPSTabStop const &tab)
80
0
{
81
0
  o << tab.m_position;
82
83
0
  switch (tab.m_alignment)
84
0
  {
85
0
  case WPSTabStop::LEFT:
86
0
    o << "L";
87
0
    break;
88
0
  case WPSTabStop::CENTER:
89
0
    o << "C";
90
0
    break;
91
0
  case WPSTabStop::RIGHT:
92
0
    o << "R";
93
0
    break;
94
0
  case WPSTabStop::DECIMAL:
95
0
    o << ":decimal";
96
0
    break;
97
0
  case WPSTabStop::BAR:
98
0
    o << ":bar";
99
0
    break;
100
0
  default:
101
0
    o << ":#type=" << int(tab.m_alignment);
102
0
    break;
103
0
  }
104
0
  if (tab.m_leaderCharacter != '\0')
105
0
    o << ":sep='"<< char(tab.m_leaderCharacter) << "'";
106
0
  return o;
107
0
}
108
109
//! operator<<
110
std::ostream &operator<<(std::ostream &o, WPSParagraph const &pp)
111
0
{
112
0
  if (pp.m_margins[0]<0||pp.m_margins[0]>0)
113
0
    o << "textIndent=" << pp.m_margins[0] << ",";
114
0
  if (pp.m_margins[1]<0||pp.m_margins[1]>0)
115
0
    o << "leftMarg=" << pp.m_margins[1] << ",";
116
0
  if (pp.m_margins[2]<0||pp.m_margins[2]>0)
117
0
    o << "rightMarg=" << pp.m_margins[2] << ",";
118
119
0
  if (pp.m_spacings[0] < 1.0 || pp.m_spacings[0] > 1.0)
120
0
  {
121
0
    o << "interLineSpacing=" << pp.m_spacings[0];
122
0
    if (pp.m_spacingsInterlineUnit==librevenge::RVNG_PERCENT)
123
0
      o << "%";
124
0
    else if (pp.m_spacingsInterlineUnit==librevenge::RVNG_POINT)
125
0
      o << "pt";
126
0
    else if (pp.m_spacingsInterlineUnit==librevenge::RVNG_INCH)
127
0
      o << "in";
128
0
    if (pp.m_spacingsInterlineType==WPSParagraph::AtLeast)
129
0
      o << "[atLeast]";
130
0
    o << ",";
131
0
  }
132
0
  if (pp.m_spacings[1]<0||pp.m_spacings[1]>0)
133
0
    o << "befSpacing=" << pp.m_spacings[1] << ",";
134
0
  if (pp.m_spacings[2]<0||pp.m_spacings[2]>0)
135
0
    o << "aftSpacing=" << pp.m_spacings[2] << ",";
136
137
0
  if (pp.m_breakStatus & libwps::NoBreakBit) o << "dontbreak,";
138
0
  if (pp.m_breakStatus & libwps::NoBreakWithNextBit) o << "dontbreakafter,";
139
140
0
  switch (pp.m_justify)
141
0
  {
142
0
  case libwps::JustificationLeft:
143
0
    break;
144
0
  case libwps::JustificationCenter:
145
0
    o << "just=centered, ";
146
0
    break;
147
0
  case libwps::JustificationRight:
148
0
    o << "just=right, ";
149
0
    break;
150
0
  case libwps::JustificationFull:
151
0
    o << "just=full, ";
152
0
    break;
153
0
  case libwps::JustificationFullAllLines:
154
0
    o << "just=fullAllLines, ";
155
0
    break;
156
0
  default:
157
0
    WPS_DEBUG_MSG(("WPSParagraph:operator<<: called with unknown justification\n"));
158
0
    o << "just=" << static_cast<unsigned>(pp.m_justify) << ", ";
159
0
    break;
160
0
  }
161
162
0
  if (pp.m_tabs.size())
163
0
  {
164
0
    o << "tabs=(";
165
0
    for (auto const &tab : pp.m_tabs)
166
0
      o << tab << ",";
167
0
    o << "),";
168
0
  }
169
0
  if (!pp.m_backgroundColor.isWhite())
170
0
    o << "backgroundColor=" << pp.m_backgroundColor << ",";
171
0
  if (pp.m_listLevelIndex >= 1)
172
0
    o << pp.m_listLevel << ":" << pp.m_listLevelIndex <<",";
173
174
0
  if (pp.m_border)
175
0
  {
176
0
    o << "bord(" << pp.m_borderStyle << ")";
177
0
    o << "=";
178
0
    if (pp.m_border&WPSBorder::TopBit) o << "T";
179
0
    if (pp.m_border&WPSBorder::BottomBit) o << "B";
180
0
    if (pp.m_border&WPSBorder::LeftBit) o << "L";
181
0
    if (pp.m_border&WPSBorder::RightBit) o << "R";
182
0
    o << ",";
183
0
  }
184
185
0
  if (!pp.m_extra.empty()) o << "extras=(" << pp.m_extra << ")";
186
0
  return o;
187
0
}
188
189
WPSParagraph::~WPSParagraph()
190
7.17M
{
191
7.17M
}
192
193
void WPSParagraph::addTo(librevenge::RVNGPropertyList &propList, bool inTable) const
194
2.05M
{
195
2.05M
  switch (m_justify)
196
2.05M
  {
197
2.02M
  case libwps::JustificationLeft:
198
    // doesn't require a paragraph prop - it is the default
199
2.02M
    propList.insert("fo:text-align", "left");
200
2.02M
    break;
201
12.1k
  case libwps::JustificationCenter:
202
12.1k
    propList.insert("fo:text-align", "center");
203
12.1k
    break;
204
13.1k
  case libwps::JustificationRight:
205
13.1k
    propList.insert("fo:text-align", "end");
206
13.1k
    break;
207
9.35k
  case libwps::JustificationFull:
208
9.35k
    propList.insert("fo:text-align", "justify");
209
9.35k
    break;
210
0
  case libwps::JustificationFullAllLines:
211
0
    propList.insert("fo:text-align", "justify");
212
0
    propList.insert("fo:text-align-last", "justify");
213
0
    break;
214
0
  default:
215
0
    break;
216
2.05M
  }
217
2.05M
  if (!inTable)
218
1.67M
  {
219
    // these properties are not appropriate when a table is opened..
220
1.67M
    propList.insert("fo:margin-left", m_listLevelIndex >= 1 ? m_listLevel.m_labelIndent : m_margins[1]);
221
1.67M
    propList.insert("fo:text-indent", m_margins[0]);
222
1.67M
    propList.insert("fo:margin-right", m_margins[2]);
223
1.67M
    if (!m_backgroundColor.isWhite())
224
5.55k
      propList.insert("fo:background-color", m_backgroundColor.str().c_str());
225
1.67M
    if (m_border && m_borderStyle.m_style != WPSBorder::None)
226
6.89k
    {
227
6.89k
      int border = m_border;
228
6.89k
      if (border == 0xF)
229
2.08k
        m_borderStyle.addTo(propList);
230
4.80k
      else
231
4.80k
      {
232
4.80k
        if (border & WPSBorder::LeftBit)
233
1.98k
          m_borderStyle.addTo(propList, "left");
234
4.80k
        if (border & WPSBorder::RightBit)
235
2.68k
          m_borderStyle.addTo(propList, "right");
236
4.80k
        if (border & WPSBorder::TopBit)
237
2.26k
          m_borderStyle.addTo(propList, "top");
238
4.80k
        if (border & WPSBorder::BottomBit)
239
2.20k
          m_borderStyle.addTo(propList, "bottom");
240
4.80k
      }
241
6.89k
    }
242
1.67M
  }
243
  // Note:
244
  // as we can not use percent, this may give a good approximation
245
2.05M
  propList.insert("fo:margin-top", (10.*m_spacings[1])/72., librevenge::RVNG_INCH);
246
2.05M
  propList.insert("fo:margin-bottom", (10.*m_spacings[2])/72., librevenge::RVNG_INCH);
247
2.05M
  switch (m_spacingsInterlineType)
248
2.05M
  {
249
2.00M
  case Fixed:
250
2.00M
    if (m_spacings[0] >= 0)
251
2.00M
      propList.insert("fo:line-height", m_spacings[0], m_spacingsInterlineUnit);
252
2.00M
    break;
253
52.3k
  case AtLeast:
254
52.3k
    if (m_spacings[0] <= 0 && m_spacings[0] >= 0)
255
3.33k
      break;
256
49.0k
    if (m_spacings[0] < 0)
257
6.25k
    {
258
6.25k
      static bool first = true;
259
6.25k
      if (first)
260
3
      {
261
3
        WPS_DEBUG_MSG(("WPSParagraph::addTo: interline spacing seems bad\n"));
262
3
        first = false;
263
3
      }
264
6.25k
    }
265
42.7k
    else if (m_spacingsInterlineUnit != librevenge::RVNG_PERCENT)
266
11.2k
      propList.insert("style:line-height-at-least", m_spacings[0], m_spacingsInterlineUnit);
267
31.4k
    else
268
31.4k
    {
269
31.4k
      propList.insert("style:line-height-at-least", m_spacings[0]*12.0, librevenge::RVNG_POINT);
270
31.4k
      static bool first = true;
271
31.4k
      if (first)
272
3
      {
273
3
        first = false;
274
3
        WPS_DEBUG_MSG(("WPSParagraph::addTo: assume height=12 to set line spacing at least with percent type\n"));
275
3
      }
276
31.4k
    }
277
49.0k
    break;
278
0
  default:
279
0
    WPS_DEBUG_MSG(("WPSParagraph::addTo: can not set line spacing type: %d\n",int(m_spacingsInterlineType)));
280
0
    break;
281
2.05M
  }
282
2.05M
  if (m_breakStatus & libwps::NoBreakBit)
283
3.00k
    propList.insert("fo:keep-together", "always");
284
2.05M
  if (m_breakStatus & libwps::NoBreakWithNextBit)
285
22.0k
    propList.insert("fo:keep-with-next", "always");
286
2.05M
  librevenge::RVNGPropertyListVector tabStops;
287
2.05M
  for (auto const &tab : m_tabs)
288
3.23M
    tab.addTo(tabStops, 0);
289
2.05M
  if (tabStops.count())
290
59.8k
    propList.insert("style:tab-stops", tabStops);
291
2.05M
}
292
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */