/src/libwps/src/lib/QuattroDosChart.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) 2006, 2007 Andrew Ziem |
11 | | * Copyright (C) 2004 Marc Maurer (uwog@uwog.net) |
12 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
13 | | * |
14 | | * For minor contributions see the git repository. |
15 | | * |
16 | | * Alternatively, the contents of this file may be used under the terms |
17 | | * of the GNU Lesser General Public License Version 2.1 or later |
18 | | * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are |
19 | | * applicable instead of those above. |
20 | | */ |
21 | | |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | |
25 | | #include <cmath> |
26 | | #include <sstream> |
27 | | #include <limits> |
28 | | #include <map> |
29 | | #include <stack> |
30 | | |
31 | | #include <librevenge-stream/librevenge-stream.h> |
32 | | |
33 | | #include "libwps_internal.h" |
34 | | #include "libwps_tools_win.h" |
35 | | |
36 | | #include "WKSChart.h" |
37 | | #include "WKSContentListener.h" |
38 | | #include "WPSEntry.h" |
39 | | #include "WPSFont.h" |
40 | | #include "WPSPosition.h" |
41 | | |
42 | | #include "QuattroDos.h" |
43 | | |
44 | | #include "QuattroDosChart.h" |
45 | | |
46 | | namespace QuattroDosChartInternal |
47 | | { |
48 | | |
49 | | /////////////////////////////////////////////////////////////////// |
50 | | //! the chart of a Quattro Pro Dos |
51 | | |
52 | | class Chart final : public WKSChart |
53 | | { |
54 | | public: |
55 | | //! constructor |
56 | | explicit Chart(QuattroDosChart &parser, RVNGInputStreamPtr const &input) |
57 | 60.3k | : WKSChart() |
58 | 60.3k | , m_spreadsheetId(-1) |
59 | 60.3k | , m_parser(parser) |
60 | 60.3k | , m_input(input) |
61 | 60.3k | { |
62 | 60.3k | } |
63 | | //! send the zone content (called when the zone is of text type) |
64 | | void sendContent(TextZone const &zone, WPSListenerPtr &listener) const final; |
65 | | |
66 | | //! the chart range |
67 | | Position m_ranges[2]; |
68 | | //! the sheet id |
69 | | int m_spreadsheetId; |
70 | | protected: |
71 | | //! the parser |
72 | | QuattroDosChart &m_parser; |
73 | | //! the input |
74 | | RVNGInputStreamPtr m_input; |
75 | | }; |
76 | | |
77 | | void Chart::sendContent(TextZone const &zone, WPSListenerPtr &listener) const |
78 | 750 | { |
79 | 750 | if (!listener.get()) |
80 | 0 | { |
81 | 0 | WPS_DEBUG_MSG(("QuattroDosChartInternal::Chart::sendContent: no listener\n")); |
82 | 0 | return; |
83 | 0 | } |
84 | 750 | long pos = m_input->tell(); |
85 | 750 | listener->setFont(zone.m_font); |
86 | 750 | bool sendText=false; |
87 | 750 | for (auto const &e : zone.m_textEntryList) |
88 | 750 | { |
89 | 750 | if (!e.valid()) continue; |
90 | 750 | if (sendText) listener->insertEOL(true); |
91 | 750 | m_parser.sendText(e); |
92 | 750 | sendText=true; |
93 | 750 | } |
94 | 750 | m_input->seek(pos, librevenge::RVNG_SEEK_SET); |
95 | 750 | } |
96 | | |
97 | | //! the state of QuattroDosChart |
98 | | struct State |
99 | | { |
100 | | //! constructor |
101 | | State() |
102 | 15.4k | : m_eof(-1) |
103 | 15.4k | , m_version(-1) |
104 | 15.4k | , m_chartType(-1) |
105 | 15.4k | , m_idToChartMap() |
106 | 15.4k | { |
107 | 15.4k | } |
108 | | //! returns the pattern corresponding to a pattern id between 0 and 15 |
109 | | static bool getPattern(int id, WPSGraphicStyle::Pattern &pattern); |
110 | | |
111 | | //! the last file position |
112 | | long m_eof; |
113 | | //! the file version |
114 | | int m_version; |
115 | | //! the chart type |
116 | | int m_chartType; |
117 | | //! map sheet id to chart |
118 | | std::multimap<int, std::shared_ptr<Chart> > m_idToChartMap; |
119 | | |
120 | | }; |
121 | | |
122 | | bool State::getPattern(int id, WPSGraphicStyle::Pattern &pat) |
123 | 263k | { |
124 | 263k | if (id<0 || id>15) |
125 | 51.2k | { |
126 | 51.2k | WPS_DEBUG_MSG(("QuattroDosChartInternal::State::getPattern(): unknown pattern id: %d\n",id)); |
127 | 51.2k | return false; |
128 | 51.2k | } |
129 | 212k | static const uint16_t patterns[]= |
130 | 212k | { |
131 | 212k | 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0xff00, 0x00ff, 0xff00, 0xeedd, 0xbb77, 0xeedd, 0xbb77, // 0-3 |
132 | 212k | 0x3366, 0xcc99, 0x3366, 0xcc99, 0x8844, 0x2211, 0x8844, 0x2211, 0x99cc, 0x6633, 0x99cc, 0x6633, 0xff10, 0x1010, 0xff10, 0xff10, // 4-7 |
133 | 212k | 0xbf7f, 0xfefc, 0x7bb7, 0xcfdf, 0xaa55, 0xaa55, 0xaa55, 0xaa55, 0x7fff, 0xffff, 0xf7ff, 0xffff, 0x77ff, 0xddff, 0x77ff, 0xddff, // 8-9 |
134 | 212k | 0x990f, 0x050f, 0x99f0, 0x50f0, 0x0101, 0x01ff, 0x1010, 0x10ff, 0xbf7f, 0xfefc, 0x7bb7, 0xcfdf, 0xf77f, 0xbfdf, 0xeffe, 0xfdfb // 12-15 |
135 | 212k | }; |
136 | 212k | pat.m_dim=Vec2i(8,8); |
137 | 212k | uint16_t const *ptr=&patterns[4*id]; |
138 | 212k | pat.m_data.resize(8); |
139 | 1.06M | for (size_t i=0; i < 8; i+=2) |
140 | 851k | { |
141 | 851k | uint16_t val=*(ptr++); |
142 | 851k | pat.m_data[i]=static_cast<unsigned char>((val>>8) & 0xFF); |
143 | 851k | pat.m_data[i+1]=static_cast<unsigned char>(val & 0xFF); |
144 | 851k | } |
145 | 212k | return true; |
146 | 263k | } |
147 | | } |
148 | | |
149 | | // constructor, destructor |
150 | | QuattroDosChart::QuattroDosChart(QuattroDosParser &parser) |
151 | 15.4k | : m_input(parser.getInput()) |
152 | 15.4k | , m_listener() |
153 | 15.4k | , m_mainParser(parser) |
154 | 15.4k | , m_state(new QuattroDosChartInternal::State) |
155 | 15.4k | , m_asciiFile(parser.ascii()) |
156 | 15.4k | { |
157 | 15.4k | } |
158 | | |
159 | | QuattroDosChart::~QuattroDosChart() |
160 | 15.4k | { |
161 | 15.4k | } |
162 | | |
163 | | int QuattroDosChart::version() const |
164 | 108k | { |
165 | 108k | if (m_state->m_version<0) |
166 | 4.10k | m_state->m_version=m_mainParser.version(); |
167 | 108k | return m_state->m_version; |
168 | 108k | } |
169 | | |
170 | | bool QuattroDosChart::checkFilePosition(long pos) |
171 | 0 | { |
172 | 0 | if (m_state->m_eof < 0) |
173 | 0 | { |
174 | 0 | long actPos = m_input->tell(); |
175 | 0 | m_input->seek(0, librevenge::RVNG_SEEK_END); |
176 | 0 | m_state->m_eof=m_input->tell(); |
177 | 0 | m_input->seek(actPos, librevenge::RVNG_SEEK_SET); |
178 | 0 | } |
179 | 0 | return pos <= m_state->m_eof; |
180 | 0 | } |
181 | | |
182 | | int QuattroDosChart::getNumSpreadsheets() const |
183 | 7.11k | { |
184 | 7.11k | auto it = m_state->m_idToChartMap.end(); |
185 | 7.11k | if (it==m_state->m_idToChartMap.begin()) |
186 | 5.29k | return 0; |
187 | 1.82k | --it; |
188 | 1.82k | if (it->first>255) |
189 | 12 | { |
190 | 12 | WPS_DEBUG_MSG(("QuattroDosChart::getNumSpreadsheets: the number of spreadsheets seems to big: %d\n", it->first)); |
191 | 12 | return 256; |
192 | 12 | } |
193 | 1.80k | return it->first+1; |
194 | 1.82k | } |
195 | | |
196 | | void QuattroDosChart::getChartPositionMap(int sheetId, std::map<Vec2i, Vec2i> &cellList) const |
197 | 83.7k | { |
198 | 83.7k | cellList.clear(); |
199 | 83.7k | auto it = m_state->m_idToChartMap.lower_bound(sheetId); |
200 | 116k | while (it!=m_state->m_idToChartMap.end() && it->first==sheetId) |
201 | 33.1k | { |
202 | 33.1k | if (it->second) |
203 | 33.1k | cellList[it->second->m_ranges[0].m_pos]=it->second->m_ranges[1].m_pos; |
204 | 33.1k | ++it; |
205 | 33.1k | } |
206 | 83.7k | } |
207 | | |
208 | | bool QuattroDosChart::updateSpreadsheetNames(QuattroDosChartInternal::Chart &chart) |
209 | 3.83k | { |
210 | 3.83k | for (auto &range : chart.m_ranges) |
211 | 7.66k | { |
212 | 7.66k | if (range.m_sheetId>=0) |
213 | 7.66k | range.m_sheetName = m_mainParser.getSheetName(range.m_sheetId); |
214 | 7.66k | } |
215 | 3.83k | for (auto &it : chart.getIdSerieMap()) |
216 | 13.8k | { |
217 | 13.8k | auto &serie=const_cast<WKSChart::Serie &>(it.second); |
218 | 13.8k | for (auto &range : serie.m_ranges) |
219 | 27.6k | { |
220 | 27.6k | if (range.m_sheetId>=0) |
221 | 27.6k | range.m_sheetName = m_mainParser.getSheetName(range.m_sheetId); |
222 | 27.6k | } |
223 | 13.8k | for (auto &range : serie.m_labelRanges) |
224 | 27.6k | { |
225 | 27.6k | if (range.m_sheetId>=0) |
226 | 15.5k | range.m_sheetName = m_mainParser.getSheetName(range.m_sheetId); |
227 | 27.6k | } |
228 | 13.8k | } |
229 | 3.83k | for (auto &range : chart.getAxis(0).m_labelRanges) |
230 | 7.66k | { |
231 | 7.66k | if (range.m_sheetId>=0) |
232 | 4.42k | range.m_sheetName = m_mainParser.getSheetName(range.m_sheetId); |
233 | 7.66k | } |
234 | 3.83k | return true; |
235 | 3.83k | } |
236 | | |
237 | | bool QuattroDosChart::sendChart(int sheetId, Vec2i const &cell, Vec2f const &chartSize) |
238 | 3.83k | { |
239 | 3.83k | if (m_listener.get() == nullptr) |
240 | 0 | { |
241 | 0 | WPS_DEBUG_MSG(("QuattroDosChart::sendChart: I can not find the listener\n")); |
242 | 0 | return false; |
243 | 0 | } |
244 | 3.83k | auto it = m_state->m_idToChartMap.lower_bound(sheetId); |
245 | 24.5k | while (it!=m_state->m_idToChartMap.end() && it->first==sheetId) |
246 | 24.5k | { |
247 | 24.5k | if (it->second && it->second->m_ranges[0].m_pos==cell) |
248 | 3.83k | { |
249 | 3.83k | updateSpreadsheetNames(*it->second); |
250 | 3.83k | Vec2f size(chartSize[0]>0 ? chartSize[0] : 100, chartSize[1]>0 ? chartSize[1] : 100); |
251 | 3.83k | WPSPosition pos(Vec2f(0,0), size, librevenge::RVNG_POINT); |
252 | 3.83k | pos.m_anchorTo = WPSPosition::Cell; |
253 | 3.83k | auto endRange=it->second->m_ranges[1]; |
254 | 3.83k | endRange.m_pos += Vec2i(1,1); |
255 | 3.83k | pos.m_anchorCellName = endRange.getCellName(); |
256 | | // the chart is in fact a 1024*7?? windows scaled back on the chosen cells |
257 | 3.83k | it->second->m_dimension=Vec2f(1024,700); |
258 | 3.83k | m_listener->insertChart(pos, *it->second); |
259 | 3.83k | return true; |
260 | 3.83k | } |
261 | 20.7k | ++it; |
262 | 20.7k | } |
263 | 0 | WPS_DEBUG_MSG(("QuattroDosChart::sendChart: can not find chart %dx%d[%d]\n", cell[0], cell[1], sheetId)); |
264 | 0 | return false; |
265 | 3.83k | } |
266 | | |
267 | | bool QuattroDosChart::sendText(WPSEntry const &entry) |
268 | 750 | { |
269 | 750 | if (m_listener.get() == nullptr) |
270 | 0 | { |
271 | 0 | WPS_DEBUG_MSG(("QuattroDosChart::sendText: I can not find the listener\n")); |
272 | 0 | return false; |
273 | 0 | } |
274 | 750 | if (!entry.valid()) |
275 | 0 | return true; |
276 | 750 | m_input->seek(entry.begin(), librevenge::RVNG_SEEK_SET); |
277 | 750 | std::string text; |
278 | 12.3k | for (long i=0; i<entry.length(); ++i) |
279 | 11.6k | { |
280 | 11.6k | auto c = char(libwps::readU8(m_input)); |
281 | 11.6k | if (c == '\0') continue; |
282 | 7.58k | text.push_back(c); |
283 | 7.58k | } |
284 | 750 | if (!text.empty()) |
285 | 750 | m_listener->insertUnicodeString(libwps_tools_win::Font::unicodeString(text, m_mainParser.getDefaultFontType())); |
286 | 750 | return true; |
287 | 750 | } |
288 | | //////////////////////////////////////////////////////////// |
289 | | // low level |
290 | | |
291 | | //////////////////////////////////////////////////////////// |
292 | | // general |
293 | | //////////////////////////////////////////////////////////// |
294 | | bool QuattroDosChart::readChartSetType() |
295 | 1.45k | { |
296 | | |
297 | 1.45k | long pos = m_input->tell(); |
298 | 1.45k | auto type = long(libwps::readU16(m_input)); |
299 | 1.45k | if (type != 0xb8 && type != 0xca) |
300 | 0 | { |
301 | 0 | WPS_DEBUG_MSG(("QuattroDosChart::readChartSetType: not a chart definition\n")); |
302 | 0 | return false; |
303 | 0 | } |
304 | 1.45k | libwps::DebugStream f; |
305 | 1.45k | f << "Entries(" << (type==0xb8 ? "Chart3d" : "ChartBubble") << "):"; |
306 | 1.45k | auto sz = long(libwps::readU16(m_input)); |
307 | 1.45k | if (sz!=1) |
308 | 849 | { |
309 | 849 | WPS_DEBUG_MSG(("QuattroDosChart::readChartSetType: find unexpected size\n")); |
310 | 849 | f << "###"; |
311 | 849 | ascii().addPos(pos); |
312 | 849 | ascii().addNote(f.str().c_str()); |
313 | 849 | m_input->seek(sz, librevenge::RVNG_SEEK_CUR); |
314 | 849 | return true; |
315 | 849 | } |
316 | 608 | m_state->m_chartType=int(libwps::readU8(m_input)); |
317 | 608 | f << "type=" << m_state->m_chartType << ","; |
318 | 608 | ascii().addPos(pos); |
319 | 608 | ascii().addNote(f.str().c_str()); |
320 | 608 | return true; |
321 | 1.45k | } |
322 | | |
323 | | bool QuattroDosChart::readChartName() |
324 | 597 | { |
325 | | |
326 | 597 | long pos = m_input->tell(); |
327 | 597 | auto type = long(libwps::readU16(m_input)); |
328 | 597 | if (type != 0xb9) |
329 | 0 | { |
330 | 0 | WPS_DEBUG_MSG(("QuattroDosChart::readChartName: not a chart definition\n")); |
331 | 0 | return false; |
332 | 0 | } |
333 | 597 | libwps::DebugStream f; |
334 | 597 | f << "Entries(ChartName):"; |
335 | 597 | auto sz = long(libwps::readU16(m_input)); |
336 | 597 | if (sz!=0x10) |
337 | 310 | { |
338 | 310 | WPS_DEBUG_MSG(("QuattroDosChart::readChartName: find unexpected size\n")); |
339 | 310 | f << "###"; |
340 | 310 | ascii().addPos(pos); |
341 | 310 | ascii().addNote(f.str().c_str()); |
342 | 310 | m_input->seek(sz, librevenge::RVNG_SEEK_CUR); |
343 | 310 | return true; |
344 | 310 | } |
345 | 287 | librevenge::RVNGString name(""); |
346 | 287 | if (!m_mainParser.readPString(name,15)) |
347 | 136 | f << "##sSz,"; |
348 | 151 | else if (!name.empty()) |
349 | 60 | f << name.cstr() << ','; |
350 | 287 | ascii().addPos(pos); |
351 | 287 | ascii().addNote(f.str().c_str()); |
352 | 287 | return true; |
353 | 597 | } |
354 | | |
355 | | bool QuattroDosChart::readChart() |
356 | 108k | { |
357 | 108k | int vers=version(); |
358 | 108k | libwps::DebugStream f; |
359 | | |
360 | 108k | long pos = m_input->tell(); |
361 | 108k | auto type = long(libwps::readU16(m_input)); |
362 | 108k | if (type != 0x2D && type != 0x2e) |
363 | 0 | { |
364 | 0 | WPS_DEBUG_MSG(("QuattroDosChart::readChart: not a chart definition\n")); |
365 | 0 | return false; |
366 | 0 | } |
367 | 108k | auto sz = long(libwps::readU16(m_input)); |
368 | 108k | int normalSz = 0x2ca; |
369 | 108k | if (type == 0x2e) normalSz += 0x10; |
370 | 108k | if (vers>=2) normalSz+=2*26+4; |
371 | 108k | if (sz < normalSz) |
372 | 48.6k | { |
373 | 48.6k | WPS_DEBUG_MSG(("QuattroDosChart::readChart: chart definition too short\n")); |
374 | 48.6k | ascii().addPos(pos); |
375 | 48.6k | ascii().addNote("Entries(ChartDef):###"); |
376 | 48.6k | return true; |
377 | 48.6k | } |
378 | | |
379 | 60.3k | f << "Entries(ChartDef):"; |
380 | 60.3k | std::shared_ptr<QuattroDosChartInternal::Chart> chart(new QuattroDosChartInternal::Chart(*this, m_input)); |
381 | 60.3k | if (type == 0x2e) |
382 | 441 | { |
383 | 441 | long actPos = m_input->tell(); |
384 | 441 | librevenge::RVNGString name(""); |
385 | 441 | if (!m_mainParser.readPString(name,15)) |
386 | 169 | f << "##sSz,"; |
387 | 272 | else if (!name.empty()) |
388 | 73 | { |
389 | 73 | chart->m_name=name; |
390 | 73 | f << "title=" << name.cstr() << ','; |
391 | 73 | } |
392 | 441 | m_input->seek(actPos+16, librevenge::RVNG_SEEK_SET); |
393 | 441 | } |
394 | 60.3k | bool hasLegend=false; |
395 | 844k | for (int i = 0; i < 13; i++) // 0: X-serie, 1-6: data[series%d], 7-12:label serie%d |
396 | 783k | { |
397 | 783k | WKSChart::Position ranges[2]; |
398 | 783k | for (auto &range : ranges) |
399 | 1.56M | { |
400 | 1.56M | int dim[3]; |
401 | 5.14M | for (int d=0; d<(vers>=2 ? 3 : 2); ++d) dim[d] = int(libwps::read16(m_input)); |
402 | 1.56M | if (dim[0]==-1) |
403 | 27.3k | continue; |
404 | 1.54M | range = WKSChart::Position(Vec2i(dim[0],dim[1])); |
405 | 1.54M | range.m_sheetId=vers<2 ? 0 : dim[2]; |
406 | 1.54M | } |
407 | 783k | if (ranges[0].valid(ranges[1])) |
408 | 550k | { |
409 | 550k | f << "z" << i << "=" << ranges[0] << ":" << ranges[1] << ","; |
410 | 550k | if (i==0) |
411 | 47.0k | { |
412 | 47.0k | auto &axis=chart->getAxis(0); |
413 | 47.0k | axis.m_labelRanges[0]=ranges[0]; |
414 | 47.0k | axis.m_labelRanges[1]=ranges[1]; |
415 | 47.0k | } |
416 | 503k | else if (i<=6) |
417 | 263k | { |
418 | 263k | auto *serie=chart->getSerie(i-1, true); |
419 | 263k | serie->m_ranges[0]=ranges[0]; |
420 | 263k | serie->m_ranges[1]=ranges[1]; |
421 | 263k | } |
422 | 239k | else |
423 | 239k | { |
424 | 239k | auto *serie=chart->getSerie(i-7, false); |
425 | 239k | if (serie) |
426 | 189k | { |
427 | 189k | serie->m_labelRanges[0]=ranges[0]; |
428 | 189k | serie->m_labelRanges[1]=ranges[1]; |
429 | 189k | } |
430 | 239k | if (ranges[0]!=ranges[1]) |
431 | 62.5k | { |
432 | 62.5k | WPS_DEBUG_MSG(("QuattroDosChart::readChart: unexpected label ranges for %d\n", i)); |
433 | 62.5k | } |
434 | 239k | } |
435 | 550k | } |
436 | 783k | } |
437 | 60.3k | ascii().addPos(pos); |
438 | 60.3k | ascii().addNote(f.str().c_str()); |
439 | 60.3k | char const *axisNames[]= {"X", "Y", "Y2"}; |
440 | 60.3k | pos=m_input->tell(); |
441 | 60.3k | f.str(""); |
442 | 60.3k | f << "ChartDef-A:"; // GraphDef0 |
443 | 60.3k | auto chartType=int(libwps::readU8(m_input)); |
444 | 60.3k | if (m_state->m_chartType>=0) |
445 | 37 | { |
446 | 37 | chartType=m_state->m_chartType; |
447 | 37 | m_state->m_chartType=-1; |
448 | 37 | } |
449 | 60.3k | WKSChart::Serie::Type serieType=WKSChart::Serie::S_Bar; |
450 | 60.3k | switch (chartType) |
451 | 60.3k | { |
452 | 48.6k | case 0: // XY |
453 | 48.6k | serieType=WKSChart::Serie::S_Scatter; |
454 | 48.6k | break; |
455 | 218 | case 1: // basic column |
456 | 218 | break; |
457 | 2.41k | case 2: // pie |
458 | 2.55k | case 6: // column (like circle) |
459 | 2.55k | serieType=WKSChart::Serie::S_Circle; |
460 | 2.55k | break; |
461 | 397 | case 3: // area stacked |
462 | 397 | serieType=WKSChart::Serie::S_Area; |
463 | 397 | chart->m_dataStacked=true; |
464 | 397 | break; |
465 | 219 | case 4: // line |
466 | 219 | serieType=WKSChart::Serie::S_Line; |
467 | 219 | break; |
468 | 132 | case 5: // basic column |
469 | 132 | chart->m_dataStacked=true; |
470 | 132 | break; |
471 | 92 | case 7: // min-max |
472 | 92 | serieType=WKSChart::Serie::S_Stock; |
473 | 92 | break; |
474 | 123 | case 8: // basic bar |
475 | 123 | chart->m_dataVertical=true; |
476 | 123 | break; |
477 | 151 | case 9: // bubble |
478 | 151 | serieType=WKSChart::Serie::S_Bubble; |
479 | 151 | break; |
480 | 127 | case 10: // 3D-bar |
481 | 366 | case 12: // 3D-bar tie together |
482 | 366 | chart->m_is3D=true; |
483 | 366 | break; |
484 | 245 | case 11: // 3D-ribbon |
485 | 245 | chart->m_is3D=true; |
486 | 245 | serieType=WKSChart::Serie::S_Line; |
487 | 245 | break; |
488 | 277 | case 13: |
489 | 277 | chart->m_is3D=true; |
490 | 277 | serieType=WKSChart::Serie::S_Area; |
491 | 277 | chart->m_dataStacked=true; |
492 | 277 | break; |
493 | 6.86k | default: |
494 | 6.86k | WPS_DEBUG_MSG(("QuattroDosChart::readChart: unknown chart type\n")); |
495 | 6.86k | f << "###"; |
496 | 60.3k | } |
497 | 60.3k | if (chartType) f << "type=" << chartType << ","; |
498 | | |
499 | 60.3k | chart->m_type=serieType; |
500 | 60.3k | if (chartType==3 || chartType==5) chart->m_dataStacked=true; |
501 | 60.3k | if (chartType==8) chart->m_dataVertical=true; |
502 | 60.3k | auto pointType = serieType==WKSChart::Serie::S_Scatter ? WKSChart::Serie::P_Automatic : WKSChart::Serie::P_None; |
503 | 422k | for (int i=0; i<6; ++i) |
504 | 361k | { |
505 | 361k | auto *serie=chart->getSerie(i, false); |
506 | 361k | if (!serie) continue; |
507 | 263k | serie->m_type=serieType; |
508 | 263k | serie->m_pointType=pointType; |
509 | 263k | serie->m_style.m_lineWidth=1; |
510 | 263k | } |
511 | 60.3k | auto val=int(libwps::readU8(m_input)); |
512 | 60.3k | f << "grid="; |
513 | 60.3k | if (val&1) |
514 | 6.98k | f << "X"; |
515 | 53.3k | else |
516 | 53.3k | chart->getAxis(0).m_showGrid=false; |
517 | 60.3k | if (val&2) |
518 | 6.55k | f << "Y"; |
519 | 53.7k | else |
520 | 53.7k | chart->getAxis(1).m_showGrid=false; |
521 | 60.3k | if (val&0xFC) |
522 | 7.32k | f << "[##" << std::hex << (val&0xFC) << std::dec; |
523 | 60.3k | f << ","; |
524 | 60.3k | val=int(libwps::readU8(m_input)); |
525 | | // bool useColor=val!=0; USEME |
526 | 60.3k | if (val==0) |
527 | 49.0k | f << "use[color]=no,"; |
528 | 11.2k | else if (val!=0xFF) |
529 | 10.3k | f << "use[color]=###"<< val << ","; |
530 | 60.3k | f << "unkn=["; |
531 | 422k | for (int i=0; i<6; ++i) |
532 | 361k | { |
533 | 361k | val=int(libwps::readU8(m_input)); |
534 | 361k | if (val) |
535 | 63.1k | f << val << ","; |
536 | 298k | else |
537 | 298k | f << "_,"; |
538 | 361k | } |
539 | 60.3k | f << "],"; |
540 | 60.3k | f << "align[serie]=["; |
541 | 422k | for (int i=0; i<6; ++i) // serie, label position, safe to ignore ? |
542 | 361k | { |
543 | 361k | val=int(libwps::readU8(m_input)); |
544 | 361k | if (val<6) |
545 | 316k | { |
546 | 316k | char const *wh[]= {"center", "left", "above", "right", "below", "none"}; |
547 | 316k | f << wh[val] << ","; |
548 | 316k | } |
549 | 45.5k | else |
550 | 45.5k | f << "##" << val << ","; |
551 | 361k | } |
552 | 60.3k | f << "],"; |
553 | 180k | for (int i=0; i<2; ++i) |
554 | 120k | { |
555 | 120k | auto &axis=chart->getAxis(i); |
556 | 120k | f << "axis" << axisNames[i] << "=["; |
557 | 120k | val=int(libwps::readU8(m_input)); |
558 | 120k | if (val==1) |
559 | 1.29k | { |
560 | 1.29k | f << "scale[manual],"; |
561 | 1.29k | axis.m_automaticScaling=false; |
562 | 1.29k | } |
563 | 119k | else if (val) |
564 | 19.3k | f << "scale=##" << val << ","; |
565 | 361k | for (int j=0; j<2; ++j) |
566 | 241k | { |
567 | 241k | long actPos=m_input->tell(); |
568 | 241k | long double value; |
569 | 241k | bool isNaN; |
570 | 241k | if (!libwps::readDouble8(m_input, value, isNaN)) |
571 | 32.8k | { |
572 | 32.8k | m_input->seek(actPos+8, librevenge::RVNG_SEEK_SET); |
573 | 32.8k | f << "##value,"; |
574 | 32.8k | } |
575 | 208k | else |
576 | 208k | { |
577 | 208k | if (value<0 || value>0) |
578 | 57.0k | f << (j==0 ? "low" : "high") << "=" << value << ","; |
579 | 208k | axis.m_scaling[j]=float(value); |
580 | 208k | } |
581 | 241k | } |
582 | 120k | f << "],"; |
583 | 120k | } |
584 | 60.3k | m_input->seek(pos+49, librevenge::RVNG_SEEK_SET); |
585 | 60.3k | ascii().addPos(pos); |
586 | 60.3k | ascii().addNote(f.str().c_str()); |
587 | 60.3k | pos=m_input->tell(); |
588 | 60.3k | f.str(""); |
589 | 60.3k | f << "ChartDef-names:"; |
590 | 663k | for (int i = 0; i < 10; i++) |
591 | 603k | { |
592 | | // ok to find string before i < 6 |
593 | | // checkme after |
594 | 603k | long actPos = m_input->tell(); |
595 | 603k | int dataSz = i < 4 ? 40 : 20; |
596 | 603k | librevenge::RVNGString name(""); |
597 | 603k | if (!m_mainParser.readPString(name,dataSz-1)) |
598 | 50.0k | f << "##sSz,"; |
599 | 603k | if (name.empty()) |
600 | 588k | { |
601 | 588k | m_input->seek(actPos+dataSz, librevenge::RVNG_SEEK_SET); |
602 | 588k | continue; |
603 | 588k | } |
604 | 14.6k | if (i<2) |
605 | 4.20k | { |
606 | 4.20k | WPSEntry entry; |
607 | 4.20k | entry.setBegin(actPos+1); |
608 | 4.20k | entry.setEnd(m_input->tell()); |
609 | 4.20k | auto *textZone=chart->getTextZone(i==0 ? WKSChart::TextZone::T_Title : WKSChart::TextZone::T_SubTitle, true); |
610 | 4.20k | textZone->m_contentType=WKSChart::TextZone::C_Text; |
611 | 4.20k | textZone->m_textEntryList.push_back(entry); |
612 | 4.20k | f << (i==0 ? "title" : "subTitle") << "=" << name.cstr() << ","; |
613 | 4.20k | } |
614 | 10.4k | else if (i<4) |
615 | 3.46k | { |
616 | 3.46k | chart->getAxis(i-2).m_title=name; |
617 | 3.46k | f << (i==2 ? "x" : "y") << "Title=" << name.cstr() << ","; |
618 | 3.46k | } |
619 | 6.98k | else |
620 | 6.98k | { |
621 | 6.98k | auto *serie=chart->getSerie(i-3, false); |
622 | 6.98k | if (serie) |
623 | 3.56k | { |
624 | 3.56k | serie->m_legendText=name; |
625 | 3.56k | hasLegend=true; |
626 | 3.56k | } |
627 | 6.98k | f << "serie" << i-3 << "=" << name.cstr() << ","; |
628 | 6.98k | } |
629 | 14.6k | m_input->seek(actPos+dataSz, librevenge::RVNG_SEEK_SET); |
630 | 14.6k | } |
631 | 60.3k | ascii().addPos(pos); |
632 | 60.3k | ascii().addNote(f.str().c_str()); |
633 | | |
634 | 60.3k | pos=m_input->tell(); |
635 | 60.3k | f.str(""); |
636 | 60.3k | f << "ChartDef-B:"; |
637 | 180k | for (int i=0; i<2; ++i) // axisX, axisY: format: USEME |
638 | 120k | { |
639 | 120k | val=int(libwps::readU8(m_input)); |
640 | 120k | if (val) f << "fmt" << axisNames[i] << "=" << val << ","; |
641 | 120k | } |
642 | 180k | for (int i=0; i<2; ++i) // axisX, axisY, number of tick: USEME |
643 | 120k | { |
644 | 120k | val=int(libwps::readU8(m_input)); |
645 | 120k | if (val) f << "num[tick" << axisNames[i] << "]=" << val << ","; |
646 | 120k | } |
647 | 180k | for (int i=0; i<2; ++i) |
648 | 120k | { |
649 | 120k | val=int(libwps::readU8(m_input)); |
650 | 120k | if (val==1 || val==255) |
651 | 2.33k | f << "display[scale" << axisNames[i] << "]=no,"; |
652 | 118k | else if (val) |
653 | 17.4k | f << "display[scale" << axisNames[i] << "]=##" << val << ","; |
654 | 120k | } |
655 | 60.3k | f << "pattern[series]=["; |
656 | 60.3k | int patternSeriesId[6]; |
657 | 60.3k | for (auto &pId : patternSeriesId) |
658 | 361k | { |
659 | 361k | pId=int(libwps::readU16(m_input)); |
660 | 361k | if (pId==0) |
661 | 256k | f << "_,"; |
662 | 105k | else |
663 | 105k | f << pId << ","; |
664 | 361k | } |
665 | 60.3k | f << "],"; |
666 | 60.3k | f << "colors2=["; |
667 | 241k | for (int i=0; i<3; ++i) |
668 | 180k | f << int(libwps::readU16(m_input)) << ","; |
669 | 60.3k | f << "],"; |
670 | 60.3k | f << "color[series]=["; |
671 | 60.3k | WPSColor colorSeriesId[6]; |
672 | 60.3k | for (auto &color : colorSeriesId) |
673 | 361k | { |
674 | 361k | auto cId=int(libwps::readU16(m_input)); |
675 | 361k | if (m_mainParser.getColor(cId, color)) |
676 | 274k | f << color << ","; |
677 | 87.3k | else |
678 | 87.3k | { |
679 | 87.3k | color=WPSColor(128,128,128); |
680 | 87.3k | f << "###" << cId << ","; |
681 | 87.3k | } |
682 | 361k | } |
683 | 60.3k | f << "],"; |
684 | 60.3k | f << "unkn=["; |
685 | 301k | for (int i=0; i<4; ++i) // 3 colors + big number |
686 | 241k | f << int(libwps::readU16(m_input)) << ","; |
687 | 60.3k | f << "],"; |
688 | 60.3k | auto cId=int(libwps::readU8(m_input)); |
689 | 60.3k | WPSColor backColor(WPSColor::white()); |
690 | 60.3k | if (m_mainParser.getColor(cId, backColor)) |
691 | 54.6k | { |
692 | 54.6k | chart->m_style.setSurfaceColor(backColor); |
693 | 54.6k | f << "col[background]=" << backColor << ","; |
694 | 54.6k | } |
695 | 5.62k | else |
696 | 5.62k | f << "col[background]=###" << val << ","; |
697 | 60.3k | val=int(libwps::readU8(m_input)); |
698 | 60.3k | if (val) f << "f0=" << val << ","; |
699 | 60.3k | m_input->seek(pos+46, librevenge::RVNG_SEEK_SET); |
700 | 60.3k | ascii().addPos(pos); |
701 | 60.3k | ascii().addNote(f.str().c_str()); |
702 | | |
703 | 60.3k | pos=m_input->tell(); |
704 | 60.3k | f.str(""); |
705 | 60.3k | f << "ChartDef-fonts:"; |
706 | 422k | for (int i = 0; i < 6; ++i) // the series font? |
707 | 361k | { |
708 | 361k | WPSFont font; |
709 | 361k | libwps_tools_win::Font::Type fFontType; |
710 | 361k | if (!m_mainParser.readFont(font, fFontType)) |
711 | 0 | { |
712 | 0 | f << "###"; |
713 | 0 | m_input->seek(pos+(i+1)*8, librevenge::RVNG_SEEK_SET); |
714 | 0 | } |
715 | 361k | else |
716 | 361k | { |
717 | 361k | auto *serie=chart->getSerie(i, false); |
718 | 361k | if (serie) |
719 | 263k | serie->m_font=font; |
720 | 361k | } |
721 | 361k | f << "[" << font << "],"; |
722 | 361k | } |
723 | 60.3k | ascii().addPos(pos); |
724 | 60.3k | ascii().addNote(f.str().c_str()); |
725 | | |
726 | 60.3k | pos=m_input->tell(); |
727 | 60.3k | f.str(""); |
728 | 60.3k | f << "ChartDef-C:"; |
729 | 60.3k | val=int(libwps::readU16(m_input)); |
730 | 60.3k | if (val) f << "f0=" << std::hex << val << std::dec << ","; |
731 | 422k | for (int i=0; i<6; ++i) |
732 | 361k | { |
733 | 361k | f << "serie" << i << "=["; |
734 | 361k | auto *serie = chart->getSerie(i, false); |
735 | 361k | val=int(libwps::readU8(m_input)); |
736 | 361k | if (val==1 || val==255) |
737 | 11.6k | { |
738 | 11.6k | if (serie) serie->m_useSecondaryY=true; |
739 | 11.6k | f << "secondary,"; |
740 | 11.6k | } |
741 | 350k | else if (val) |
742 | 48.2k | f << "coordinate=###" << val << ","; |
743 | 361k | val=int(libwps::readU8(m_input)); |
744 | 361k | if (val==1) |
745 | 2.36k | { |
746 | 2.36k | if (serie && serie->m_type==WKSChart::Serie::S_Line) |
747 | 197 | serie->m_type=WKSChart::Serie::S_Bar; |
748 | 2.36k | f << "bar,"; |
749 | 2.36k | } |
750 | 359k | else if (val==2) |
751 | 22.6k | { |
752 | 22.6k | if (serie && serie->m_type==WKSChart::Serie::S_Bar) |
753 | 1.80k | serie->m_type=WKSChart::Serie::S_Line; |
754 | 22.6k | f << "line,"; |
755 | 22.6k | } |
756 | 336k | else if (val) |
757 | 53.0k | f << "type=##" << val << ","; |
758 | 361k | f << "],"; |
759 | 361k | } |
760 | 60.3k | val=int(libwps::readU8(m_input)); |
761 | 60.3k | auto &axisYSecond=chart->getAxis(2); |
762 | 60.3k | if (val==1) |
763 | 643 | { |
764 | 643 | f << "scaleY2[manual],"; |
765 | 643 | axisYSecond.m_automaticScaling=false; |
766 | 643 | } |
767 | 59.6k | else if (val) |
768 | 10.4k | f << "scaleY2=##" << val << ","; |
769 | 180k | for (int i=0; i<2; ++i) |
770 | 120k | { |
771 | 120k | long actPos=m_input->tell(); |
772 | 120k | long double value; |
773 | 120k | bool isNaN; |
774 | 120k | if (!libwps::readDouble8(m_input, value, isNaN)) |
775 | 19.4k | { |
776 | 19.4k | m_input->seek(actPos+8, librevenge::RVNG_SEEK_SET); |
777 | 19.4k | f << "##value,"; |
778 | 19.4k | } |
779 | 101k | else |
780 | 101k | { |
781 | 101k | if (value<0 || value>0) |
782 | 25.2k | f << (i==0 ? "lowY2" : "highY2") << "=" << value << ","; |
783 | 101k | axisYSecond.m_scaling[i]=float(value); |
784 | 101k | } |
785 | 120k | } |
786 | 60.3k | val=int(libwps::readU8(m_input)); |
787 | 60.3k | if (val) |
788 | 13.8k | f << "fmtY2=" << std::hex << val << std::dec << ","; |
789 | 60.3k | val=int(libwps::readU8(m_input)); |
790 | 60.3k | if (val) |
791 | 8.34k | f << "f1=" << val << ","; |
792 | 60.3k | m_input->seek(pos+33, librevenge::RVNG_SEEK_SET); |
793 | 60.3k | ascii().addPos(pos); |
794 | 60.3k | ascii().addNote(f.str().c_str()); |
795 | | |
796 | 60.3k | pos=m_input->tell(); |
797 | 60.3k | f.str(""); |
798 | 60.3k | f << "ChartDef-name2:"; |
799 | 60.3k | librevenge::RVNGString name(""); |
800 | 60.3k | if (!m_mainParser.readPString(name,39)) |
801 | 7.06k | f << "##sSz,"; |
802 | 53.2k | else if (!name.empty()) f << name.cstr() << ","; |
803 | 60.3k | m_input->seek(pos+40, librevenge::RVNG_SEEK_SET); |
804 | 60.3k | ascii().addPos(pos); |
805 | 60.3k | ascii().addNote(f.str().c_str()); |
806 | | |
807 | 60.3k | pos=m_input->tell(); |
808 | 60.3k | f.str(""); |
809 | 60.3k | f << "ChartDef-D:"; |
810 | 60.3k | val=int(libwps::readU8(m_input)); |
811 | 60.3k | if (val==0) |
812 | 46.9k | f << "text[pos]=bottom,"; |
813 | 13.3k | else if (val==1) |
814 | 265 | f << "text[pos]=right,"; |
815 | 13.1k | else if (val==2) |
816 | 4.37k | f << "text[pos]=none,"; |
817 | 8.72k | else |
818 | 8.72k | f << "text[pos]=##" << val << ","; |
819 | 241k | for (int i=0; i<3; ++i) // USEME |
820 | 180k | { |
821 | 180k | val=int(libwps::readU8(m_input)); |
822 | 180k | if (val==6) continue; |
823 | 180k | f << (i==0 ? "title" : i==1 ? "legend" : "graph") << "[ouline]="; |
824 | 180k | if (val>=0 && val<=7) |
825 | 158k | { |
826 | 158k | char const *wh[]= {"box", "doubleLine", "thickLine", "shadow", "3d", "rndRect", "none","sculpted"}; |
827 | 158k | f << wh[val] << ","; |
828 | 158k | } |
829 | 22.2k | else |
830 | 22.2k | f << "###" << val << ","; |
831 | 180k | } |
832 | 241k | for (int i=0; i<3; ++i) |
833 | 180k | { |
834 | 180k | auto &axis = chart->getAxis(i); |
835 | 180k | f << "axis" << (i==0 ? "X" : i==1 ? "Y" : "Y2") << "=["; |
836 | 180k | val=int(libwps::readU16(m_input)); |
837 | 180k | if (val) f << "f0=" << std::hex << val << std::dec << ","; |
838 | 180k | val=int(libwps::readU8(m_input)); |
839 | 180k | if (val==0) |
840 | 150k | axis.m_type= WKSChart::Axis::A_Numeric; |
841 | 30.6k | else if (val==1 || val==255) |
842 | 5.49k | { |
843 | 5.49k | f << "log,"; // 0:normal |
844 | 5.49k | axis.m_type= WKSChart::Axis::A_Logarithmic; |
845 | 5.49k | } |
846 | 25.1k | else f << "scale=###" << val << ","; |
847 | 180k | long actPos=m_input->tell(); |
848 | 180k | long double value; |
849 | 180k | bool isNaN; |
850 | 180k | if (!libwps::readDouble8(m_input, value, isNaN)) |
851 | 29.9k | { |
852 | 29.9k | m_input->seek(actPos+8, librevenge::RVNG_SEEK_SET); |
853 | 29.9k | f << "##value,"; |
854 | 29.9k | } |
855 | 150k | else if (value<0 || value>0) // USEME |
856 | 32.9k | f << "increment=" << value << ","; |
857 | 180k | f << "],"; |
858 | 180k | } |
859 | 60.3k | val=int(libwps::readU8(m_input)); |
860 | 60.3k | if (val && val<=7) |
861 | 2.22k | { |
862 | | // USEME |
863 | 2.22k | char const *wh[]= {"solid", "dotted", "center-line", "dashed", "heavy solid", |
864 | 2.22k | "heavy dotted", "heavy centered", "heavy dashed" |
865 | 2.22k | }; |
866 | 2.22k | f << "style[gridline]=" << wh[val] << ","; |
867 | 2.22k | } |
868 | 58.0k | else if (val) |
869 | 6.26k | f << "##style[gridline]=" << val << ","; |
870 | 60.3k | cId=int(libwps::readU8(m_input)); |
871 | 60.3k | WPSColor gridColor(WPSColor::black()); |
872 | 60.3k | if (m_mainParser.getColor(cId, gridColor)) |
873 | 53.7k | { |
874 | 53.7k | chart->setGridColor(gridColor); |
875 | 53.7k | f << "color[line/grid]=" << gridColor << ","; |
876 | 53.7k | } |
877 | 6.54k | else |
878 | 6.54k | f << "##color[line/grid]=" << cId << ","; |
879 | 60.3k | ascii().addDelimiter(m_input->tell(),'|'); |
880 | 60.3k | m_input->seek(pos+49, librevenge::RVNG_SEEK_SET); |
881 | 60.3k | ascii().addPos(pos); |
882 | 60.3k | ascii().addNote(f.str().c_str()); |
883 | | |
884 | | // time to update the serie pattern |
885 | 60.3k | if (hasLegend) |
886 | 3.03k | { |
887 | 3.03k | chart->getLegend().m_show=true; |
888 | 3.03k | chart->getLegend().m_autoPosition=true; |
889 | 3.03k | chart->getLegend().m_relativePosition=WPSBorder::RightBit; |
890 | 3.03k | } |
891 | 422k | for (int i=0; i<6; ++i) |
892 | 361k | { |
893 | 361k | auto *serie=chart->getSerie(i, false); |
894 | 361k | if (!serie) continue; |
895 | 263k | WPSGraphicStyle::Pattern pattern; |
896 | 263k | if (!m_state->getPattern(patternSeriesId[i],pattern)) |
897 | 51.2k | { |
898 | 51.2k | WPS_DEBUG_MSG(("QuattroDosChart::readChart: oops, can not find pattern %d\n", i)); |
899 | 51.2k | serie->setPrimaryColor(colorSeriesId[i]); |
900 | 51.2k | serie->setSecondaryColor(gridColor); |
901 | 51.2k | continue; |
902 | 51.2k | } |
903 | 212k | pattern.m_colors[0]=colorSeriesId[i]; |
904 | 212k | pattern.m_colors[1]=backColor; |
905 | 212k | serie->setPrimaryPattern(pattern); |
906 | 212k | serie->setSecondaryColor(gridColor); |
907 | 212k | } |
908 | | |
909 | 60.3k | pos=m_input->tell(); |
910 | 60.3k | f.str(""); |
911 | 60.3k | f << "ChartDef-E:"; |
912 | 60.3k | val=int(libwps::readU8(m_input)); |
913 | 60.3k | if (val) f << "tickX[alternate],"; |
914 | 60.3k | val=int(libwps::readU16(m_input)); |
915 | 60.3k | if (val) f << "f0=" << std::hex << val << std::dec << ","; |
916 | 60.3k | val=int(libwps::readU8(m_input)); |
917 | 60.3k | if (val) f << "use[depth],"; |
918 | 60.3k | ascii().addDelimiter(m_input->tell(),'|'); |
919 | 60.3k | m_input->seek(24, librevenge::RVNG_SEEK_CUR); |
920 | 60.3k | ascii().addDelimiter(m_input->tell(),'|'); |
921 | 60.3k | val=int(libwps::read16(m_input)); |
922 | 60.3k | if (val) f << "bar[width]=" << val << "%,"; |
923 | 180k | for (int i=0; i<2; ++i) // 0: local graph position, 1: title/sub title frames |
924 | 120k | { |
925 | 120k | int dim[4]; |
926 | 482k | for (auto &d : dim) d = int(libwps::read16(m_input)); |
927 | 120k | if (dim[0]==-1) |
928 | 1.30k | continue; |
929 | 119k | WPSBox2i box(Vec2i(dim[0],dim[1]), Vec2i(dim[2],dim[3])); |
930 | 119k | if (box==WPSBox2i()) continue; |
931 | 66.3k | f << (i==0 ? "grid" : "title") << "[pos]=" << box << ","; |
932 | 66.3k | if (i==0) // the size seems to be the windows size 1024*??? |
933 | 32.9k | chart->m_plotAreaPosition= |
934 | 32.9k | WPSBox2f(Vec2f(float(dim[0])/1024.f,float(dim[1])/700.f),Vec2f(float(dim[2])/1024.f,float(dim[3])/700.f)); |
935 | 66.3k | } |
936 | 60.3k | f << "unk=["; |
937 | 603k | for (int i=0; i<9; ++i) |
938 | 542k | { |
939 | 542k | val=int(libwps::readU8(m_input)); |
940 | 542k | if (val==255) |
941 | 11.5k | f << "*,"; |
942 | 531k | else if (val) |
943 | 75.4k | f << val << ","; |
944 | 455k | else |
945 | 455k | f << "_,"; |
946 | 542k | } |
947 | 60.3k | f << "],"; |
948 | 60.3k | WPSColor color; |
949 | 60.3k | cId=int(libwps::readU8(m_input)); |
950 | 60.3k | if (m_mainParser.getColor(cId, color)) |
951 | 53.1k | { |
952 | 53.1k | chart->m_wallStyle.setSurfaceColor(color); |
953 | 53.1k | f << "col[fill]=" << color << ","; |
954 | 53.1k | } |
955 | 7.18k | else |
956 | 7.18k | f << "col[fill]=###" << color << ","; |
957 | 60.3k | val=int(libwps::readU8(m_input)); |
958 | 60.3k | if (val) f << "f1=" << std::hex << val << std::dec << ","; |
959 | 60.3k | for (auto &range : chart->m_ranges) |
960 | 120k | { |
961 | 120k | int dim[3]; |
962 | 395k | for (int d=0; d<(vers>=2 ? 3 : 2); ++d) dim[d] = int(libwps::read16(m_input)); |
963 | 120k | if (dim[0]==-1) |
964 | 664 | continue; |
965 | 119k | chart->m_spreadsheetId=vers<2 ? 0 : dim[2]; |
966 | 119k | range = WKSChart::Position(Vec2i(dim[0],dim[1])); |
967 | 119k | range.m_sheetId=chart->m_spreadsheetId; |
968 | 119k | } |
969 | 60.3k | if (chart->m_ranges[0].valid(chart->m_ranges[1])) |
970 | 48.5k | { |
971 | 48.5k | f << "position=" << chart->m_ranges[0] << ":" << chart->m_ranges[1] << ","; |
972 | 48.5k | if (chart->m_ranges[1].m_pos[0]>255 || chart->m_ranges[1].m_pos[1]>65535) |
973 | 1.85k | { |
974 | 1.85k | f << "###"; |
975 | 1.85k | WPS_DEBUG_MSG(("QuattroDosChart::readChart: oops, the maximum position seems bad\n")); |
976 | 1.85k | } |
977 | 46.6k | else if (chart->m_ranges[0].m_sheetId!=chart->m_ranges[1].m_sheetId) |
978 | 2.71k | { |
979 | 2.71k | f << "###"; |
980 | 2.71k | WPS_DEBUG_MSG(("QuattroDosChart::readChart: oops, the position is on different sheet\n")); |
981 | 2.71k | } |
982 | 43.9k | else |
983 | 43.9k | { |
984 | 43.9k | m_state->m_idToChartMap.insert(std::multimap<int, std::shared_ptr<QuattroDosChartInternal::Chart> >::value_type(chart->m_spreadsheetId, chart)); |
985 | 43.9k | } |
986 | 48.5k | } |
987 | 60.3k | if (sz != normalSz) ascii().addDelimiter(m_input->tell(),'#'); |
988 | 60.3k | ascii().addPos(pos); |
989 | 60.3k | ascii().addNote(f.str().c_str()); |
990 | | |
991 | 60.3k | return true; |
992 | 60.3k | } |
993 | | |
994 | | /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */ |