Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libetonyek/src/lib/contexts/KEY1StylesContext.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/*
3
 * This file is part of the libetonyek project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#include <boost/spirit/include/qi.hpp>
11
#include <memory>
12
13
#include "KEY1StylesContext.h"
14
15
#include "IWORKProperties.h"
16
#include "IWORKTokenizer.h"
17
18
#include "KEY1Dictionary.h"
19
#include "KEY1FillElement.h"
20
#include "KEY1StringConverter.h"
21
#include "KEY1Token.h"
22
#include "KEY1ParserState.h"
23
24
#include "libetonyek_xml.h"
25
26
namespace libetonyek
27
{
28
namespace
29
{
30
class MarkerStyleElement : public KEY1XMLElementContextBase
31
{
32
public:
33
  MarkerStyleElement(KEY1ParserState &state, boost::optional<IWORKMarker> &m_marker);
34
35
private:
36
  void attribute(int name, const char *value) override;
37
  IWORKXMLContextPtr_t element(int name) override;
38
  void endOfElement() override;
39
40
private:
41
  boost::optional<IWORKMarker> &m_marker;
42
};
43
44
MarkerStyleElement::MarkerStyleElement(KEY1ParserState &state, boost::optional<IWORKMarker> &marker)
45
0
  : KEY1XMLElementContextBase(state)
46
0
  , m_marker(marker)
47
0
{
48
0
  m_marker=IWORKMarker();
49
0
}
50
51
void MarkerStyleElement::attribute(const int name, const char *const value)
52
0
{
53
0
  switch (name)
54
0
  {
55
0
  case KEY1Token::is_filled :
56
0
    get(m_marker).m_filled = bool_cast(value);
57
0
    break;
58
0
  case KEY1Token::id :
59
0
    setId(value);
60
0
    break;
61
0
  case KEY1Token::match_point :
62
0
    get(m_marker).m_endPoint=KEY1StringConverter<IWORKPosition>::convert(value);
63
0
    break;
64
0
  case KEY1Token::path :
65
0
    get(m_marker).m_path=value;
66
0
    break;
67
0
  default :
68
0
    ETONYEK_DEBUG_MSG(("MarkerStyleElement::attribute[KEY1StylesContext.cpp]: unexpected attribute\n"));
69
0
    break;
70
0
  }
71
0
}
72
73
IWORKXMLContextPtr_t MarkerStyleElement::element(const int /*name*/)
74
0
{
75
0
  ETONYEK_DEBUG_MSG(("MarkerStyleElement::element[KEY1StylesContext.cpp]: unknown element\n"));
76
77
0
  return IWORKXMLContextPtr_t();
78
0
}
79
80
void MarkerStyleElement::endOfElement()
81
0
{
82
  // todo safe marker
83
0
}
84
}
85
86
namespace
87
{
88
class PatternStyleElement : public KEY1XMLElementContextBase
89
{
90
public:
91
  PatternStyleElement(KEY1ParserState &state, boost::optional<IWORKPattern> &m_pattern);
92
93
private:
94
  void attribute(int name, const char *value) override;
95
  IWORKXMLContextPtr_t element(int name) override;
96
  void endOfElement() override;
97
98
private:
99
  boost::optional<IWORKPattern> &m_pattern;
100
};
101
102
PatternStyleElement::PatternStyleElement(KEY1ParserState &state, boost::optional<IWORKPattern> &pattern)
103
0
  : KEY1XMLElementContextBase(state)
104
0
  , m_pattern(pattern)
105
0
{
106
0
  m_pattern=IWORKPattern();
107
0
}
108
109
void PatternStyleElement::attribute(const int name, const char *const value)
110
0
{
111
0
  switch (name)
112
0
  {
113
0
  case KEY1Token::pattern:
114
0
    switch (getState().getTokenizer().getId(value))
115
0
    {
116
0
    case KEY1Token::none :
117
0
      m_pattern->m_type = IWORK_STROKE_TYPE_NONE;
118
0
      break;
119
0
    case KEY1Token::solid :
120
0
      m_pattern->m_type = IWORK_STROKE_TYPE_SOLID;
121
0
      break;
122
0
    default :
123
0
    {
124
0
      namespace spirit = boost::spirit;
125
0
      using spirit::ascii::space;
126
0
      using spirit::ascii::char_;
127
0
      using spirit::qi::double_;
128
0
      std::string val(value);
129
0
      std::string::const_iterator it = val.begin(), end = val.end();
130
0
      if (spirit::qi::phrase_parse(it, end, double_ >> *(double_), space, m_pattern->m_values) && it==end)
131
0
        m_pattern->m_type = IWORK_STROKE_TYPE_DASHED;
132
0
      else
133
0
      {
134
0
        ETONYEK_DEBUG_MSG(("PatternStyleElement::attribute[KEY1StylesContext.cpp]: can not parse pattern %s\n", value));
135
0
        m_pattern->m_values.clear();
136
0
      }
137
0
      break;
138
0
    }
139
0
    }
140
0
    break;
141
0
  case KEY1Token::id :
142
0
    setId(value);
143
0
    break;
144
0
  default :
145
0
    ETONYEK_DEBUG_MSG(("PatternStyleElement::attribute[KEY1StylesContext.cpp]: unexpected attribute\n"));
146
0
    break;
147
0
  }
148
0
}
149
150
IWORKXMLContextPtr_t PatternStyleElement::element(const int /*name*/)
151
0
{
152
0
  ETONYEK_DEBUG_MSG(("PatternStyleElement::element[KEY1StylesContext.cpp]: unknown element\n"));
153
154
0
  return IWORKXMLContextPtr_t();
155
0
}
156
157
void PatternStyleElement::endOfElement()
158
0
{
159
0
  if (getId())
160
0
    getState().getDictionary().m_patterns[get(getId())]=get(m_pattern);
161
0
}
162
}
163
164
namespace
165
{
166
class ShadowStyleElement : public KEY1XMLElementContextBase
167
{
168
public:
169
  ShadowStyleElement(KEY1ParserState &state, boost::optional<IWORKShadow> &m_shadow);
170
171
private:
172
  void attribute(int name, const char *value) override;
173
  IWORKXMLContextPtr_t element(int name) override;
174
  void endOfElement() override;
175
176
private:
177
  boost::optional<IWORKShadow> &m_shadow;
178
};
179
180
ShadowStyleElement::ShadowStyleElement(KEY1ParserState &state, boost::optional<IWORKShadow> &shadow)
181
0
  : KEY1XMLElementContextBase(state)
182
0
  , m_shadow(shadow)
183
0
{
184
0
  m_shadow=IWORKShadow();
185
0
}
186
187
void ShadowStyleElement::attribute(const int name, const char *const value)
188
0
{
189
0
  switch (name)
190
0
  {
191
0
  case KEY1Token::angle :
192
0
    get(m_shadow).m_angle=double_cast(value);
193
0
    break;
194
0
  case KEY1Token::color :
195
0
  {
196
0
    boost::optional<IWORKColor> color=KEY1StringConverter<IWORKColor>::convert(value);
197
0
    if (color) get(m_shadow).m_color=get(color);
198
0
    break;
199
0
  }
200
0
  case KEY1Token::id :
201
0
    setId(value);
202
0
    break;
203
0
  case KEY1Token::offset :
204
0
    get(m_shadow).m_offset=double_cast(value);
205
0
    break;
206
0
  case KEY1Token::opacity :
207
0
    get(m_shadow).m_opacity=double_cast(value);
208
0
    break;
209
0
  case KEY1Token::radius :
210
0
    get(m_shadow).m_radius=double_cast(value);
211
0
    break;
212
0
  default :
213
0
    ETONYEK_DEBUG_MSG(("ShadowStyleElement::attribute[KEY1StylesContext.cpp]: unexpected attribute\n"));
214
0
    break;
215
0
  }
216
0
}
217
218
IWORKXMLContextPtr_t ShadowStyleElement::element(const int /*name*/)
219
0
{
220
0
  ETONYEK_DEBUG_MSG(("ShadowStyleElement::element[KEY1StylesContext.cpp]: unknown element\n"));
221
222
0
  return IWORKXMLContextPtr_t();
223
0
}
224
225
void ShadowStyleElement::endOfElement()
226
0
{
227
0
  if (getId())
228
0
    getState().getDictionary().m_shadows[get(getId())]=get(m_shadow);
229
0
}
230
}
231
232
KEY1StylesContext::KEY1StylesContext(KEY1ParserState &state, IWORKStylePtr_t &style, IWORKStylePtr_t parentStyle)
233
0
  : KEY1XMLElementContextBase(state)
234
0
  , m_style(style)
235
0
  , m_propMap()
236
0
  , m_parentStyle(parentStyle)
237
0
  , m_fill()
238
0
  , m_lineHead()
239
0
  , m_lineTail()
240
0
  , m_pattern()
241
0
  , m_shadow()
242
0
{
243
0
}
244
245
IWORKXMLContextPtr_t KEY1StylesContext::element(const int name)
246
0
{
247
0
  switch (name)
248
0
  {
249
0
  case +KEY1Token::dash_style | KEY1Token::NS_URI_KEY :
250
0
    return std::make_shared<PatternStyleElement>(getState(), m_pattern);
251
0
  case +KEY1Token::fill_style | KEY1Token::NS_URI_KEY :
252
0
    return std::make_shared<KEY1FillElement>(getState(), m_fill);
253
0
  case +KEY1Token::line_head_style | KEY1Token::NS_URI_KEY :
254
0
    return std::make_shared<MarkerStyleElement>(getState(), m_lineHead);
255
0
  case +KEY1Token::line_tail_style | KEY1Token::NS_URI_KEY :
256
0
    return std::make_shared<MarkerStyleElement>(getState(), m_lineTail);
257
0
  case +KEY1Token::shadow_style | KEY1Token::NS_URI_KEY :
258
0
    return std::make_shared<ShadowStyleElement>(getState(), m_shadow);
259
0
  default :
260
0
    ETONYEK_DEBUG_MSG(("KEY1StylesContext::element[KEY1StylesContext.cpp]: unknown element\n"));
261
0
    break;
262
0
  }
263
0
  return IWORKXMLContextPtr_t();
264
0
}
265
266
void KEY1StylesContext::endOfElement()
267
0
{
268
0
  if (m_fill)
269
0
    m_propMap.put<property::Fill>(get(m_fill));
270
0
  if (m_lineHead)
271
0
    m_propMap.put<property::HeadLineEnd>(get(m_lineHead));
272
0
  if (m_lineTail)
273
0
    m_propMap.put<property::TailLineEnd>(get(m_lineTail));
274
0
  if (m_pattern)
275
0
  {
276
0
    IWORKStroke stroke;
277
0
    if (m_parentStyle && m_parentStyle->has<property::Stroke>())
278
0
      stroke=m_parentStyle->get<property::Stroke>();
279
0
    stroke.m_pattern=get(m_pattern);
280
0
    m_propMap.put<property::Stroke>(stroke);
281
0
  }
282
0
  if (m_shadow)
283
0
    m_propMap.put<property::Shadow>(get(m_shadow));
284
0
  m_style = std::make_shared<IWORKStyle>(m_propMap, boost::none, m_parentStyle);
285
0
}
286
287
}
288
289
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */