/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: */ |