1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3 /* libmwaw
4 * Version: MPL 2.0 / LGPLv2+
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 2.0 (the "License"); you may not use this file except in compliance with
8 * the License or as specified alternatively below. You may obtain a copy of
9 * the License at http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * Major Contributor(s):
17 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18 * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20 * Copyright (C) 2006, 2007 Andrew Ziem
21 * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22 *
23 *
24 * All Rights Reserved.
25 *
26 * For minor contributions see the git repository.
27 *
28 * Alternatively, the contents of this file may be used under the terms of
29 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30 * in which case the provisions of the LGPLv2+ are applicable
31 * instead of those above.
32 */
33
34 #include <iomanip>
35 #include <map>
36 #include <sstream>
37 #include <stack>
38
39 #include "MWAWCell.hxx"
40 #include "MWAWDebug.hxx"
41 #include "MWAWFont.hxx"
42 #include "MWAWFontConverter.hxx"
43 #include "MWAWParagraph.hxx"
44 #include "MWAWSection.hxx"
45
46 #include "RagTime5Document.hxx"
47 #include "RagTime5StructManager.hxx"
48
49 #include "RagTime5StyleManager.hxx"
50
51 /** Internal: the structures of a RagTime5Style */
52 namespace RagTime5StyleManagerInternal
53 {
54 ////////////////////////////////////////
55 //! Internal: the helper to read field color field for a RagTime5StyleManager
56 struct ColorFieldParser final : public RagTime5StructManager::FieldParser {
57 //! constructor
ColorFieldParserRagTime5StyleManagerInternal::ColorFieldParser58 ColorFieldParser()
59 : RagTime5StructManager::FieldParser("GraphColor")
60 , m_colorsList()
61 {
62 m_regroupFields=false;
63 }
64 //! destructor
65 ~ColorFieldParser() final;
66 //! return the debug name corresponding to a field
getZoneNameRagTime5StyleManagerInternal::ColorFieldParser67 std::string getZoneName(int n) const final
68 {
69 std::stringstream s;
70 s << "GraphColor-GC" << n;
71 return s.str();
72 }
73 //! parse a field
parseFieldRagTime5StyleManagerInternal::ColorFieldParser74 bool parseField(RagTime5StructManager::Field &field, RagTime5Zone &/*zone*/, int n, libmwaw::DebugStream &f) final
75 {
76 if (field.m_type!=RagTime5StructManager::Field::T_FieldList) {
77 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::ColorFieldParser::parseField: find unexpected field type \n"));
78 f << "##field,";
79 return true;
80 }
81 switch (field.m_fileType) {
82 case 0x7d02a:
83 for (auto const &child : field.m_fieldList) {
84 // checkme:
85 if (child.m_type==RagTime5StructManager::Field::T_Color && child.m_fileType==0x84040) {
86 if (n>=0 && int(m_colorsList.size())<n)
87 m_colorsList.resize(size_t(n));
88 if (n>=1 && n<=int(m_colorsList.size()))
89 m_colorsList[size_t(n-1)]=child.m_color;
90 else {
91 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::ColorFieldParser::parseField: find bad n\n"));
92 f << "col=" << child.m_color << "[###],";
93 }
94 continue;
95 }
96 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::ColorFieldParser::parseField: find some unknown color block\n"));
97 f << "##col=" << child << ",";
98 }
99 break;
100 case 0x17d481a:
101 for (auto const &child : field.m_fieldList) {
102 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x3b880) {
103 f << "id=" << child.m_longValue[0] << ",";
104 continue;
105 }
106 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::ColorFieldParser::parseField: find some unknown id block\n"));
107 f << "##id=" << child << ",";
108 }
109 break;
110 case 0x17d484a: // always 0:1
111 for (auto const &child : field.m_fieldList) {
112 if (child.m_type==RagTime5StructManager::Field::T_2Long && child.m_fileType==0x34800) {
113 f << "unkn0=" << child.m_longValue[0] << "x" << child.m_longValue[1] << ",";
114 continue;
115 }
116 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::ColorFieldParser::parseField: find some unknown unkn0 block\n"));
117 f << "##unkn0=" << child << ",";
118 }
119 break;
120 case 0x17d486a:
121 for (auto const &child : field.m_fieldList) {
122 if (child.m_type==RagTime5StructManager::Field::T_Bool && child.m_fileType==0x360c0) {
123 f << "fl0=" << child.m_longValue[0] << ",";
124 continue;
125 }
126 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::ColorFieldParser::parseField: find some unknown fl0 block\n"));
127 f << "##fl0=" << child << ",";
128 }
129 break;
130 default:
131 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::ColorFieldParser::parseField: find some unknown block\n"));
132 f << "###" << field;
133 break;
134 }
135 return true;
136 }
137
138 //! the list of color
139 std::vector<MWAWColor> m_colorsList;
140 };
141
~ColorFieldParser()142 ColorFieldParser::~ColorFieldParser()
143 {
144 }
145
146 ////////////////////////////////////////
147 //! Internal: the helper to read field graphic field for a RagTime5StyleManager
148 struct GraphicFieldParser final : public RagTime5StructManager::FieldParser {
149 //! constructor
GraphicFieldParserRagTime5StyleManagerInternal::GraphicFieldParser150 explicit GraphicFieldParser(std::vector<MWAWColor> const &colorList)
151 : RagTime5StructManager::FieldParser("GraphStyle")
152 , m_colorsList(colorList)
153 , m_styleList()
154 {
155 m_regroupFields=true;
156 }
157 //! destructor
158 ~GraphicFieldParser() final;
159 //! return the debug name corresponding to a field
getZoneNameRagTime5StyleManagerInternal::GraphicFieldParser160 std::string getZoneName(int n) const final
161 {
162 // we need to resize here (if the style does not contains any field)
163 if (n>=int(m_styleList.size()))
164 const_cast<GraphicFieldParser *>(this)->m_styleList.resize(size_t(n+1));
165 std::stringstream s;
166 s << "GraphStyle-GS" << n;
167 return s.str();
168 }
169 //! parse a header field
parseHeaderFieldRagTime5StyleManagerInternal::GraphicFieldParser170 bool parseHeaderField(RagTime5StructManager::Field &field, RagTime5Zone &zone, int n, libmwaw::DebugStream &f) final
171 {
172 if (n>=int(m_styleList.size()))
173 m_styleList.resize(size_t(n+1));
174 auto &style=m_styleList[size_t(n)];
175 MWAWInputStreamPtr input=zone.getInput();
176 if (style.read(input, field, m_colorsList))
177 f << style;
178 else
179 f << "###" << field;
180 return true;
181 }
182 //! parse a field
parseFieldRagTime5StyleManagerInternal::GraphicFieldParser183 bool parseField(RagTime5StructManager::Field &field, RagTime5Zone &zone, int n, libmwaw::DebugStream &f) final
184 {
185 if (n<=0) {
186 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::GraphicFieldParser::parseField: n=%d is bad\n", n));
187 n=0;
188 }
189 if (n>=int(m_styleList.size()))
190 m_styleList.resize(size_t(n+1));
191 auto &style=m_styleList[size_t(n)];
192 MWAWInputStreamPtr input=zone.getInput();
193 if (style.read(input, field, m_colorsList)) {
194 RagTime5StyleManager::GraphicStyle modStyle;
195 modStyle.read(input, field, m_colorsList);
196 f << modStyle;
197 }
198 else
199 f << "##" << field;
200 return true;
201 }
202
203 // !the main color map
204 std::vector<MWAWColor> const &m_colorsList;
205 //! the list of graphic style
206 std::vector<RagTime5StyleManager::GraphicStyle> m_styleList;
207 };
208
~GraphicFieldParser()209 GraphicFieldParser::~GraphicFieldParser()
210 {
211 }
212
213 ////////////////////////////////////////
214 //! Internal: the helper to read style for a RagTime5StyleManager
215 struct TextFieldParser final : public RagTime5StructManager::FieldParser {
216 //! constructor
TextFieldParserRagTime5StyleManagerInternal::TextFieldParser217 TextFieldParser()
218 : RagTime5StructManager::FieldParser("TextStyle")
219 , m_styleList()
220 {
221 }
222 //! destructor
223 ~TextFieldParser() final;
224 //! return the debug name corresponding to a field
getZoneNameRagTime5StyleManagerInternal::TextFieldParser225 std::string getZoneName(int n) const final
226 {
227 std::stringstream s;
228 s << "TextStyle-TS" << n;
229 return s.str();
230 }
231 //! parse a header field
parseHeaderFieldRagTime5StyleManagerInternal::TextFieldParser232 bool parseHeaderField(RagTime5StructManager::Field &field, RagTime5Zone &/*zone*/, int n, libmwaw::DebugStream &f) final
233 {
234 if (n>=int(m_styleList.size()))
235 m_styleList.resize(size_t(n+1));
236 auto &style=m_styleList[size_t(n)];
237 if (style.read(field))
238 f << style;
239 else
240 f << "###" << field;
241 return true;
242 }
243 //! parse a field
parseFieldRagTime5StyleManagerInternal::TextFieldParser244 bool parseField(RagTime5StructManager::Field &field, RagTime5Zone &/*zone*/, int n, libmwaw::DebugStream &f) final
245 {
246 if (n<=0) {
247 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::TextFieldParser::parseField: n=%d is bad\n", n));
248 n=0;
249 }
250 if (n>=int(m_styleList.size()))
251 m_styleList.resize(size_t(n+1));
252 auto &style=m_styleList[size_t(n)];
253 if (style.read(field)) {
254 RagTime5StyleManager::TextStyle modStyle;
255 modStyle.read(field);
256 f << modStyle;
257 }
258 else
259 f << "#" << field;
260 return true;
261 }
262
263 //! the list of read style
264 std::vector<RagTime5StyleManager::TextStyle> m_styleList;
265 };
266
267 //! Internal: the state of a RagTime5Style
268 struct State {
269 //! constructor
StateRagTime5StyleManagerInternal::State270 State()
271 : m_colorsList()
272 , m_formatList()
273 , m_graphicStyleList()
274 , m_textStyleList()
275 {
276 }
277 //! init the color list (if empty)
278 void initColorsList();
279 //! the list of color
280 std::vector<MWAWColor> m_colorsList;
281 //! the list of format
282 std::vector<MWAWCell::Format> m_formatList;
283 //! the list of graphic styles
284 std::vector<RagTime5StyleManager::GraphicStyle> m_graphicStyleList;
285 //! the list of text styles
286 std::vector<RagTime5StyleManager::TextStyle> m_textStyleList;
287 };
288
~TextFieldParser()289 TextFieldParser::~TextFieldParser()
290 {
291 }
292
initColorsList()293 void State::initColorsList()
294 {
295 if (!m_colorsList.empty()) return;
296 MWAW_DEBUG_MSG(("RagTime5StyleManagerInternal::State::initColorsList: colors' list is empty, set it to default\n"));
297 m_colorsList.push_back(MWAWColor::white());
298 m_colorsList.push_back(MWAWColor(0,0,0,0)); // transparent
299 m_colorsList.push_back(MWAWColor::black());
300 }
301 }
302
303 ////////////////////////////////////////////////////////////
304 // constructor/destructor, ...
305 ////////////////////////////////////////////////////////////
RagTime5StyleManager(RagTime5Document & doc)306 RagTime5StyleManager::RagTime5StyleManager(RagTime5Document &doc)
307 : m_document(doc)
308 , m_parserState(doc.getParserState())
309 , m_state(new RagTime5StyleManagerInternal::State)
310 {
311 }
312
~RagTime5StyleManager()313 RagTime5StyleManager::~RagTime5StyleManager()
314 {
315 }
316
317 ////////////////////////////////////////////////////////////
318 // read style
319 ////////////////////////////////////////////////////////////
readGraphicColors(RagTime5ClusterManager::Cluster & cluster)320 bool RagTime5StyleManager::readGraphicColors(RagTime5ClusterManager::Cluster &cluster)
321 {
322 RagTime5StyleManagerInternal::ColorFieldParser fieldParser;
323 if (!m_document.readStructZone(cluster.m_dataLink, fieldParser, 14, &cluster.m_nameLink))
324 return false;
325 m_state->m_colorsList=fieldParser.m_colorsList;
326 return true;
327 }
328
readGraphicStyles(RagTime5ClusterManager::Cluster & cluster)329 bool RagTime5StyleManager::readGraphicStyles(RagTime5ClusterManager::Cluster &cluster)
330 {
331 m_state->initColorsList();
332 RagTime5StyleManagerInternal::GraphicFieldParser fieldParser(m_state->m_colorsList);
333 if (!m_document.readStructZone(cluster.m_dataLink, fieldParser, 14, &cluster.m_nameLink))
334 return false;
335 if (fieldParser.m_styleList.empty())
336 fieldParser.m_styleList.resize(1);
337
338 //
339 // check parent relation, check for loop, ...
340 //
341 std::vector<size_t> rootList;
342 std::stack<size_t> toCheck;
343 std::multimap<size_t, size_t> idToChildIpMap;
344 auto numStyles=size_t(fieldParser.m_styleList.size());
345 for (size_t i=0; i<numStyles; ++i) {
346 auto &style=fieldParser.m_styleList[i];
347 if (style.m_parentId>=0 && style.m_parentId>=static_cast<int>(numStyles)) {
348 MWAW_DEBUG_MSG(("RagTime5StyleManager::readGraphicStyles: find unexpected parent %d for style %d\n",
349 static_cast<int>(style.m_parentId), static_cast<int>(i)));
350 style.m_parentId=0;
351 continue;
352 }
353 else if (style.m_parentId>=0) {
354 idToChildIpMap.insert(std::multimap<size_t, size_t>::value_type(size_t(style.m_parentId),i));
355 continue;
356 }
357 rootList.push_back(i);
358 toCheck.push(i);
359 }
360 std::set<size_t> seens;
361 while (true) {
362 size_t posToCheck=0; // to make clang happy
363 if (!toCheck.empty()) {
364 posToCheck=toCheck.top();
365 toCheck.pop();
366 }
367 else if (seens.size()+1==numStyles)
368 break;
369 else {
370 bool ok=false;
371 for (size_t i=1; i<numStyles; ++i) {
372 if (seens.find(i)!=seens.end())
373 continue;
374 MWAW_DEBUG_MSG(("RagTime5StyleManager::readGraphicStyles: find unexpected root %d\n", static_cast<int>(i)));
375 posToCheck=i;
376 rootList.push_back(i);
377
378 auto &style=fieldParser.m_styleList[i];
379 style.m_parentId=0;
380 ok=true;
381 break;
382 }
383 if (!ok)
384 break;
385 }
386 if (seens.find(posToCheck)!=seens.end()) {
387 MWAW_DEBUG_MSG(("RagTime5StyleManager::readGraphicStyles: oops, %d is already seens\n", static_cast<int>(posToCheck)));
388 continue;
389 }
390 seens.insert(posToCheck);
391 auto childIt=idToChildIpMap.lower_bound(posToCheck);
392 std::vector<size_t> badChildList;
393 while (childIt!=idToChildIpMap.end() && childIt->first==posToCheck) {
394 size_t childId=childIt++->second;
395 if (seens.find(childId)!=seens.end()) {
396 MWAW_DEBUG_MSG(("RagTime5StyleManager::readGraphicStyles: find loop for child %d\n", static_cast<int>(childId)));
397 RagTime5StyleManager::GraphicStyle &style=fieldParser.m_styleList[childId];
398 style.m_parentId=0;
399 badChildList.push_back(childId);
400 continue;
401 }
402 toCheck.push(childId);
403 }
404 for (auto badId : badChildList) {
405 childIt=idToChildIpMap.lower_bound(posToCheck);
406 while (childIt!=idToChildIpMap.end() && childIt->first==posToCheck) {
407 if (childIt->second==badId) {
408 idToChildIpMap.erase(childIt);
409 break;
410 }
411 ++childIt;
412 }
413 }
414 }
415
416 if (!m_state->m_graphicStyleList.empty()) {
417 MWAW_DEBUG_MSG(("RagTime5StyleManager::readGraphicStyles: Ooops, we already set some graphicStyles\n"));
418 }
419
420 // now let generate the final style
421 m_state->m_graphicStyleList.resize(numStyles);
422 seens.clear();
423 for (auto id : rootList) {
424 if (id>=numStyles) {
425 MWAW_DEBUG_MSG(("RagTime5StyleManager::readGraphicStyles: find loop for id=%d\n", static_cast<int>(id)));
426 continue;
427 }
428 updateGraphicStyles(id, fieldParser.m_styleList[id], fieldParser.m_styleList, idToChildIpMap, seens);
429 }
430 return true;
431 }
432
updateGraphicStyles(size_t id,RagTime5StyleManager::GraphicStyle const & style,std::vector<RagTime5StyleManager::GraphicStyle> const & listReadStyles,std::multimap<size_t,size_t> const & idToChildIpMap,std::set<size_t> & seens)433 void RagTime5StyleManager::updateGraphicStyles
434 (size_t id, RagTime5StyleManager::GraphicStyle const &style, std::vector<RagTime5StyleManager::GraphicStyle> const &listReadStyles,
435 std::multimap<size_t, size_t> const &idToChildIpMap, std::set<size_t> &seens)
436 {
437 if (id>=m_state->m_graphicStyleList.size() || seens.find(id)!=seens.end()) {
438 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateGraphicStyles: problem with style with id=%d\n", static_cast<int>(id)));
439 return;
440 }
441 seens.insert(id);
442 m_state->m_graphicStyleList[id]=style;
443
444 auto childIt=idToChildIpMap.lower_bound(id);
445 while (childIt!=idToChildIpMap.end() && childIt->first==id) {
446 size_t childId=childIt++->second;
447 if (childId>=listReadStyles.size()) {
448 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateGraphicStyles: problem with style with childId=%d\n", static_cast<int>(childId)));
449 continue;
450 }
451 auto childStyle=style;
452 childStyle.insert(listReadStyles[childId]);
453 updateGraphicStyles(childId, childStyle, listReadStyles, idToChildIpMap, seens);
454 }
455 }
456
getLineColor(int gId,MWAWColor & color) const457 bool RagTime5StyleManager::getLineColor(int gId, MWAWColor &color) const
458 {
459 if (gId<=0 || gId>=static_cast<int>(m_state->m_graphicStyleList.size())) {
460 MWAW_DEBUG_MSG(("RagTime5StyleManager::getLineColor: can not find graphic style %d\n", gId));
461 return false;
462 }
463 auto const &style=m_state->m_graphicStyleList[size_t(gId)];
464 color=style.m_colors[0].get();
465 if (style.m_colorsAlpha[0]>=0 && style.m_colorsAlpha[0]<1)
466 color=MWAWColor::barycenter(style.m_colorsAlpha[0],color,1-style.m_colorsAlpha[0],MWAWColor::white());
467
468 return true;
469 }
470
getCellBorder(int gId,MWAWBorder & border) const471 bool RagTime5StyleManager::getCellBorder(int gId, MWAWBorder &border) const
472 {
473 if (gId<=0 || gId>=static_cast<int>(m_state->m_graphicStyleList.size())) {
474 MWAW_DEBUG_MSG(("RagTime5StyleManager::getCellBorder: can not find graphic style %d\n", gId));
475 border.m_width=0;
476 return false;
477 }
478 auto const &gStyle=m_state->m_graphicStyleList[size_t(gId)];
479 if (gStyle.m_width>=0)
480 border.m_width=double(gStyle.m_width);
481 else
482 border.m_width=1;
483 if (gStyle.m_pattern) {
484 MWAWColor color;
485 if (gStyle.m_pattern->getAverageColor(color)) {
486 if (gStyle.m_colors[0].isSet() || gStyle.m_colors[1].isSet()) {
487 float alpha=(float(color.getRed())+float(color.getGreen())+float(color.getBlue()))/765.f;
488 border.m_color=MWAWColor::barycenter(1.f-alpha, *gStyle.m_colors[0], alpha, *gStyle.m_colors[1]);
489 }
490 else
491 border.m_color=color;
492 }
493 }
494 else if (gStyle.m_colors[0].isSet())
495 border.m_color=gStyle.m_colors[0].get();
496 else // default
497 border.m_color=MWAWColor(0,0,0);
498 if (gStyle.m_dash.isSet() && gStyle.m_dash->size()>=4) {
499 long fullWidth=0, emptyWidth=0;
500 for (size_t i=0; i<gStyle.m_dash->size(); i+=2) {
501 if ((i%4)==0)
502 fullWidth+= (*gStyle.m_dash)[i];
503 else
504 emptyWidth+=(*gStyle.m_dash)[i];
505 }
506 if (fullWidth==2 && emptyWidth==2)
507 border.m_style=MWAWBorder::Dot;
508 else if (fullWidth==10 && emptyWidth==5)
509 border.m_style=MWAWBorder::Dash;
510 else // ok, specific dash, let use large dot
511 border.m_style=MWAWBorder::LargeDot;
512 }
513 return true;
514
515 }
516
getCellBackgroundColor(int gId,MWAWColor & color) const517 bool RagTime5StyleManager::getCellBackgroundColor(int gId, MWAWColor &color) const
518 {
519 if (gId<=0 || gId>=static_cast<int>(m_state->m_graphicStyleList.size())) {
520 MWAW_DEBUG_MSG(("RagTime5StyleManager::getCellBackgroundColor: can not find graphic style %d\n", gId));
521 return false;
522 }
523 auto const &gStyle=m_state->m_graphicStyleList[size_t(gId)];
524 if (gStyle.m_pattern) {
525 MWAWColor col;
526 if (gStyle.m_pattern->getAverageColor(col)) {
527 if (gStyle.m_colors[0].isSet() || gStyle.m_colors[1].isSet()) {
528 float alpha=(float(col.getRed())+float(col.getGreen())+float(col.getBlue()))/765.f;
529 color=MWAWColor::barycenter(1.f-alpha, *gStyle.m_colors[0], alpha, *gStyle.m_colors[1]);
530 }
531 else
532 color=col;
533 }
534 }
535 else if (gStyle.m_colors[0].isSet())
536 color=gStyle.m_colors[0].get();
537 else // default is white
538 color=MWAWColor(255,255,255);
539
540 return true;
541 }
542
updateBorderStyle(int gId,MWAWGraphicStyle & style,bool isLine) const543 bool RagTime5StyleManager::updateBorderStyle(int gId, MWAWGraphicStyle &style, bool isLine) const
544 {
545 if (gId<=0 || gId>=static_cast<int>(m_state->m_graphicStyleList.size())) {
546 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateBorderStyle: can not find graphic style %d\n", gId));
547 style.m_lineWidth=0;
548 return false;
549 }
550 auto const &gStyle=m_state->m_graphicStyleList[size_t(gId)];
551 if (gStyle.m_width>=0)
552 style.m_lineWidth=gStyle.m_width;
553 else
554 style.m_lineWidth=1;
555 if (gStyle.m_pattern) {
556 MWAWColor color;
557 if (gStyle.m_pattern->getAverageColor(color)) {
558 if (gStyle.m_colors[0].isSet() || gStyle.m_colors[1].isSet()) {
559 float alpha=(float(color.getRed())+float(color.getGreen())+float(color.getBlue()))/765.f;
560 style.m_lineColor=MWAWColor::barycenter(1.f-alpha, *gStyle.m_colors[0], alpha, *gStyle.m_colors[1]);
561 }
562 else
563 style.m_lineColor=color;
564 }
565 }
566 else if (isLine || gStyle.m_colors[0].isSet())
567 style.m_lineColor=gStyle.m_colors[0].get();
568 else // default is blue
569 style.m_lineColor=MWAWColor(0,0,255);
570 if (gStyle.m_colorsAlpha[0]>=0)
571 style.m_lineOpacity=gStyle.m_colorsAlpha[0];
572 if (gStyle.m_dash.isSet() && gStyle.m_dash->size()>=4) {
573 for (size_t i=0; i<gStyle.m_dash->size(); i+=2)
574 style.m_lineDashWidth.push_back(float((*gStyle.m_dash)[i]));
575 }
576 return true;
577 }
578
updateFrameStyle(int gId,MWAWGraphicStyle & style) const579 bool RagTime5StyleManager::updateFrameStyle(int gId, MWAWGraphicStyle &style) const
580 {
581 if (gId<=0 || gId>=static_cast<int>(m_state->m_graphicStyleList.size())) {
582 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateSurfaceStyle: can not find graphic style %d\n", gId));
583 return false;
584 }
585 auto const &gStyle=m_state->m_graphicStyleList[size_t(gId)];
586 if (gStyle.m_colorsAlpha[0]<=0 && gStyle.m_colorsAlpha[0]>=0)
587 return true;
588 float alpha=gStyle.m_colorsAlpha[0]>=0 ? gStyle.m_colorsAlpha[0] : 1;
589 if (((gStyle.m_gradient>=1 && gStyle.m_gradient<=2) || gStyle.m_pattern) &&
590 gStyle.m_colors[0].isSet() && gStyle.m_colors[1].isSet())
591 style.setBackgroundColor(MWAWColor::barycenter(0.5, gStyle.m_colors[0].get(),
592 0.5, gStyle.m_colors[1].get()),
593 0.5f*gStyle.m_colorsAlpha[0]+0.5f*gStyle.m_colorsAlpha[1]);
594 else if (gStyle.m_colors[0].isSet())
595 style.setBackgroundColor(gStyle.m_colors[0].get(), alpha);
596 return true;
597 }
598
updateSurfaceStyle(int gId,MWAWGraphicStyle & style) const599 bool RagTime5StyleManager::updateSurfaceStyle(int gId, MWAWGraphicStyle &style) const
600 {
601 if (gId<=0 || gId>=static_cast<int>(m_state->m_graphicStyleList.size())) {
602 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateSurfaceStyle: can not find graphic style %d\n", gId));
603 return false;
604 }
605 auto const &gStyle=m_state->m_graphicStyleList[size_t(gId)];
606 if (gStyle.m_colorsAlpha[0]<=0 && gStyle.m_colorsAlpha[0]>=0)
607 return true;
608 float alpha=gStyle.m_colorsAlpha[0]>=0 ? gStyle.m_colorsAlpha[0] : 1;
609 if (gStyle.m_gradient>=1 && gStyle.m_gradient<=2) {
610 auto &finalGrad=style.m_gradient;
611 finalGrad.m_type=gStyle.m_gradient==2 ? MWAWGraphicStyle::Gradient::G_Radial : MWAWGraphicStyle::Gradient::G_Linear;
612 finalGrad.m_stopList.resize(0);
613 if (gStyle.m_gradient==1)
614 finalGrad.m_stopList.push_back(MWAWGraphicStyle::Gradient::Stop(0, MWAWColor::white()));
615 else
616 finalGrad.m_stopList.push_back(MWAWGraphicStyle::Gradient::Stop(0, gStyle.m_colors[0].get()));
617 finalGrad.m_stopList.push_back(MWAWGraphicStyle::Gradient::Stop(1, gStyle.m_colors[1].get()));
618 if (gStyle.m_gradientCenter.isSet())
619 finalGrad.m_percentCenter=*gStyle.m_gradientCenter;
620 if (gStyle.m_gradientRotation>-1000)
621 finalGrad.m_angle=gStyle.m_gradientRotation+90;
622 }
623 else if (gStyle.m_pattern) {
624 auto pat=*gStyle.m_pattern;
625 if (gStyle.m_colors[0].isSet())
626 pat.m_colors[1]=*gStyle.m_colors[0];
627 if (gStyle.m_colors[1].isSet())
628 pat.m_colors[0]=*gStyle.m_colors[1];
629 style.setPattern(pat, alpha);
630 }
631 else if (gStyle.m_colors[0].isSet())
632 style.setSurfaceColor(gStyle.m_colors[0].get(), alpha);
633 return true;
634 }
635
readTextStyles(RagTime5ClusterManager::Cluster & cluster)636 bool RagTime5StyleManager::readTextStyles(RagTime5ClusterManager::Cluster &cluster)
637 {
638 RagTime5StyleManagerInternal::TextFieldParser fieldParser;
639 if (!m_document.readStructZone(cluster.m_dataLink, fieldParser, 14, &cluster.m_nameLink))
640 return false;
641
642 if (fieldParser.m_styleList.empty())
643 fieldParser.m_styleList.resize(1);
644
645 //
646 // check parent relation, check for loop, ...
647 //
648 std::vector<size_t> rootList;
649 std::stack<size_t> toCheck;
650 std::multimap<size_t, size_t> idToChildIpMap;
651 auto numStyles=size_t(fieldParser.m_styleList.size());
652 for (size_t i=0; i<numStyles; ++i) {
653 RagTime5StyleManager::TextStyle &style=fieldParser.m_styleList[i];
654 if (!style.m_fontName.empty()) // update the font it
655 style.m_fontId=m_parserState->m_fontConverter->getId(style.m_fontName.cstr());
656 bool ok=true;
657 for (auto &parentId : style.m_parentId) {
658 if (parentId<=0)
659 continue;
660 if (parentId>=static_cast<int>(numStyles)) {
661 MWAW_DEBUG_MSG(("RagTime5StyleManager::readTextStyles: find unexpected parent %d for style %d\n",
662 static_cast<int>(parentId), static_cast<int>(i)));
663 parentId=0;
664 continue;
665 }
666 ok=false;
667 idToChildIpMap.insert(std::multimap<size_t, size_t>::value_type(size_t(parentId),i));
668 }
669 if (!ok) continue;
670 rootList.push_back(i);
671 toCheck.push(i);
672 }
673 std::set<size_t> seens;
674 while (true) {
675 size_t posToCheck=0; // to make clang happy
676 if (!toCheck.empty()) {
677 posToCheck=toCheck.top();
678 toCheck.pop();
679 }
680 else if (seens.size()+1==numStyles)
681 break;
682 else {
683 bool ok=false;
684 for (size_t i=1; i<numStyles; ++i) {
685 if (seens.find(i)!=seens.end())
686 continue;
687 MWAW_DEBUG_MSG(("RagTime5StyleManager::readTextStyles: find unexpected root %d\n", static_cast<int>(i)));
688 posToCheck=i;
689 rootList.push_back(i);
690
691 auto &style=fieldParser.m_styleList[i];
692 style.m_parentId[0]=style.m_parentId[1]=0;
693 ok=true;
694 break;
695 }
696 if (!ok)
697 break;
698 }
699 if (seens.find(posToCheck)!=seens.end()) {
700 MWAW_DEBUG_MSG(("RagTime5StyleManager::readTextStyles: oops, %d is already seens\n", static_cast<int>(posToCheck)));
701 continue;
702 }
703 seens.insert(posToCheck);
704 auto childIt=idToChildIpMap.lower_bound(posToCheck);
705 std::vector<size_t> badChildList;
706 while (childIt!=idToChildIpMap.end() && childIt->first==posToCheck) {
707 size_t childId=childIt++->second;
708 if (seens.find(childId)!=seens.end()) {
709 MWAW_DEBUG_MSG(("RagTime5StyleManager::readTextStyles: find loop for child %d\n", static_cast<int>(childId)));
710 auto &style=fieldParser.m_styleList[childId];
711 if (style.m_parentId[0]==static_cast<int>(posToCheck))
712 style.m_parentId[0]=0;
713 if (style.m_parentId[1]==static_cast<int>(posToCheck))
714 style.m_parentId[1]=0;
715 badChildList.push_back(childId);
716 continue;
717 }
718 toCheck.push(childId);
719 }
720 for (auto badId : badChildList) {
721 childIt=idToChildIpMap.lower_bound(posToCheck);
722 while (childIt!=idToChildIpMap.end() && childIt->first==posToCheck) {
723 if (childIt->second==badId) {
724 idToChildIpMap.erase(childIt);
725 break;
726 }
727 ++childIt;
728 }
729 }
730 }
731
732 if (!m_state->m_textStyleList.empty()) {
733 MWAW_DEBUG_MSG(("RagTime5StyleManager::readTextStyles: Ooops, we already set some textStyles\n"));
734 }
735
736 // now let generate the final style
737 m_state->m_textStyleList.resize(numStyles);
738 seens.clear();
739 for (auto id : rootList) {
740 if (id>=numStyles) {
741 MWAW_DEBUG_MSG(("RagTime5StyleManager::readTextStyles: find loop for id=%d\n", static_cast<int>(id)));
742 continue;
743 }
744 updateTextStyles(id, fieldParser.m_styleList[id], fieldParser.m_styleList, idToChildIpMap, seens);
745 }
746 return true;
747 }
748
updateTextStyles(size_t id,RagTime5StyleManager::TextStyle const & style,std::vector<RagTime5StyleManager::TextStyle> const & listReadStyles,std::multimap<size_t,size_t> const & idToChildIpMap,std::set<size_t> & seens)749 void RagTime5StyleManager::updateTextStyles
750 (size_t id, RagTime5StyleManager::TextStyle const &style, std::vector<RagTime5StyleManager::TextStyle> const &listReadStyles,
751 std::multimap<size_t, size_t> const &idToChildIpMap, std::set<size_t> &seens)
752 {
753 if (id>=m_state->m_textStyleList.size() || seens.find(id)!=seens.end()) {
754 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateTextStyles: problem with style with id=%d\n", static_cast<int>(id)));
755 return;
756 }
757 seens.insert(id);
758 auto styl=style;
759 styl.m_fontFlags[0]&=(~style.m_fontFlags[1]);
760 m_state->m_textStyleList[id]=styl;
761
762 auto childIt=idToChildIpMap.lower_bound(id);
763 while (childIt!=idToChildIpMap.end() && childIt->first==id) {
764 size_t childId=childIt++->second;
765 if (childId>=listReadStyles.size()) {
766 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateTextStyles: problem with style with childId=%d\n", static_cast<int>(childId)));
767 continue;
768 }
769 auto childStyle=styl;
770 childStyle.insert(listReadStyles[childId]);
771 updateTextStyles(childId, childStyle, listReadStyles, idToChildIpMap, seens);
772 }
773 }
774
updateTextStyles(int tId,MWAWFont & font,MWAWParagraph & para,MWAWSection & section,double totalWidth) const775 bool RagTime5StyleManager::updateTextStyles(int tId, MWAWFont &font, MWAWParagraph ¶, MWAWSection §ion, double totalWidth) const
776 {
777 font=MWAWFont();
778 para=MWAWParagraph();
779 section=MWAWSection();
780
781 if (tId<=0 || tId>=static_cast<int>(m_state->m_textStyleList.size())) {
782 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateTextStyles: can not find text style %d\n", tId));
783 return false;
784 }
785 auto const &style=m_state->m_textStyleList[size_t(tId)];
786 if (style.m_fontId>0) font.setId(style.m_fontId);
787 if (style.m_fontSize>0) font.setSize(float(style.m_fontSize));
788
789 MWAWFont::Line underline(MWAWFont::Line::None);
790 uint32_t flag=style.m_fontFlags[0];
791 uint32_t flags=0;
792 if (flag&0x1) flags |= MWAWFont::boldBit;
793 if (flag&0x2) flags |= MWAWFont::italicBit;
794 if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple); // checkme
795 if (flag&0x8) flags |= MWAWFont::embossBit;
796 if (flag&0x10) flags |= MWAWFont::shadowBit;
797
798 if (flag&0x200) font.setStrikeOutStyle(MWAWFont::Line::Simple);
799 if (flag&0x400) flags |= MWAWFont::smallCapsBit;
800 // flag&0x800: kumorarya
801 if (flag&0x2000)
802 underline.m_word=true;
803 switch (style.m_caps) {
804 case 1:
805 flags |= MWAWFont::uppercaseBit;
806 break;
807 case 2:
808 flags |= MWAWFont::lowercaseBit;
809 break;
810 case 3:
811 flags |= MWAWFont::initialcaseBit;
812 break;
813 default:
814 break;
815 }
816 switch (style.m_underline) {
817 case 1:
818 underline.m_style=MWAWFont::Line::Simple;
819 font.setUnderline(underline);
820 break;
821 case 2:
822 underline.m_style=MWAWFont::Line::Simple;
823 underline.m_type=MWAWFont::Line::Double;
824 font.setUnderline(underline);
825 break;
826 default:
827 break;
828 }
829 if (style.m_letterSpacings[0]>0 || style.m_letterSpacings[0]<0)
830 font.setDeltaLetterSpacing(float(1+style.m_letterSpacings[0]), librevenge::RVNG_PERCENT);
831 if (style.m_widthStreching>0)
832 font.setWidthStreching(float(style.m_widthStreching));
833 if (style.m_scriptPosition.isSet() || style.m_fontScaling>=0) {
834 float scaling=style.m_fontScaling>0 ? style.m_fontScaling : 1;
835 font.set(MWAWFont::Script(*style.m_scriptPosition*100,librevenge::RVNG_PERCENT,int(scaling*100)));
836 }
837 if (style.m_language>0) {
838 std::string lang=TextStyle::getLanguageLocale(style.m_language);
839 if (!lang.empty())
840 font.setLanguage(lang);
841 }
842 font.setFlags(flags);
843 MWAWColor color;
844 if (style.m_graphStyleId>0 && getLineColor(style.m_graphStyleId, color))
845 font.setColor(color);
846
847 //
848 // para
849 //
850 if (style.m_keepWithNext.isSet() && *style.m_keepWithNext)
851 para.m_breakStatus = para.m_breakStatus.get()|MWAWParagraph::NoBreakWithNextBit;
852 switch (style.m_justify) {
853 case 0:
854 break;
855 case 1:
856 para.m_justify = MWAWParagraph::JustificationCenter;
857 break;
858 case 2:
859 para.m_justify = MWAWParagraph::JustificationRight ;
860 break;
861 case 3:
862 para.m_justify = MWAWParagraph::JustificationFull;
863 break;
864 case 4:
865 para.m_justify = MWAWParagraph::JustificationFullAllLines;
866 break;
867 default:
868 break;
869 }
870 // TODO: use style.m_breakMethod
871 para.m_marginsUnit=librevenge::RVNG_POINT;
872 for (int i=0; i<3; ++i) {
873 if (style.m_margins[i]<0) continue;
874 if (i==2)
875 para.m_margins[0]=style.m_margins[2]-*para.m_margins[1];
876 else
877 para.m_margins[i+1] = style.m_margins[i];
878 }
879 if (style.m_spacings[0]>0) {
880 if (style.m_spacingUnits[0]==0)
881 para.setInterline(style.m_spacings[0], librevenge::RVNG_PERCENT);
882 else if (style.m_spacingUnits[0]==1)
883 para.setInterline(style.m_spacings[0], librevenge::RVNG_POINT);
884 }
885 for (int i=1; i<3; ++i) {
886 if (style.m_spacings[i]<0) continue;
887 if (style.m_spacingUnits[i]==0)
888 para.m_spacings[i]=style.m_spacings[i]*12./72.;
889 else if (style.m_spacingUnits[0]==1)
890 para.m_spacings[i]=style.m_spacings[i]/72.;
891 }
892 // tabs stop
893 for (auto const &tab : style.m_tabList) {
894 MWAWTabStop newTab;
895 newTab.m_position = double(tab.m_position)/72.;
896 switch (tab.m_type) {
897 case 2:
898 case 5: // kintou waritsuke
899 newTab.m_alignment = MWAWTabStop::CENTER;
900 break;
901 case 3:
902 newTab.m_alignment = MWAWTabStop::RIGHT;
903 break;
904 case 4:
905 newTab.m_alignment = MWAWTabStop::DECIMAL;
906 break;
907 case 1: // left
908 default:
909 break;
910 }
911 newTab.m_leaderCharacter=tab.m_leaderChar;
912 para.m_tabs->push_back(newTab);
913 }
914 if (totalWidth>0 && style.m_numColumns>1)
915 section.setColumns(style.m_numColumns, totalWidth/double(style.m_numColumns), librevenge::RVNG_POINT, style.m_columnGap>0 ? style.m_columnGap/72. : 0.05);
916 return true;
917 }
918
readFormats(RagTime5ClusterManager::Cluster & cluster)919 bool RagTime5StyleManager::readFormats(RagTime5ClusterManager::Cluster &cluster)
920 {
921 RagTime5ClusterManager::Link const &link=cluster.m_dataLink;
922 if (link.m_ids.size()<2 || !link.m_ids[1])
923 return false;
924
925 std::map<int, librevenge::RVNGString> idToNameMap;
926 if (!cluster.m_nameLink.empty()) {
927 m_document.readUnicodeStringList(cluster.m_nameLink, idToNameMap);
928 cluster.m_nameLink=RagTime5ClusterManager::NameLink();
929 }
930 std::vector<long> decal;
931 if (link.m_ids[0])
932 m_document.readPositions(link.m_ids[0], decal);
933 if (decal.empty())
934 decal=link.m_longList;
935 int const dataId=link.m_ids[1];
936 auto dataZone=m_document.getDataZone(dataId);
937 auto N=int(decal.size());
938
939 if (!dataZone || !dataZone->m_entry.valid() ||
940 dataZone->getKindLastPart(dataZone->m_kinds[1].empty())!="ItemData" || N<=1) {
941 if (N==1 && dataZone && !dataZone->m_entry.valid()) {
942 // a zone with 0 zone is ok...
943 dataZone->m_isParsed=true;
944 return true;
945 }
946 MWAW_DEBUG_MSG(("RagTime5StyleManager::readFormats: the data zone %d seems bad\n", dataId));
947 return false;
948 }
949
950 dataZone->m_isParsed=true;
951 MWAWEntry entry=dataZone->m_entry;
952 libmwaw::DebugFile &ascFile=dataZone->ascii();
953 libmwaw::DebugStream f;
954 f << "Entries(FormatDef)[" << *dataZone << "]:";
955 ascFile.addPos(entry.end());
956 ascFile.addNote("_");
957 ascFile.addPos(entry.begin());
958 ascFile.addNote(f.str().c_str());
959
960 MWAWInputStreamPtr input=dataZone->getInput();
961 input->setReadInverted(!dataZone->m_hiLoEndian);
962 long debPos=entry.begin();
963 long endPos=entry.end();
964 if (!input->checkPosition(endPos)) {
965 MWAW_DEBUG_MSG(("RagTime5StyleManager::readFormats:bad endPos\n"));
966 return false;
967 }
968 m_state->m_formatList.resize(size_t(N ? N-1 : 0));
969 for (int i=1; i<N; ++i) {
970 long pos=debPos+decal[size_t(i-1)], endDPos=debPos+decal[size_t(i)];
971 if (pos==endDPos) continue;
972 if (pos<debPos || endDPos>endPos || endDPos-pos<4) {
973 MWAW_DEBUG_MSG(("RagTime5StyleManager::readFormats: can not read the data zone %d-%d seems bad\n", dataId, i));
974 continue;
975 }
976 input->seek(pos, librevenge::RVNG_SEEK_SET);
977 f.str("");
978 f << "FormatDef-Fo" << i << ":";
979 auto val=static_cast<int>(input->readLong(4));
980 if (val) f << "num[used]=" << val << ",";
981 if (endDPos-pos<10) {
982 if (endDPos!=pos+4) f << "###";
983 ascFile.addPos(pos);
984 ascFile.addNote(f.str().c_str());
985 continue;
986 }
987 auto nId=static_cast<int>(input->readLong(2));
988 if (idToNameMap.find(i)!=idToNameMap.end())
989 f << "\"" << idToNameMap.find(i)->second.cstr() << "\",";
990 else {
991 MWAW_DEBUG_MSG(("RagTime5StyleManager::readFormats: can not find the format name for zone %d\n", dataId));
992 f << "###name[id]=" << nId << ",";
993 }
994 auto numFormat=static_cast<int>(input->readLong(1));
995 if (numFormat!=1)
996 f << "numFormat=" << numFormat << ",";
997 auto type=static_cast<int>(input->readLong(1)); // 6, 10 abd one time 4(slide number) and 14(unknown)
998 if (type==10) f << "dateTime,";
999 else if (type!=6) f << "#type=" << type << ",";
1000 for (int fo=0; fo<numFormat; ++fo) {
1001 MWAWCell::Format format;
1002 f << "form" << fo << "=[";
1003 auto type2=static_cast<int>(input->readULong(1));
1004 bool isDateTime=false, isMoneyThousand=false, isCurrency=false;
1005 switch (type2) {
1006 case 0:
1007 f << "general,";
1008 format.m_format=MWAWCell::F_NUMBER;
1009 format.m_numberFormat=MWAWCell::F_NUMBER_GENERIC;
1010 break;
1011 case 1: // number normal
1012 format.m_format=MWAWCell::F_NUMBER;
1013 format.m_numberFormat=MWAWCell::F_NUMBER_DECIMAL;
1014 break;
1015 case 4:
1016 f << "money/thousand,";
1017 format.m_format=MWAWCell::F_NUMBER;
1018 format.m_numberFormat=MWAWCell::F_NUMBER_DECIMAL;
1019 isMoneyThousand=true;
1020 break;
1021 default:
1022 isDateTime=true;
1023 format.m_format=MWAWCell::F_DATE; // or time
1024 if (type2&0x80) f << "%a";
1025 if (type2&0x40) f << "%y";
1026 if (type2&0x20) f << "%m";
1027 if (type2&8) f << "%d";
1028 if (type2&4) f << "%H";
1029 if (type2&2) f << "%M";
1030 if (type2&1) f << "%S";
1031 if (type2&0x10)
1032 f << "#type2[high]";
1033 f << ",";
1034 break;
1035 }
1036 val=static_cast<int>(input->readULong(1));
1037 if (val) f << "num[decim]=" << val << ",";
1038 if (format.m_format==MWAWCell::F_NUMBER && format.m_numberFormat!=MWAWCell::F_NUMBER_GENERIC)
1039 format.m_digits=val;
1040 for (int j=0; j<4; ++j) {
1041 val=static_cast<int>(input->readULong(1));
1042 if (val) f << "fl" << j << "=" << std::hex << val << std::dec << ",";
1043 }
1044 auto fSz=static_cast<int>(input->readULong(1));
1045 if (input->tell()+fSz>endDPos) {
1046 MWAW_DEBUG_MSG(("RagTime5StyleManager::readFormats: can not read the string format zone %d\n", dataId));
1047 f << "###fSz=" << fSz << ",";
1048 break;
1049 }
1050 f << "format=\"";
1051 for (int j=0; j<fSz; ++j) {
1052 val=static_cast<int>(input->readULong(1));
1053 if (isMoneyThousand && val!=2 && val!=3 && val!=5 && !isCurrency)
1054 isCurrency=true;
1055 switch (val) {
1056 case 1: // general digit
1057 f << "*";
1058 break;
1059 case 2: // decimal digit
1060 f << "0";
1061 break;
1062 case 3: // potential digit (ie. diese)
1063 f << "1";
1064 break;
1065 case 5: // commas
1066 f << ".";
1067 if (isDateTime)
1068 format.m_DTFormat.append(".");
1069 break;
1070 case 6:
1071 if (isDateTime)
1072 format.m_DTFormat.append("%y");
1073 f << "%y";
1074 break;
1075 case 7: // year or fraction
1076 if (isDateTime) {
1077 format.m_DTFormat.append("%Y");
1078 f << "%Y";
1079 break;
1080 }
1081 f << "/";
1082 if (format.m_format==MWAWCell::F_NUMBER && format.m_numberFormat==MWAWCell::F_NUMBER_DECIMAL)
1083 format.m_numberFormat=MWAWCell::F_NUMBER_FRACTION;
1084 break;
1085 case 8:
1086 if (isDateTime)
1087 format.m_DTFormat.append("%m");
1088 f << "%m";
1089 break;
1090 case 9: // month with two digits
1091 if (isDateTime)
1092 format.m_DTFormat.append("%m");
1093 f << "%0m";
1094 break;
1095 case 0xa: // month abbrev or exponant
1096 if (isDateTime) {
1097 format.m_DTFormat.append("%b");
1098 f << "%b";
1099 break;
1100 }
1101 f << "e";
1102 if (format.m_format==MWAWCell::F_NUMBER && format.m_numberFormat==MWAWCell::F_NUMBER_DECIMAL)
1103 format.m_numberFormat=MWAWCell::F_NUMBER_SCIENTIFIC;
1104 break;
1105 case 0xb: // month
1106 if (isDateTime)
1107 format.m_DTFormat.append("%B");
1108 f << "%B";
1109 break;
1110 case 0xc: // day or percent
1111 if (isDateTime) {
1112 format.m_DTFormat.append("%d");
1113 f << "%d";
1114 break;
1115 }
1116 f << "%";
1117 if (format.m_format==MWAWCell::F_NUMBER && format.m_numberFormat==MWAWCell::F_NUMBER_DECIMAL)
1118 format.m_numberFormat=MWAWCell::F_NUMBER_PERCENT;
1119 break;
1120 case 0xd: // day 2 digits
1121 if (isDateTime)
1122 format.m_DTFormat.append("%d");
1123 f << "%0d";
1124 break;
1125 case 0xe: // checkme
1126 if (isDateTime)
1127 format.m_DTFormat.append("%a");
1128 f << "%a";
1129 break;
1130 case 0xf:
1131 if (isDateTime)
1132 format.m_DTFormat.append("%A");
1133 f << "%A";
1134 break;
1135 case 0x10: // pm (precedeed by c0)
1136 if (isDateTime)
1137 format.m_DTFormat.append("%p");
1138 f << "%p";
1139 break;
1140 case 0x14: // hour
1141 if (isDateTime)
1142 format.m_DTFormat.append("%H");
1143 f << "%0H";
1144 break;
1145 case 0x15:
1146 if (isDateTime)
1147 format.m_DTFormat.append("%H");
1148 f << "%H";
1149 break;
1150 case 0x16:
1151 if (isDateTime)
1152 format.m_DTFormat.append("%M");
1153 f << "%0M";
1154 break;
1155 case 0x17: // minute
1156 if (isDateTime)
1157 format.m_DTFormat.append("%M");
1158 f << "%M";
1159 break;
1160 case 0x19: // second
1161 if (isDateTime)
1162 format.m_DTFormat.append("%S");
1163 f << "%S";
1164 break;
1165 case 0x1f:
1166 if (isDateTime)
1167 format.m_DTFormat.append("%p");
1168 f << "%p";
1169 break;
1170 case 0xa3: // pound symbol
1171 f << "[pound]";
1172 break;
1173 case 0xc0: // pm/am condition?
1174 if (j+1>=fSz) {
1175 f << "[##c0]";
1176 break;
1177 }
1178 break;
1179 case 0xfd: // parenthesis delimiter ?
1180 if (j+1>=fSz) {
1181 f << "[##fd]";
1182 break;
1183 }
1184 ++j;
1185 input->seek(1, librevenge::RVNG_SEEK_CUR);
1186 break;
1187 case 0xff: // unicode
1188 if (j+2>=fSz) {
1189 f << "[##ff]";
1190 break;
1191 }
1192 j+=2;
1193 f << "[U" << std::hex << input->readULong(2) << std::dec << "]";
1194 break;
1195 default:
1196 if (val>=0x20 && val<0x80) {
1197 f << char(val);
1198 if (isDateTime)
1199 format.m_DTFormat+=char(val);
1200 else if (format.m_format==MWAWCell::F_NUMBER && val=='(')
1201 format.m_parenthesesForNegative=true;
1202 }
1203 else
1204 f << "[#" << std::hex << val << std::dec << "]";
1205 break;
1206 }
1207 }
1208 f << "\",";
1209 f << "],";
1210 if (isCurrency)
1211 format.m_numberFormat=MWAWCell::F_NUMBER_CURRENCY;
1212 else if (isMoneyThousand)
1213 format.m_thousandHasSeparator=true;
1214 if (fo==0)
1215 m_state->m_formatList[size_t(i-1)]=format;
1216 }
1217 f << "],";
1218
1219 if (input->tell()!=endDPos)
1220 ascFile.addDelimiter(input->tell(),'|');
1221 ascFile.addPos(pos);
1222 ascFile.addNote(f.str().c_str());
1223 }
1224
1225 input->setReadInverted(false);
1226
1227 for (auto lnk : cluster.m_linksList) {
1228 lnk.m_name=std::string("FormatUnkn")+(lnk.m_fileType[0]==0x3e800 ? "A" : lnk.m_fileType[0]==0x35800 ? "B" : lnk.getZoneName().c_str());
1229 if (lnk.m_fileType[0]==0x3e800 || lnk.m_fileType[0]==0x35800) {
1230 /* rare only find in two files,
1231 FormA: list of 0 or small int: next list?,
1232 FormB: list of 0, 80000000 or small int: prev list ?
1233 when the value are small ints, FormB(FormA(val)+1)=val
1234 */
1235 std::vector<long> data;
1236 m_document.readLongList(lnk, data);
1237 }
1238 else
1239 m_document.readFixedSizeZone(lnk, lnk.m_name);
1240 }
1241
1242 return true;
1243 }
1244
updateCellFormat(int formatId,MWAWCell & cell) const1245 bool RagTime5StyleManager::updateCellFormat(int formatId, MWAWCell &cell) const
1246 {
1247 if (formatId<=0 || formatId>static_cast<int>(m_state->m_formatList.size())) {
1248 MWAW_DEBUG_MSG(("RagTime5StyleManager::updateCellFormat: can not find format %d\n", formatId));
1249 return false;
1250 }
1251 auto format=m_state->m_formatList[size_t(formatId-1)];
1252 auto cellType=cell.getFormat().m_format;
1253 if (cellType==format.m_format && (cellType==MWAWCell::F_NUMBER || cellType==MWAWCell::F_DATE))
1254 cell.setFormat(format);
1255 else if (cellType==MWAWCell::F_TIME && format.m_format==MWAWCell::F_DATE) {
1256 format.m_format=MWAWCell::F_TIME;
1257 cell.setFormat(format);
1258 }
1259 return true;
1260 }
1261
1262 ////////////////////////////////////////////////////////////
1263 // parse cluster
1264 ////////////////////////////////////////////////////////////
1265
1266 //
1267 // graphic style
1268 //
~GraphicStyle()1269 RagTime5StyleManager::GraphicStyle::~GraphicStyle()
1270 {
1271 }
1272
read(MWAWInputStreamPtr & input,RagTime5StructManager::Field const & field,std::vector<MWAWColor> const & colorList)1273 bool RagTime5StyleManager::GraphicStyle::read(MWAWInputStreamPtr &input, RagTime5StructManager::Field const &field, std::vector<MWAWColor> const &colorList)
1274 {
1275 std::stringstream s;
1276 if (field.m_type==RagTime5StructManager::Field::T_Long) { // header
1277 switch (field.m_fileType) {
1278 case 0x148c042: // -2<->8
1279 if (field.m_longValue[0])
1280 s << "H" << RagTime5StyleManager::printType(field.m_fileType) << "=" << field.m_longValue[0] << ",";
1281 else
1282 s << "H" << RagTime5StyleManager::printType(field.m_fileType) << ",";
1283 m_extra+=s.str();
1284 return true;
1285 case 0x1460042: // -3-23
1286 s << "lineStyle,";
1287 if (field.m_longValue[0]!=-3)
1288 s << "pId?=" << field.m_longValue[0] << ",";
1289 m_extra += s.str();
1290 return true;
1291 case 0x145e042: // -2<->24 : fill style CHECKME related to parent id?
1292 case 0x1489842: // -2<->19
1293 m_parentId=static_cast<int>(field.m_longValue[0]);
1294 return true;
1295 default:
1296 return false;
1297 }
1298 }
1299 else if (field.m_type==RagTime5StructManager::Field::T_FieldList) {
1300 switch (field.m_fileType) {
1301 case 0x7d02a:
1302 case 0x145e05a: {
1303 int wh=field.m_fileType==0x7d02a ? 0 : 1;
1304 for (auto const &child : field.m_fieldList) {
1305 if (child.m_type==RagTime5StructManager::Field::T_Color && child.m_fileType==0x84040) {
1306 if (child.m_longValue[0]==50) {
1307 if (!updateColor(field.m_fileType==0x7d02a, int(child.m_longValue[1])+1, colorList)) {
1308 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown color %ld block\n", child.m_longValue[1]+1));
1309 s << "###";
1310 }
1311 s << "col=GC" << child.m_longValue[1]+1 << ",";
1312 continue;
1313 }
1314 m_colors[wh]=child.m_color;
1315 m_colorsAlpha[wh]=1; // checkme
1316 continue;
1317 }
1318 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown color %d block\n", wh));
1319 s << "##col[" << wh << "]=" << child << ",";
1320 }
1321 m_extra+=s.str();
1322 return true;
1323 }
1324 case 0x145e02a:
1325 case 0x145e0ea: {
1326 int wh=field.m_fileType==0x145e02a ? 0 : 1;
1327 for (auto const &child : field.m_fieldList) {
1328 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0xb6000) {
1329 m_colorsAlpha[wh]=float(child.m_doubleValue);
1330 continue;
1331 }
1332 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown colorAlpha[%d] block\n", wh));
1333 s << "###colorAlpha[" << wh << "]=" << child << ",";
1334 }
1335 m_extra+=s.str();
1336 return true;
1337 }
1338 case 0x145e01a: {
1339 for (auto const &child : field.m_fieldList) {
1340 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x147c080) {
1341 if (m_parentId>-1000) {
1342 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: parent id is already set\n"));
1343 s << "###newParentId,";
1344 }
1345 m_parentId=static_cast<int>(child.m_longValue[0]);
1346 continue;
1347 }
1348 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown parent block\n"));
1349 s << "###parent=" << child << ",";
1350 }
1351 m_extra+=s.str();
1352 return true;
1353 }
1354 case 0x7d04a:
1355 for (auto const &child : field.m_fieldList) {
1356 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0x1494800) {
1357 m_width=float(child.m_doubleValue);
1358 continue;
1359 }
1360 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown width block\n"));
1361 s << "###w=" << child << ",";
1362 }
1363 m_extra+=s.str();
1364 return true;
1365 case 0x145e0ba: {
1366 for (auto const &child : field.m_fieldList) {
1367 if (child.m_type==RagTime5StructManager::Field::T_Bool && child.m_fileType==0x360c0) {
1368 m_hidden=child.m_longValue[0]!=0;
1369 continue;
1370 }
1371 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown no print block\n"));
1372 s << "###hidden=" << child << ",";
1373 }
1374 m_extra+=s.str();
1375 return true;
1376 }
1377
1378 case 0x14600ca:
1379 for (auto const &child : field.m_fieldList) {
1380 if (child.m_type==RagTime5StructManager::Field::T_LongList && child.m_fileType==(unsigned long)(long(0x80033000))) {
1381 m_dash=child.m_longList;
1382 continue;
1383 }
1384 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown dash block\n"));
1385 s << "###dash=" << child << ",";
1386 }
1387 m_extra+=s.str();
1388 return true;
1389 case 0x146005a:
1390 for (auto const &child : field.m_fieldList) {
1391 if (child.m_type==RagTime5StructManager::Field::T_Code && child.m_fileType==0x8d000) {
1392 if (child.m_string=="LiOu")
1393 m_position=3;
1394 else if (child.m_string=="LiCe") // checkme
1395 m_position=2;
1396 else if (child.m_string=="LiIn")
1397 m_position=1;
1398 else if (child.m_string=="LiRo")
1399 m_position=4;
1400 else {
1401 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown position string %s\n", child.m_string.cstr()));
1402 s << "##pos=" << child.m_string.cstr() << ",";
1403 }
1404 continue;
1405 }
1406 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown position block\n"));
1407 s << "###pos=" << child << ",";
1408 }
1409 m_extra+=s.str();
1410 return true;
1411 case 0x146007a:
1412 for (auto const &child : field.m_fieldList) {
1413 if (child.m_type==RagTime5StructManager::Field::T_Code && child.m_fileType==0x8d000) {
1414 if (child.m_string=="LiRo")
1415 m_mitter=2;
1416 else if (child.m_string=="LiBe")
1417 m_mitter=3;
1418 else {
1419 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown mitter string %s\n", child.m_string.cstr()));
1420 s << "##mitter=" << child.m_string.cstr() << ",";
1421 }
1422 continue;
1423 }
1424 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown mitter block\n"));
1425 s << "###mitter=" << child << ",";
1426 }
1427 m_extra+=s.str();
1428 return true;
1429 case 0x148981a:
1430 for (auto const &child : field.m_fieldList) {
1431 if (child.m_type==RagTime5StructManager::Field::T_Code && child.m_fileType==0x8d000) {
1432 if (child.m_string=="GrNo")
1433 m_gradient=1;
1434 else if (child.m_string=="GrRa")
1435 m_gradient=2;
1436 else {
1437 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown gradient string %s\n", child.m_string.cstr()));
1438 s << "##gradient=" << child.m_string.cstr() << ",";
1439 }
1440 continue;
1441 }
1442 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown gradient block\n"));
1443 s << "###gradient=" << child << ",";
1444 }
1445 m_extra+=s.str();
1446 return true;
1447 case 0x14600aa:
1448 for (auto const &child : field.m_fieldList) {
1449 if (child.m_type==RagTime5StructManager::Field::T_Code && child.m_fileType==0x8d000) {
1450 if (child.m_string=="CaRo")
1451 m_cap=2;
1452 else if (child.m_string=="CaSq")
1453 m_cap=3;
1454 else {
1455 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown cap string %s\n", child.m_string.cstr()));
1456 s << "##cap=" << child.m_string.cstr() << ",";
1457 }
1458 continue;
1459 }
1460 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown cap block\n"));
1461 s << "###cap=" << child << ",";
1462 }
1463 m_extra+=s.str();
1464 return true;
1465 case 0x148985a: // checkme
1466 for (auto const &child : field.m_fieldList) {
1467 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0x1495800) {
1468 m_gradientRotation=float(360*child.m_doubleValue);
1469 continue;
1470 }
1471 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown grad rotation block\n"));
1472 s << "###rot[grad]=" << child << ",";
1473 }
1474 m_extra+=s.str();
1475 return true;
1476 case 0x148983a: // checkme
1477 for (auto const &child : field.m_fieldList) {
1478 if (child.m_type==RagTime5StructManager::Field::T_DoubleList && child.m_doubleList.size()==2 && child.m_fileType==0x74040) {
1479 m_gradientCenter=MWAWVec2f(float(child.m_doubleList[0]), float(child.m_doubleList[1]));
1480 continue;
1481 }
1482 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown grad center block\n"));
1483 s << "###rot[center]=" << child << ",";
1484 }
1485 m_extra+=s.str();
1486 return true;
1487 case 0x146008a:
1488 for (auto const &child : field.m_fieldList) {
1489 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0xb6000) {
1490 m_limitPercent=float(child.m_doubleValue);
1491 continue;
1492 }
1493 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown limit percent block\n"));
1494 s << "###limitPercent=" << child << ",";
1495 }
1496 m_extra+=s.str();
1497 return true;
1498 // unknown small id
1499 case 0x145e11a: // frequent
1500 case 0x145e12a: { // unknown small int 2|3
1501 for (auto const &child : field.m_fieldList) {
1502 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x17d5880) {
1503 if (!updateColor(field.m_fileType==0x145e11a, int(child.m_longValue[0]), colorList)) {
1504 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown color %ld block\n", child.m_longValue[0]));
1505 s << "###";
1506 }
1507 s << "col=GC" << child.m_longValue[0] << ",";
1508 continue;
1509 }
1510 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some unknown unkn0 block\n"));
1511 s << "###unkn0=" << child << ",";
1512 }
1513 m_extra+=s.str();
1514 return true;
1515 }
1516 default:
1517 break;
1518 }
1519 }
1520 else if (field.m_type==RagTime5StructManager::Field::T_Unstructured) {
1521 switch (field.m_fileType) {
1522 case 0x148c01a: {
1523 if (field.m_entry.length()!=12) {
1524 MWAW_DEBUG_MSG(("RagTime5StyleManager::GraphicStyle::read: find some odd size for pattern\n"));
1525 s << "##pattern=" << field << ",";
1526 m_extra+=s.str();
1527 return true;
1528 }
1529 input->seek(field.m_entry.begin(), librevenge::RVNG_SEEK_SET);
1530 for (int i=0; i<2; ++i) {
1531 static int const expected[]= {0xb, 0x40};
1532 auto val=static_cast<int>(input->readULong(2));
1533 if (val!=expected[i])
1534 s << "pat" << i << "=" << std::hex << val << std::dec << ",";
1535 }
1536 m_pattern.reset(new MWAWGraphicStyle::Pattern);
1537 m_pattern->m_colors[0]=MWAWColor::white();
1538 m_pattern->m_colors[1]=MWAWColor::black();
1539 m_pattern->m_dim=MWAWVec2i(8,8);
1540 m_pattern->m_data.resize(8);
1541 for (auto &data : m_pattern->m_data) data=static_cast<unsigned char>(input->readULong(1));
1542 m_extra+=s.str();
1543 return true;
1544 }
1545 default:
1546 break;
1547 }
1548 }
1549 return false;
1550 }
1551
updateColor(bool first,int colorId,std::vector<MWAWColor> const & colorList)1552 bool RagTime5StyleManager::GraphicStyle::updateColor(bool first, int colorId, std::vector<MWAWColor> const &colorList)
1553 {
1554 if (colorId>=1 && colorId <= int(colorList.size())) {
1555 auto const &color=colorList[size_t(colorId-1)];
1556 m_colors[first ? 0 : 1]=color;
1557 if (color.getAlpha()<255)
1558 m_colorsAlpha[first ? 0 : 1]=float(color.getAlpha())/255.f;
1559 return true;
1560 }
1561 return false;
1562 }
1563
insert(RagTime5StyleManager::GraphicStyle const & childStyle)1564 void RagTime5StyleManager::GraphicStyle::insert(RagTime5StyleManager::GraphicStyle const &childStyle)
1565 {
1566 if (childStyle.m_width>=0) m_width=childStyle.m_width;
1567 bool updateCol=true;
1568 if (childStyle.m_dash.isSet()) m_dash=childStyle.m_dash;
1569 if (childStyle.m_pattern) m_pattern=childStyle.m_pattern;
1570 if (childStyle.m_gradient>=0) m_gradient=childStyle.m_gradient;
1571 else if (m_gradient==1) updateCol=false; // we need to use the gradient color
1572 if (childStyle.m_gradientRotation>-1000) m_gradientRotation=childStyle.m_gradientRotation;
1573 if (childStyle.m_gradientCenter.isSet()) m_gradientCenter=childStyle.m_gradientCenter;
1574 if (childStyle.m_position>=0) m_position=childStyle.m_position;
1575 if (childStyle.m_cap>=0) m_cap=childStyle.m_cap;
1576 if (childStyle.m_mitter>=0) m_mitter=childStyle.m_mitter;
1577 if (childStyle.m_limitPercent>=0) m_limitPercent=childStyle.m_limitPercent;
1578 if (childStyle.m_hidden.isSet()) m_hidden=childStyle.m_hidden;
1579 if (updateCol) {
1580 if (childStyle.m_colors[0].isSet()) m_colors[0]=*childStyle.m_colors[0];
1581 if (childStyle.m_colors[1].isSet()) m_colors[1]=*childStyle.m_colors[1];
1582 for (int i=0; i<2; ++i) {
1583 if (childStyle.m_colorsAlpha[i]>=0)
1584 m_colorsAlpha[i]=childStyle.m_colorsAlpha[i];
1585 }
1586 }
1587 m_extra+=childStyle.m_extra;
1588 }
1589
operator <<(std::ostream & o,RagTime5StyleManager::GraphicStyle const & style)1590 std::ostream &operator<<(std::ostream &o, RagTime5StyleManager::GraphicStyle const &style)
1591 {
1592 if (style.m_parentId>-1000) {
1593 if (style.m_parentId<0)
1594 o << "parent=def" << -style.m_parentId << ",";
1595 else if (style.m_parentId)
1596 o << "parent=GS" << style.m_parentId << ",";
1597 }
1598 if (style.m_width>=0) o << "w=" << style.m_width << ",";
1599 if (style.m_colors[0].isSet()) o << "color0=" << *style.m_colors[0] << ",";
1600 if (style.m_colors[1].isSet()) o << "color1=" << *style.m_colors[1] << ",";
1601 for (int i=0; i<2; ++i) {
1602 if (style.m_colorsAlpha[i]>=0)
1603 o << "color" << i << "[alpha]=" << style.m_colorsAlpha[i] << ",";
1604 }
1605 if (style.m_dash.isSet()) {
1606 o << "dash=";
1607 for (auto dash : *style.m_dash)
1608 o << dash << ":";
1609 o << ",";
1610 }
1611 if (style.m_pattern)
1612 o << "pattern=[" << *style.m_pattern << "],";
1613 switch (style.m_gradient) {
1614 case -1:
1615 break;
1616 case 0:
1617 break;
1618 case 1:
1619 o << "grad[normal],";
1620 break;
1621 case 2:
1622 o << "grad[radial],";
1623 break;
1624 default:
1625 o<< "##gradient=" << style.m_gradient;
1626 break;
1627 }
1628 if (style.m_gradientRotation>-1000 && (style.m_gradientRotation<0 || style.m_gradientRotation>0))
1629 o << "rot[grad]=" << style.m_gradientRotation << ",";
1630 if (style.m_gradientCenter.isSet())
1631 o << "center[grad]=" << *style.m_gradientCenter << ",";
1632 switch (style.m_position) {
1633 case -1:
1634 break;
1635 case 1:
1636 o << "pos[inside],";
1637 break;
1638 case 2:
1639 break;
1640 case 3:
1641 o << "pos[outside],";
1642 break;
1643 case 4:
1644 o << "pos[round],";
1645 break;
1646 default:
1647 o << "#pos=" << style.m_position << ",";
1648 break;
1649 }
1650 switch (style.m_cap) {
1651 case -1:
1652 break;
1653 case 1: // triangle
1654 break;
1655 case 2:
1656 o << "cap[round],";
1657 break;
1658 case 3:
1659 o << "cap[square],";
1660 break;
1661 default:
1662 o << "#cap=" << style.m_cap << ",";
1663 break;
1664 }
1665 switch (style.m_mitter) {
1666 case -1:
1667 break;
1668 case 1: // no add
1669 break;
1670 case 2:
1671 o << "mitter[round],";
1672 break;
1673 case 3:
1674 o << "mitter[out],";
1675 break;
1676 default:
1677 o << "#mitter=" << style.m_mitter << ",";
1678 break;
1679 }
1680 if (style.m_limitPercent>=0 && style.m_limitPercent<1)
1681 o << "limit=" << 100*style.m_limitPercent << "%,";
1682 if (style.m_hidden.get())
1683 o << "hidden,";
1684 o << style.m_extra;
1685 return o;
1686 }
1687
1688 //
1689 // text style
1690 //
~TextStyle()1691 RagTime5StyleManager::TextStyle::~TextStyle()
1692 {
1693 }
1694
getLanguageLocale(int id)1695 std::string RagTime5StyleManager::TextStyle::getLanguageLocale(int id)
1696 {
1697 switch (id) {
1698 case 1:
1699 return "hr_HR";
1700 case 4:
1701 return "ru_RU";
1702 case 8:
1703 return "da_DK";
1704 case 9:
1705 return "sv_SE";
1706 case 0xa:
1707 return "nl_NL";
1708 case 0xb:
1709 return "fi_FI";
1710 case 0xc:
1711 return "it_IT";
1712 case 0xd: // initial accent
1713 case 0x800d:
1714 return "es_ES";
1715 case 0xf:
1716 return "gr_GR";
1717 case 0x11:
1718 return "ja_JP";
1719 case 0x16:
1720 return "tr_TR";
1721 case 0x4005:
1722 case 0x8005: // initial accent
1723 return "fr_FR";
1724 case 0x4006: // old?
1725 case 0x6006:
1726 return "de_CH";
1727 case 0x8006: // old?
1728 case 0xa006:
1729 return "de_DE";
1730 case 0x4007:
1731 return "en_GB";
1732 case 0x8007:
1733 return "en_US";
1734 case 0x400e:
1735 return "pt_BR";
1736 case 0x800e:
1737 return "pt_PT";
1738 case 0x4012:
1739 return "nn_NO";
1740 case 0x8012:
1741 return "no_NO";
1742 default:
1743 break;
1744 }
1745 return "";
1746 }
1747
read(RagTime5StructManager::Field const & field)1748 bool RagTime5StyleManager::TextStyle::read(RagTime5StructManager::Field const &field)
1749 {
1750 std::stringstream s;
1751 if (field.m_type==RagTime5StructManager::Field::T_Long) { // header
1752 switch (field.m_fileType) {
1753 case 0: // one time with 0
1754 return true;
1755 case 0x1475042: // -3<->32 : ?
1756 case 0x147e842: // always 0?
1757 case 0x14b2042: // always 0?
1758 if (field.m_longValue[0])
1759 s << "H" << RagTime5StyleManager::printType(field.m_fileType) << "=" << field.m_longValue[0] << ",";
1760 else
1761 s << "H" << RagTime5StyleManager::printType(field.m_fileType) << ",";
1762 m_extra+=s.str();
1763 return true;
1764 case 0x1474042: // -1<->39 : CHECKME related to parent id?
1765 s << "parent[id]?=" << field.m_longValue[0] << ",";
1766 m_extra+=s.str();
1767 return true;
1768 default:
1769 return false;
1770 }
1771 }
1772 else if (field.m_type==RagTime5StructManager::Field::T_FieldList) {
1773 switch (field.m_fileType) {
1774 case 0x7a0aa: // style parent id?
1775 case 0x1474042: // main parent id?
1776 case 0x147551a: { // find one time with 3
1777 int wh=field.m_fileType==0x1474042 ? 0 : 1;
1778 for (auto const &child : field.m_fieldList) {
1779 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x1479080) {
1780 if (field.m_fileType==0x147551a)
1781 s << "unkn[pId]=" << child.m_longValue[0] << ",";
1782 else
1783 m_parentId[wh]=static_cast<int>(child.m_longValue[0]);
1784 continue;
1785 }
1786 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown parent id[%d] block\n", wh));
1787 s << "###parent" << wh << "[id]=" << child << ",";
1788 }
1789 m_extra+=s.str();
1790 return true;
1791 }
1792 case 0x14741fa:
1793 for (auto const &child : field.m_fieldList) {
1794 if (child.m_type==RagTime5StructManager::Field::T_LongList && child.m_fileType==(unsigned long)(long(0x80045080))) {
1795 for (auto val : child.m_longList)
1796 m_linkIdList.push_back(static_cast<int>(val));
1797 continue;
1798 }
1799 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown link id block\n"));
1800 s << "###link[id]=" << child << ",";
1801 }
1802 m_extra+=s.str();
1803 return true;
1804 case 0x1469840:
1805 for (auto const &child : field.m_fieldList) {
1806 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x147b880) {
1807 m_dateStyleId=static_cast<int>(child.m_longValue[0]);
1808 continue;
1809 }
1810 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown date style block\n"));
1811 s << "###date[id]=" << child << ",";
1812 }
1813 m_extra+=s.str();
1814 return true;
1815 case 0x145e01a:
1816 case 0x14741ea:
1817 for (auto const &child : field.m_fieldList) {
1818 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x147c080) {
1819 if (field.m_fileType==0x145e01a)
1820 m_graphStyleId=static_cast<int>(child.m_longValue[0]);
1821 else
1822 m_graphLineStyleId=static_cast<int>(child.m_longValue[0]);
1823 continue;
1824 }
1825 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown graphic style block\n"));
1826 s << "###graph[" << RagTime5StyleManager::printType(field.m_fileType) << "]=" << child << ",";
1827 }
1828 m_extra+=s.str();
1829 return true;
1830
1831 //
1832 // para
1833 //
1834 case 0x14750ea:
1835 for (auto const &child : field.m_fieldList) {
1836 if (child.m_type==RagTime5StructManager::Field::T_Bool && child.m_fileType==0x360c0) {
1837 m_keepWithNext=child.m_longValue[0]!=0;
1838 continue;
1839 }
1840 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown keep with next block\n"));
1841 s << "###keep[withNext]=" << child << ",";
1842 }
1843 m_extra+=s.str();
1844 return true;
1845 case 0x147505a: // left margin
1846 case 0x147506a: // right margin
1847 case 0x147507a: { // first margin
1848 auto wh=int(((field.m_fileType&0xF0)>>4)-5);
1849 for (auto const &child : field.m_fieldList) {
1850 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0x1493800) {
1851 m_margins[wh]=child.m_doubleValue;
1852 continue;
1853 }
1854 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown margins[%d] block\n", wh));
1855 s << "###margins[" << wh << "]=" << child << ",";
1856 }
1857 m_extra+=s.str();
1858 return true;
1859 }
1860 case 0x147501a:
1861 for (auto const &child : field.m_fieldList) {
1862 if (child.m_type==RagTime5StructManager::Field::T_Code && child.m_fileType==0x8d000) {
1863 if (child.m_string=="----") // checkme
1864 m_justify=-1;
1865 else if (child.m_string=="left")
1866 m_justify=0;
1867 else if (child.m_string=="cent")
1868 m_justify=1;
1869 else if (child.m_string=="rght")
1870 m_justify=2;
1871 else if (child.m_string=="full")
1872 m_justify=3;
1873 else if (child.m_string=="fful")
1874 m_justify=4;
1875 // find also thgr
1876 else {
1877 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some justify block %s\n", child.m_string.cstr()));
1878 s << "##justify=" << child.m_string.cstr() << ",";
1879 }
1880 continue;
1881 }
1882 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown justify block\n"));
1883 s << "###justify=" << child << ",";
1884 }
1885 m_extra+=s.str();
1886 return true;
1887 case 0x147502a:
1888 case 0x14750aa:
1889 case 0x14750ba: {
1890 int wh=field.m_fileType==0x147502a ? 0 : field.m_fileType==0x14750aa ? 1 : 2;
1891 for (auto const &child : field.m_fieldList) {
1892 if (child.m_type==RagTime5StructManager::Field::T_LongDouble && child.m_fileType==0x149a940) {
1893 m_spacings[wh]=child.m_doubleValue;
1894 m_spacingUnits[wh]=static_cast<int>(child.m_longValue[0]);
1895 continue;
1896 }
1897 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown spacings %d block\n", wh));
1898 s << "###spacings[" << wh << "]=" << child << ",";
1899 }
1900 m_extra+=s.str();
1901 return true;
1902 }
1903 case 0x14752da:
1904 case 0x147536a:
1905 case 0x147538a: {
1906 int wh=field.m_fileType==0x14752da ? 0 : field.m_fileType==0x147536a ? 1 : 2;
1907 for (auto const &child : field.m_fieldList) {
1908 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0x1495000) {
1909 s << "delta[" << (wh==0 ? "interline" : wh==1 ? "before" : "after") << "]=" << child.m_doubleValue << ",";
1910 continue;
1911 }
1912 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown spacings delta %d block\n", wh));
1913 s << "###delta[spacings" << wh << "]=" << child << ",";
1914 }
1915 m_extra+=s.str();
1916 return true;
1917 }
1918 case 0x147530a:
1919 for (auto const &child : field.m_fieldList) {
1920 if (child.m_type==RagTime5StructManager::Field::T_Code && child.m_fileType==0x8d000) {
1921 if (child.m_string=="----") // checkme
1922 m_breakMethod=0;
1923 else if (child.m_string=="nxtC")
1924 m_breakMethod=1;
1925 else if (child.m_string=="nxtP")
1926 m_breakMethod=2;
1927 else if (child.m_string=="nxtE")
1928 m_breakMethod=3;
1929 else if (child.m_string=="nxtO")
1930 m_breakMethod=4;
1931 else {
1932 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown break method block %s\n", child.m_string.cstr()));
1933 s << "##break[method]=" << child.m_string.cstr() << ",";
1934 }
1935 continue;
1936 }
1937 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown break method block\n"));
1938 s << "###break[method]=" << child << ",";
1939 }
1940 m_extra+=s.str();
1941 return true;
1942 case 0x147550a:
1943 for (auto const &child : field.m_fieldList) {
1944 if (child.m_type==RagTime5StructManager::Field::T_Bool && child.m_fileType==0x360c0) {
1945 if (child.m_longValue[0])
1946 s << "text[margins]=canOverlap,";
1947 continue;
1948 }
1949 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown text margin overlap block\n"));
1950 s << "###text[margins]=" << child << ",";
1951 }
1952 m_extra+=s.str();
1953 return true;
1954 case 0x147516a:
1955 for (auto const &child : field.m_fieldList) {
1956 if (child.m_type==RagTime5StructManager::Field::T_Bool && child.m_fileType==0x360c0) {
1957 if (child.m_longValue[0])
1958 s << "line[align]=ongrid,";
1959 continue;
1960 }
1961 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown line grid align block\n"));
1962 s << "###line[gridalign]=" << child << ",";
1963 }
1964 m_extra+=s.str();
1965 return true;
1966 case 0x147546a:
1967 case 0x147548a:
1968 case 0x14754aa: { // find one time with 1
1969 std::string wh(field.m_fileType==0x147546a ? "orphan" :
1970 field.m_fileType==0x147548a ? "widows" : "unkn54aa");
1971 for (auto const &child : field.m_fieldList) {
1972 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x328c0) {
1973 s << wh << "=" << child.m_longValue[0];
1974 continue;
1975 }
1976 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown number %s block\n", wh.c_str()));
1977 s << "###" << wh << "=" << child << ",";
1978 }
1979 m_extra+=s.str();
1980 return true;
1981 }
1982 case 0x14754ba:
1983 for (auto const &child : field.m_fieldList) {
1984 if (child.m_type==RagTime5StructManager::Field::T_Unstructured && child.m_fileType==0x1476840) {
1985 // height in line, number of character, first line with text, scaling
1986 s << "drop[initial]=" << child.m_extra << ",";
1987 continue;
1988 }
1989 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown drop initial block\n"));
1990 s << "###drop[initial]=" << child << ",";
1991 }
1992 m_extra+=s.str();
1993 return true;
1994 case 0x14750ca: // one tab, remove tab?
1995 case 0x147510a:
1996 if (field.m_fileType==0x14750ca) s << "#tab0";
1997 for (auto const &child : field.m_fieldList) {
1998 if (child.m_type==RagTime5StructManager::Field::T_TabList && (child.m_fileType==(unsigned long)(long(0x81474040)) || child.m_fileType==0x1474040)) {
1999 m_tabList=child.m_tabList;
2000 continue;
2001 }
2002 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown tab block\n"));
2003 s << "###tab=" << child << ",";
2004 }
2005 m_extra+=s.str();
2006 return true;
2007
2008 //
2009 // char
2010 //
2011 case 0x7a05a:
2012 for (auto const &child : field.m_fieldList) {
2013 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0x1495000) {
2014 m_fontSize=float(child.m_doubleValue);
2015 continue;
2016 }
2017 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown font size block\n"));
2018 s << "###size[font]=" << child << ",";
2019 }
2020 m_extra+=s.str();
2021 return true;
2022
2023 case 0xa7017:
2024 case 0xa7037:
2025 case 0xa7047:
2026 case 0xa7057:
2027 case 0xa7067: {
2028 auto wh=int(((field.m_fileType&0x70)>>4)-1);
2029 for (auto const &child : field.m_fieldList) {
2030 if (child.m_type==RagTime5StructManager::Field::T_Unicode && child.m_fileType==0xc8042) {
2031 if (wh==2)
2032 m_fontName=child.m_string;
2033 else {
2034 static char const *what[]= {"[full]" /* unsure */, "[##UNDEF]", "", "[style]" /* regular, ...*/, "[from]", "[full2]"};
2035 s << "font" << what[wh] << "=\"" << child.m_string.cstr() << "\",";
2036 }
2037 continue;
2038 }
2039 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some font name[%d] block\n", wh));
2040 s << "###font[" << wh << "]=" << child << ",";
2041 }
2042 m_extra+=s.str();
2043 return true;
2044 }
2045 case 0xa7077:
2046 case 0x147407a:
2047 case 0x147408a:
2048 for (auto const &child : field.m_fieldList) {
2049 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x3b880) {
2050 switch (field.m_fileType) {
2051 case 0xa7077:
2052 m_fontId=static_cast<int>(child.m_longValue[0]);
2053 break;
2054 case 0x147407a:
2055 s << "hyph[minSyl]=" << child.m_longValue[0] << ",";
2056 break;
2057 case 0x147408a:
2058 s << "hyph[minWord]=" << child.m_longValue[0] << ",";
2059 break;
2060 default:
2061 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown long=%lx\n", static_cast<unsigned long>(field.m_fileType)));
2062 break;
2063 }
2064 continue;
2065 }
2066 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown long=%lx block\n", static_cast<unsigned long>(field.m_fileType)));
2067 s << "###long[" << RagTime5StyleManager::printType(field.m_fileType) << "]=" << child << ",";
2068 }
2069 m_extra+=s.str();
2070 return true;
2071 case 0x7a09a:
2072 for (auto const &child : field.m_fieldList) {
2073 if (child.m_type==RagTime5StructManager::Field::T_2Long && child.m_fileType==0xa4840) {
2074 m_fontFlags[0]=static_cast<uint32_t>(child.m_longValue[0]);
2075 m_fontFlags[1]=static_cast<uint32_t>(child.m_longValue[1]);
2076 continue;
2077 }
2078 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0xa4000) {
2079 m_fontFlags[0]=static_cast<uint32_t>(child.m_longValue[0]);
2080 continue;
2081 }
2082 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown font flags block\n"));
2083 s << "###flags[font]=" << child << ",";
2084 }
2085 m_extra+=s.str();
2086 return true;
2087 case 0x14740ba:
2088 for (auto const &child : field.m_fieldList) {
2089 if (child.m_type==RagTime5StructManager::Field::T_Code && child.m_fileType==0x8d000) {
2090 if (child.m_string=="----") // checkme
2091 m_underline=0;
2092 else if (child.m_string=="undl")
2093 m_underline=1;
2094 else if (child.m_string=="Dund")
2095 m_underline=2;
2096 else {
2097 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown underline block %s\n", child.m_string.cstr()));
2098 s << "##underline=" << child.m_string.cstr() << ",";
2099 }
2100 continue;
2101 }
2102 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some underline block\n"));
2103 s << "###underline=" << child << ",";
2104 }
2105 m_extra+=s.str();
2106 return true;
2107 case 0x147403a:
2108 for (auto const &child : field.m_fieldList) {
2109 if (child.m_type==RagTime5StructManager::Field::T_Code && child.m_fileType==0x8d000) {
2110 if (child.m_string=="----") // checkme
2111 m_caps=0;
2112 else if (child.m_string=="alcp")
2113 m_caps=1;
2114 else if (child.m_string=="lowc")
2115 m_caps=2;
2116 else if (child.m_string=="Icas")
2117 m_caps=3;
2118 else {
2119 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown caps block %s\n", child.m_string.cstr()));
2120 s << "##caps=" << child.m_string.cstr() << ",";
2121 }
2122 continue;
2123 }
2124 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some caps block\n"));
2125 s << "###caps=" << child << ",";
2126 }
2127 m_extra+=s.str();
2128 return true;
2129 case 0x14753aa: // min spacing
2130 case 0x14753ca: // optimal spacing
2131 case 0x14753ea: { // max spacing
2132 int wh=field.m_fileType==0x14753aa ? 2 : field.m_fileType==0x14753ca ? 1 : 3;
2133 for (auto const &child : field.m_fieldList) {
2134 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0xb6000) {
2135 m_letterSpacings[wh]=child.m_doubleValue;
2136 continue;
2137 }
2138 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown spacings[%d] block\n", wh));
2139 s << "###spacings[" << wh << "]=" << child << ",";
2140 }
2141 m_extra+=s.str();
2142 return true;
2143 }
2144
2145 case 0x147404a: // space scaling
2146 for (auto const &child : field.m_fieldList) {
2147 if (child.m_type==RagTime5StructManager::Field::T_LongDouble && child.m_fileType==0x149c940) {
2148 m_letterSpacings[0]=child.m_doubleValue;
2149 // no sure what do to about this int : a number between 0 and 256...
2150 if (child.m_longValue[0]) s << "[" << child.m_longValue[0] << "],";
2151 else s << ",";
2152 continue;
2153 }
2154 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown space scaling block\n"));
2155 s << "###space[scaling]=" << child << ",";
2156 }
2157 m_extra+=s.str();
2158 return true;
2159
2160 case 0x147405a: // script position
2161 for (auto const &child : field.m_fieldList) {
2162 if (child.m_type==RagTime5StructManager::Field::T_LongDouble && child.m_fileType==0x149c940) {
2163 m_scriptPosition=float(child.m_doubleValue);
2164 if ((child.m_doubleValue<0 || child.m_doubleValue>0) && m_fontScaling<0)
2165 m_fontScaling=0.75;
2166 // no sure what do to about this int : a number between 0 and 256...
2167 if (child.m_longValue[0]) s << "script2[pos]?=" << child.m_longValue[0] << ",";
2168 continue;
2169 }
2170 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown font script block\n"));
2171 s << "###font[script]=" << child << ",";
2172 }
2173 m_extra+=s.str();
2174 return true;
2175
2176 case 0x14741ba:
2177 for (auto const &child : field.m_fieldList) {
2178 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0xb6000) {
2179 m_fontScaling=float(child.m_doubleValue);
2180 continue;
2181 }
2182 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown font scaling block\n"));
2183 s << "###scaling=" << child << ",";
2184 }
2185 m_extra+=s.str();
2186 return true;
2187
2188 case 0x14740ea: // horizontal streching
2189 case 0x147418a: // small cap horizontal scaling
2190 case 0x14741aa: { // small cap vertical scaling
2191 std::string wh(field.m_fileType==0x14740ea ? "font[strech]" :
2192 field.m_fileType==0x147418a ? "font[smallScaleH]" : "font[smallScaleV]");
2193 for (auto const &child : field.m_fieldList) {
2194 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0xb6000) {
2195 if (field.m_fileType==0x14740ea)
2196 m_widthStreching=child.m_doubleValue;
2197 else
2198 s << wh << "=" << child.m_doubleValue << ",";
2199 continue;
2200 }
2201 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown %s block\n", wh.c_str()));
2202 s << "###" << wh << "=" << child << ",";
2203 }
2204 m_extra+=s.str();
2205 return true;
2206 }
2207 case 0x147406a: // automatic hyphenation
2208 case 0x147552a: { // ignore 1 word ( for spacings )
2209 std::string wh(field.m_fileType==0x147406a ? "hyphen" : "spacings[ignore1Word]");
2210 for (auto const &child : field.m_fieldList) {
2211 if (child.m_type==RagTime5StructManager::Field::T_Bool && child.m_fileType==0x360c0) {
2212 if (child.m_longValue[0])
2213 s << wh << ",";
2214 else
2215 s << wh << "=no,";
2216 continue;
2217 }
2218 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown %s block\n", wh.c_str()));
2219 s << "###" << wh << "=" << child << ",";
2220 }
2221 m_extra+=s.str();
2222 return true;
2223 }
2224 case 0x147402a: // language
2225 for (auto const &child : field.m_fieldList) {
2226 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x34080) {
2227 m_language=static_cast<int>(child.m_longValue[0]);
2228 continue;
2229 }
2230 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown language block\n"));
2231 s << "###language=" << child << ",";
2232 }
2233 m_extra+=s.str();
2234 return true;
2235
2236 //
2237 // columns
2238 //
2239 case 0x147512a:
2240 for (auto const &child : field.m_fieldList) {
2241 if (child.m_type==RagTime5StructManager::Field::T_Long && child.m_fileType==0x328c0) {
2242 m_numColumns=static_cast<int>(child.m_longValue[0]);
2243 continue;
2244 }
2245 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown column's number block\n"));
2246 s << "###num[cols]=" << child << ",";
2247 }
2248 m_extra+=s.str();
2249 return true;
2250 case 0x147513a:
2251 for (auto const &child : field.m_fieldList) {
2252 if (child.m_type==RagTime5StructManager::Field::T_Double && child.m_fileType==0x1493800) {
2253 m_columnGap=child.m_doubleValue;
2254 continue;
2255 }
2256 MWAW_DEBUG_MSG(("RagTime5StyleManager::TextStyle::read: find some unknown columns gaps block\n"));
2257 s << "###col[gap]=" << child << ",";
2258 }
2259 m_extra+=s.str();
2260 return true;
2261
2262 default:
2263 break;
2264 }
2265 }
2266 return false;
2267 }
2268
insert(RagTime5StyleManager::TextStyle const & child)2269 void RagTime5StyleManager::TextStyle::insert(RagTime5StyleManager::TextStyle const &child)
2270 {
2271 if (!child.m_linkIdList.empty()) m_linkIdList=child.m_linkIdList; // usefull?
2272 if (child.m_graphStyleId>=0) m_graphStyleId=child.m_graphStyleId;
2273 if (child.m_graphLineStyleId>=0) m_graphLineStyleId=child.m_graphLineStyleId;
2274 if (child.m_dateStyleId>=0) m_dateStyleId=child.m_dateStyleId;
2275 if (child.m_keepWithNext.isSet()) m_keepWithNext=child.m_keepWithNext;
2276 if (child.m_justify>=0) m_justify=child.m_justify;
2277 if (child.m_breakMethod>=0) m_breakMethod=child.m_breakMethod;
2278 for (int i=0; i<3; ++i) {
2279 if (child.m_margins[i]>=0) m_margins[i]=child.m_margins[i];
2280 }
2281 for (int i=0; i<3; ++i) {
2282 if (child.m_spacings[i]<0) continue;
2283 m_spacings[i]=child.m_spacings[i];
2284 m_spacingUnits[i]=child.m_spacingUnits[i];
2285 }
2286 if (!child.m_tabList.empty()) m_tabList=child.m_tabList; // append ?
2287 // char
2288 if (!child.m_fontName.empty()) m_fontName=child.m_fontName;
2289 if (child.m_fontId>=0) m_fontId=child.m_fontId;
2290 if (child.m_fontSize>=0) m_fontSize=child.m_fontSize;
2291 for (int i=0; i<2; ++i) {
2292 uint32_t fl=child.m_fontFlags[i];
2293 if (!fl) continue;
2294 if (i==0) m_fontFlags[0]|=fl;
2295 else m_fontFlags[0]&=(~fl);
2296 }
2297 if (child.m_caps>=0) m_caps=child.m_caps;
2298 if (child.m_underline>=0) m_underline=child.m_underline;
2299 if (child.m_scriptPosition.isSet()) m_scriptPosition=child.m_scriptPosition;
2300 if (child.m_fontScaling>=0) m_fontScaling=child.m_fontScaling;
2301
2302 for (int i=0; i<4; ++i) {
2303 if (child.m_letterSpacings[i]>0 || child.m_letterSpacings[i]<0)
2304 m_letterSpacings[i]=child.m_letterSpacings[i];
2305 }
2306 if (child.m_language>=0) m_language=child.m_language;
2307 if (child.m_widthStreching>=0) m_widthStreching=child.m_widthStreching;
2308 // column
2309 if (child.m_numColumns>=0) m_numColumns=child.m_numColumns;
2310 if (child.m_columnGap>=0) m_columnGap=child.m_columnGap;
2311 }
2312
operator <<(std::ostream & o,RagTime5StyleManager::TextStyle const & style)2313 std::ostream &operator<<(std::ostream &o, RagTime5StyleManager::TextStyle const &style)
2314 {
2315 if (style.m_parentId[0]>=0) o << "parent=TS" << style.m_parentId[0] << ",";
2316 if (style.m_parentId[1]>=0) o << "parent[style?]=TS" << style.m_parentId[1] << ",";
2317 if (!style.m_linkIdList.empty()) {
2318 // fixme: 3 text style's id values with unknown meaning, probably important...
2319 o << "link=[";
2320 for (auto id : style.m_linkIdList)
2321 o << "TS" << id << ",";
2322 o << "],";
2323 }
2324 if (style.m_graphStyleId>=0) o << "graph[id]=GS" << style.m_graphStyleId << ",";
2325 if (style.m_graphLineStyleId>=0) o << "graphLine[id]=GS" << style.m_graphLineStyleId << ",";
2326 if (style.m_dateStyleId>=0) o << "date[id]=DS" << style.m_dateStyleId << ",";
2327 if (style.m_keepWithNext.isSet()) {
2328 o << "keep[withNext]";
2329 if (!*style.m_keepWithNext)
2330 o << "=false,";
2331 else
2332 o << ",";
2333 }
2334 switch (style.m_justify) {
2335 case 0: // left
2336 break;
2337 case 1:
2338 o << "justify=center,";
2339 break;
2340 case 2:
2341 o << "justify=right,";
2342 break;
2343 case 3:
2344 o << "justify=full,";
2345 break;
2346 case 4:
2347 o << "justify=full[all],";
2348 break;
2349 default:
2350 if (style.m_justify>=0)
2351 o << "##justify=" << style.m_justify << ",";
2352 }
2353
2354 switch (style.m_breakMethod) {
2355 case 0: // as is
2356 break;
2357 case 1:
2358 o << "break[method]=next[container],";
2359 break;
2360 case 2:
2361 o << "break[method]=next[page],";
2362 break;
2363 case 3:
2364 o << "break[method]=next[evenP],";
2365 break;
2366 case 4:
2367 o << "break[method]=next[oddP],";
2368 break;
2369 default:
2370 if (style.m_breakMethod>=0)
2371 o << "##break[method]=" << style.m_breakMethod << ",";
2372 }
2373 for (int i=0; i<3; ++i) {
2374 if (style.m_margins[i]<0) continue;
2375 static char const *wh[]= {"left", "right", "first"};
2376 o << "margins[" << wh[i] << "]=" << style.m_margins[i] << ",";
2377 }
2378 for (int i=0; i<3; ++i) {
2379 if (style.m_spacings[i]<0) continue;
2380 o << (i==0 ? "interline" : i==1 ? "before[spacing]" : "after[spacing]");
2381 o << "=" << style.m_spacings[i];
2382 if (style.m_spacingUnits[i]==0)
2383 o << "%";
2384 else if (style.m_spacingUnits[i]==1)
2385 o << "pt";
2386 else
2387 o << "[###unit]=" << style.m_spacingUnits[i];
2388 o << ",";
2389 }
2390 if (!style.m_tabList.empty()) {
2391 o << "tabs=[";
2392 for (auto const &tab : style.m_tabList)
2393 o << tab << ",";
2394 o << "],";
2395 }
2396 // char
2397 if (!style.m_fontName.empty())
2398 o << "font=\"" << style.m_fontName.cstr() << "\",";
2399 if (style.m_fontId>=0)
2400 o << "id[font]=" << style.m_fontId << ",";
2401 if (style.m_fontSize>=0)
2402 o << "sz[font]=" << style.m_fontSize << ",";
2403 for (int i=0; i<2; ++i) {
2404 uint32_t fl=style.m_fontFlags[i];
2405 if (!fl) continue;
2406 if (i==1)
2407 o << "flag[rm]=[";
2408 if (fl&1) o << "bold,";
2409 if (fl&2) o << "it,";
2410 // 4 underline?
2411 if (fl&8) o << "outline,";
2412 if (fl&0x10) o << "shadow,";
2413 if (fl&0x200) o << "strike[through],";
2414 if (fl&0x400) o << "small[caps],";
2415 if (fl&0x800) o << "kumoraru,"; // ie. with some char overlapping
2416 if (fl&0x20000) o << "underline[word],";
2417 if (fl&0x80000) o << "key[pairing],";
2418 fl &= 0xFFF5F1E4;
2419 if (fl) o << "#fontFlags=" << std::hex << fl << std::dec << ",";
2420 if (i==1)
2421 o << "],";
2422 }
2423 switch (style.m_caps) {
2424 case 0:
2425 break;
2426 case 1:
2427 o << "upper[caps],";
2428 break;
2429 case 2:
2430 o << "lower[caps],";
2431 break;
2432 case 3:
2433 o << "upper[initial+...],";
2434 break;
2435 default:
2436 if (style.m_caps >= 0)
2437 o << "###caps=" << style.m_caps << ",";
2438 break;
2439 }
2440 switch (style.m_underline) {
2441 case 0:
2442 break;
2443 case 1:
2444 o << "underline=single,";
2445 break;
2446 case 2:
2447 o << "underline=double,";
2448 break;
2449 default:
2450 if (style.m_underline>=0)
2451 o << "###underline=" << style.m_underline << ",";
2452 }
2453 if (style.m_scriptPosition.isSet())
2454 o << "ypos[font]=" << *style.m_scriptPosition << "%,";
2455 if (style.m_fontScaling>=0)
2456 o << "scale[font]=" << style.m_fontScaling << "%,";
2457
2458 for (int i=0; i<4; ++i) {
2459 if (style.m_letterSpacings[i]<=0&&style.m_letterSpacings[i]>=0) continue;
2460 static char const *wh[]= {"", "[optimal]", "[min]", "[max]"};
2461 o << "letterSpacing" << wh[i] << "=" << style.m_letterSpacings[i] << ",";
2462 }
2463 if (style.m_widthStreching>=0)
2464 o << "width[streching]=" << style.m_widthStreching*100 << "%,";
2465 if (style.m_language>0) {
2466 std::string lang=RagTime5StyleManager::TextStyle::getLanguageLocale(style.m_language);
2467 if (!lang.empty())
2468 o << lang << ",";
2469 else
2470 o << "##language=" << std::hex << style.m_language << std::dec << ",";
2471 }
2472 // column
2473 if (style.m_numColumns>=0)
2474 o << "num[col]=" << style.m_numColumns << ",";
2475 if (style.m_columnGap>=0)
2476 o << "col[gap]=" << style.m_columnGap << ",";
2477 o << style.m_extra;
2478 return o;
2479 }
2480
2481
2482 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
2483