Coverage Report

Created: 2026-09-06 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/MWAWFont.hxx
Line
Count
Source
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
#ifndef MWAW_FONT
35
#  define MWAW_FONT
36
37
#include <string>
38
#include <vector>
39
40
#include "libmwaw_internal.hxx"
41
42
//! Class to store font
43
class MWAWFont
44
{
45
public:
46
  /** a small struct to define a line in MWAWFont */
47
  struct Line {
48
    /** the line style */
49
    enum Style { None, Simple, Dot, LargeDot, Dash, Wave };
50
    /** the line style */
51
    enum Type { Single, Double, Triple };
52
    //! constructor
53
    explicit Line(Style style=None, Type type=Single, bool wordFlag=false, float w=1.0)
54
2.89G
      : m_style(style)
55
2.89G
      , m_type(type)
56
2.89G
      , m_width(w)
57
2.89G
      , m_color(MWAWColor::black())
58
2.89G
      , m_word(wordFlag)
59
2.89G
    {
60
2.89G
    }
61
    //! return true if the line is not empty
62
    bool isSet() const
63
56.7M
    {
64
56.7M
      return m_style != None && m_width>0;
65
56.7M
    }
66
    //! add a line to the propList knowing the type (line-through, underline, overline )
67
    void addTo(librevenge::RVNGPropertyList &propList, std::string const &type) const;
68
    //! operator<<
69
    friend std::ostream &operator<<(std::ostream &o, Line const &line);
70
    //! operator==
71
    bool operator==(Line const &oth) const
72
0
    {
73
0
      return cmp(oth)==0;
74
0
    }
75
    //! operator!=
76
    bool operator!=(Line const &oth) const
77
0
    {
78
0
      return cmp(oth)!=0;
79
0
    }
80
    //! small comparison function
81
    int cmp(Line const &oth) const
82
205M
    {
83
205M
      if (m_style != oth.m_style) return int(m_style)-int(oth.m_style);
84
203M
      if (m_type != oth.m_type) return int(m_type)-int(oth.m_type);
85
203M
      if (m_word != oth.m_word) return m_word ? -1 : 1;
86
203M
      if (m_width < oth.m_width) return -1;
87
203M
      if (m_width > oth.m_width) return 1;
88
203M
      if (m_color.isSet() != oth.m_color.isSet())
89
65
        return m_color.isSet();
90
203M
      if (m_color.get() < oth.m_color.get()) return -1;
91
203M
      if (m_color.get() > oth.m_color.get()) return 1;
92
203M
      return 0;
93
203M
    }
94
    /** the style */
95
    Style m_style;
96
    /** the type */
97
    Type m_type;
98
    /** the width in point */
99
    float m_width;
100
    /** the color ( if not set, we use the font color )*/
101
    MWAWVariable<MWAWColor> m_color;
102
    /** word or not word line */
103
    bool m_word;
104
  };
105
  /** a small struct to define the script position in MWAWFont */
106
  struct Script {
107
    //! constructor
108
    explicit Script(float delta=0, librevenge::RVNGUnit deltaUnit=librevenge::RVNG_PERCENT, int scale=100)
109
1.13G
      : m_delta(delta)
110
1.13G
      , m_deltaUnit(deltaUnit)
111
1.13G
      , m_scale(scale)
112
1.13G
    {
113
1.13G
    }
114
    //! return true if the position is not default
115
    bool isSet() const
116
62.9M
    {
117
62.9M
      return *this != Script();
118
62.9M
    }
119
    //! return a yposition which correspond to a basic subscript
120
    static Script sub()
121
2.56M
    {
122
2.56M
      return Script(-33,librevenge::RVNG_PERCENT,58);
123
2.56M
    }
124
    //! return a yposition which correspond to a basic subscript100
125
    static Script sub100()
126
22.9M
    {
127
22.9M
      return Script(-20);
128
22.9M
    }
129
    //! return a yposition which correspond to a basic superscript
130
    static Script super()
131
2.73M
    {
132
2.73M
      return Script(33,librevenge::RVNG_PERCENT,58);
133
2.73M
    }
134
    //! return a yposition which correspond to a basic superscript100
135
    static Script super100()
136
39.9M
    {
137
39.9M
      return Script(20);
138
39.9M
    }
139
    //! return a string which correspond to style:text-position
140
    std::string str(float fSize) const;
141
142
    //! operator==
143
    bool operator==(Script const &oth) const
144
0
    {
145
0
      return cmp(oth)==0;
146
0
    }
147
    //! operator!=
148
    bool operator!=(Script const &oth) const
149
62.9M
    {
150
62.9M
      return cmp(oth)!=0;
151
62.9M
    }
152
    //! operator<
153
    bool operator<(Script const &oth) const
154
0
    {
155
0
      return cmp(oth)<0;
156
0
    }
157
    //! operator<=
158
    bool operator<=(Script const &oth) const
159
0
    {
160
0
      return cmp(oth)<=0;
161
0
    }
162
    //! operator>
163
    bool operator>(Script const &oth) const
164
0
    {
165
0
      return cmp(oth)>0;
166
0
    }
167
    //! operator>=
168
    bool operator>=(Script const &oth) const
169
0
    {
170
0
      return cmp(oth)>=0;
171
0
    }
172
    //! small comparison function
173
    int cmp(Script const &oth) const
174
133M
    {
175
133M
      if (m_delta > oth.m_delta) return -1;
176
117M
      if (m_delta < oth.m_delta) return 1;
177
90.2M
      if (m_deltaUnit != oth.m_deltaUnit) return int(m_deltaUnit)-int(oth.m_deltaUnit);
178
90.2M
      if (m_scale != oth.m_scale) return m_scale-oth.m_scale;
179
90.2M
      return 0;
180
90.2M
    }
181
    //! the ydelta
182
    float m_delta;
183
    //! the ydelta unit ( point or percent )
184
    librevenge::RVNGUnit m_deltaUnit;
185
    //! the font scaling ( in percent )
186
    int m_scale;
187
  };
188
189
  //! the different font bit
190
  enum FontBits { boldBit=1, italicBit=2, blinkBit=4, embossBit=8, engraveBit=0x10,
191
                  hiddenBit=0x20, outlineBit=0x40, shadowBit=0x80,
192
                  reverseVideoBit=0x100, smallCapsBit=0x200, uppercaseBit=0x400,
193
                  lowercaseBit=0x800,
194
                  initialcaseBit=2*lowercaseBit,
195
                  boxedBit=2*initialcaseBit,
196
                  boxedRoundedBit=2*boxedBit,
197
                  reverseWritingBit=2*boxedRoundedBit
198
                };
199
  /** constructor
200
   *
201
   * \param newId system id font
202
   * \param sz the font size
203
   * \param f the font attributes bold, ... */
204
  explicit MWAWFont(int newId=-1, float sz=12, uint32_t f = 0)
205
956M
    : m_id(newId)
206
956M
    , m_size(sz)
207
956M
    , m_sizeIsRelative(false)
208
956M
    , m_deltaSpacing(0)
209
956M
    , m_deltaSpacingUnit(librevenge::RVNG_POINT)
210
956M
    , m_widthStreching(1)
211
956M
    , m_scriptPosition()
212
956M
    , m_flags(f)
213
956M
    , m_overline(Line(Line::None))
214
956M
    , m_strikeoutline(Line(Line::None))
215
956M
    , m_underline(Line(Line::None))
216
956M
    , m_color(MWAWColor::black())
217
956M
    , m_backgroundColor(MWAWColor::white())
218
956M
    , m_language("")
219
956M
    , m_extra("")
220
956M
  {
221
956M
    resetColor();
222
956M
  }
223
  //! returns true if the font id is initialized
224
  bool isSet() const
225
0
  {
226
0
    return m_id.isSet();
227
0
  }
228
  //! inserts the set value in the current font
229
  void insert(MWAWFont const &ft)
230
133k
  {
231
133k
    m_id.insert(ft.m_id);
232
133k
    m_size.insert(ft.m_size);
233
133k
    m_sizeIsRelative.insert(ft.m_sizeIsRelative);
234
133k
    m_deltaSpacing.insert(ft.m_deltaSpacing);
235
133k
    m_deltaSpacingUnit.insert(ft.m_deltaSpacingUnit);
236
133k
    m_widthStreching.insert(ft.m_widthStreching);
237
133k
    m_scriptPosition.insert(ft.m_scriptPosition);
238
133k
    if (ft.m_flags.isSet()) {
239
97.5k
      if (m_flags.isSet())
240
95.2k
        setFlags(flags()| ft.flags());
241
2.30k
      else
242
2.30k
        m_flags = ft.m_flags;
243
97.5k
    }
244
133k
    m_overline.insert(ft.m_overline);
245
133k
    m_strikeoutline.insert(ft.m_strikeoutline);
246
133k
    m_underline.insert(ft.m_underline);
247
133k
    m_color.insert(ft.m_color);
248
133k
    m_backgroundColor.insert(ft.m_backgroundColor);
249
133k
    m_extra += ft.m_extra;
250
133k
  }
251
  //! sets the font id and resets size to the previous size for this font
252
  void setFont(int newId)
253
9.18M
  {
254
9.18M
    resetColor();
255
9.18M
    m_id=newId;
256
9.18M
  }
257
258
  //! returns the font id
259
  int id() const
260
3.94G
  {
261
3.94G
    return m_id.get();
262
3.94G
  }
263
  //! sets the font id
264
  void setId(int newId)
265
80.0M
  {
266
80.0M
    m_id = newId;
267
80.0M
  }
268
269
  //! returns the font size
270
  float size() const
271
499M
  {
272
499M
    return m_size.get();
273
499M
  }
274
  //! sets the font size
275
  void setSize(float sz, bool isRelative=false)
276
97.8M
  {
277
97.8M
    m_size = sz;
278
97.8M
    m_sizeIsRelative = isRelative;
279
97.8M
  }
280
281
  //! returns the condensed(negative)/extended(positive) width
282
  float deltaLetterSpacing() const
283
0
  {
284
0
    return m_deltaSpacing.get();
285
0
  }
286
  //! returns the condensed(negative)/extended(positive) unit
287
  librevenge::RVNGUnit deltaLetterSpacingUnit() const
288
0
  {
289
0
    return m_deltaSpacingUnit.get();
290
0
  }
291
  //! sets the letter spacing ( delta value in point )
292
  void setDeltaLetterSpacing(float d, librevenge::RVNGUnit unit=librevenge::RVNG_POINT)
293
15.9M
  {
294
15.9M
    m_deltaSpacing=d;
295
15.9M
    m_deltaSpacingUnit=unit;
296
15.9M
  }
297
  //! returns the text width streching
298
  float widthStreching() const
299
0
  {
300
0
    return m_widthStreching.get();
301
0
  }
302
  //! sets the text width streching
303
  void setWidthStreching(float scale=1.0)
304
19.9k
  {
305
19.9k
    m_widthStreching = scale;
306
19.9k
  }
307
  //! returns the script position
308
  Script const &script() const
309
141M
  {
310
141M
    return m_scriptPosition.get();
311
141M
  }
312
313
  //! sets the script position
314
  void set(Script const &newscript)
315
111M
  {
316
111M
    m_scriptPosition = newscript;
317
111M
  }
318
319
  //! returns the font flags
320
  uint32_t flags() const
321
3.92G
  {
322
3.92G
    return m_flags.get();
323
3.92G
  }
324
  //! sets the font attributes bold, ...
325
  void setFlags(uint32_t fl)
326
3.64G
  {
327
3.64G
    m_flags = fl;
328
3.64G
  }
329
330
  //! returns true if the font color is not black
331
  bool hasColor() const
332
50.7M
  {
333
50.7M
    return m_color.isSet() && !m_color.get().isBlack();
334
50.7M
  }
335
  //! returns the font color
336
  void getColor(MWAWColor &c) const
337
75.5k
  {
338
75.5k
    c = m_color.get();
339
75.5k
  }
340
  //! sets the font color
341
  void setColor(MWAWColor color)
342
97.8M
  {
343
97.8M
    m_color = color;
344
97.8M
  }
345
346
  //! returns the font background color
347
  void getBackgroundColor(MWAWColor &c) const
348
2.42k
  {
349
2.42k
    c = m_backgroundColor.get();
350
2.42k
  }
351
  //! sets the font background color
352
  void setBackgroundColor(MWAWColor color)
353
213k
  {
354
213k
    m_backgroundColor = color;
355
213k
  }
356
  //! resets the font color to black and the background color to white
357
  void resetColor()
358
965M
  {
359
965M
    m_color = MWAWColor::black();
360
965M
    m_backgroundColor = MWAWColor::white();
361
965M
  }
362
363
  //! return true if the font has decorations line (overline, strikeout, underline)
364
  bool hasDecorationLines() const
365
4.21M
  {
366
4.21M
    return (m_overline.isSet() && m_overline->isSet()) ||
367
4.16M
           (m_strikeoutline.isSet() && m_strikeoutline->isSet()) ||
368
4.08M
           (m_underline.isSet() && m_underline->isSet());
369
4.21M
  }
370
  //! reset the decoration
371
  void resetDecorationLines()
372
700k
  {
373
700k
    if (m_overline.isSet()) m_overline=Line(Line::None);
374
700k
    if (m_strikeoutline.isSet()) m_strikeoutline=Line(Line::None);
375
700k
    if (m_underline.isSet()) m_underline=Line(Line::None);
376
700k
  }
377
  //! returns the overline
378
  Line const &getOverline() const
379
2.42k
  {
380
2.42k
    return m_overline.get();
381
2.42k
  }
382
  //! sets the overline
383
  void setOverline(Line const &line)
384
41.6k
  {
385
41.6k
    m_overline = line;
386
41.6k
  }
387
  //! sets the overline style ( by default, we also reset the style)
388
  void setOverlineStyle(Line::Style style=Line::None, bool doReset=true)
389
109k
  {
390
109k
    if (doReset)
391
109k
      m_overline = Line(style);
392
0
    else
393
0
      m_overline->m_style = style;
394
109k
  }
395
  //! sets the overline type
396
  void setOverlineType(Line::Type type=Line::Single)
397
0
  {
398
0
    m_overline->m_type = type;
399
0
  }
400
  //! sets the overline word flag
401
  void setOverlineWordFlag(bool wordFlag=false)
402
0
  {
403
0
    m_overline->m_word = wordFlag;
404
0
  }
405
  //! sets the overline width
406
  void setOverlineWidth(float w)
407
15.1k
  {
408
15.1k
    m_overline->m_width = w;
409
15.1k
  }
410
  //! sets the overline color
411
  void setOverlineColor(MWAWColor const &color)
412
0
  {
413
0
    m_overline->m_color = color;
414
0
  }
415
416
  //! returns the strikeoutline
417
  Line const &getStrikeOut() const
418
101k
  {
419
101k
    return m_strikeoutline.get();
420
101k
  }
421
  //! sets the strikeoutline
422
  void setStrikeOut(Line const &line)
423
0
  {
424
0
    m_strikeoutline = line;
425
0
  }
426
  //! sets the strikeoutline style ( by default, we also reset the style)
427
  void setStrikeOutStyle(Line::Style style=Line::None, bool doReset=true)
428
2.88M
  {
429
2.88M
    if (doReset)
430
2.88M
      m_strikeoutline = Line(style);
431
0
    else
432
0
      m_strikeoutline->m_style = style;
433
2.88M
  }
434
  //! sets the strikeoutline type
435
  void setStrikeOutType(Line::Type type=Line::Single)
436
1.08k
  {
437
1.08k
    m_strikeoutline->m_type = type;
438
1.08k
  }
439
  //! sets the strikeoutline word flag
440
  void setStrikeOutWordFlag(bool wordFlag=false)
441
0
  {
442
0
    m_strikeoutline->m_word = wordFlag;
443
0
  }
444
  //! sets the strikeoutline width
445
  void setStrikeOutWidth(float w)
446
0
  {
447
0
    m_strikeoutline->m_width = w;
448
0
  }
449
  //! sets the strikeoutline color
450
  void setStrikeOutColor(MWAWColor const &color)
451
0
  {
452
0
    m_strikeoutline->m_color = color;
453
0
  }
454
455
  //! returns the underline
456
  Line const &getUnderline() const
457
356k
  {
458
356k
    return m_underline.get();
459
356k
  }
460
  //! sets the underline
461
  void setUnderline(Line const &line)
462
41.7k
  {
463
41.7k
    m_underline = line;
464
41.7k
  }
465
  //! sets the underline style ( by default, we also reset the style)
466
  void setUnderlineStyle(Line::Style style=Line::None, bool doReset=true)
467
22.8M
  {
468
22.8M
    if (doReset)
469
22.8M
      m_underline = Line(style);
470
0
    else
471
0
      m_underline->m_style = style;
472
22.8M
  }
473
  //! sets the underline type
474
  void setUnderlineType(Line::Type type=Line::Single)
475
3.99M
  {
476
3.99M
    m_underline->m_type = type;
477
3.99M
  }
478
  //! sets the underline word flag
479
  void setUnderlineWordFlag(bool wordFlag=false)
480
264k
  {
481
264k
    m_underline->m_word = wordFlag;
482
264k
  }
483
  //! sets the underline width
484
  void setUnderlineWidth(float w)
485
14.3k
  {
486
14.3k
    m_underline->m_width = w;
487
14.3k
  }
488
  //! sets the underline color
489
  void setUnderlineColor(MWAWColor const &color)
490
1.76k
  {
491
1.76k
    m_underline->m_color = color;
492
1.76k
  }
493
494
  //! returns the language
495
  std::string const &language() const
496
0
  {
497
0
    return m_language.get();
498
0
  }
499
  //! set the language ( in the for en_US, en_GB, en, ...)
500
  void setLanguage(std::string const &lang)
501
4.33M
  {
502
4.33M
    m_language=lang;
503
4.33M
  }
504
  //! add to the propList
505
  void addTo(librevenge::RVNGPropertyList &propList, std::shared_ptr<MWAWFontConverter> fontConverter) const;
506
  //! add to the propList to a list level
507
  void addToListLevel(librevenge::RVNGPropertyList &propList, std::shared_ptr<MWAWFontConverter> fontConverter) const;
508
509
  //! returns a string which can be used for debugging
510
  std::string getDebugString(std::shared_ptr<MWAWFontConverter> &converter) const;
511
512
  //! operator==
513
  bool operator==(MWAWFont const &f) const
514
101M
  {
515
101M
    return cmp(f) == 0;
516
101M
  }
517
  //! operator!=
518
  bool operator!=(MWAWFont const &f) const
519
0
  {
520
0
    return cmp(f) != 0;
521
0
  }
522
523
  //! a comparison function
524
  int cmp(MWAWFont const &oth) const
525
101M
  {
526
101M
    int diff = id() - oth.id();
527
101M
    if (diff != 0) return diff;
528
83.2M
    if (size() < oth.size()) return -1;
529
75.8M
    if (size() > oth.size()) return 1;
530
74.4M
    if (m_sizeIsRelative.get() != oth.m_sizeIsRelative.get()) return m_sizeIsRelative.get() ? 1 : -1;
531
74.4M
    if (flags() < oth.flags()) return -1;
532
72.8M
    if (flags() > oth.flags()) return 1;
533
71.0M
    if (m_deltaSpacing.get() < oth.m_deltaSpacing.get()) return -1;
534
70.8M
    if (m_deltaSpacing.get() > oth.m_deltaSpacing.get()) return 1;
535
70.6M
    if (m_deltaSpacingUnit.get() < oth.m_deltaSpacingUnit.get()) return -1;
536
70.6M
    if (m_deltaSpacingUnit.get() > oth.m_deltaSpacingUnit.get()) return 1;
537
70.6M
    if (m_widthStreching.get() < oth.m_widthStreching.get()) return -1;
538
70.6M
    if (m_widthStreching.get() > oth.m_widthStreching.get()) return 1;
539
70.6M
    diff = script().cmp(oth.script());
540
70.6M
    if (diff != 0) return diff;
541
68.7M
    diff = m_overline.get().cmp(oth.m_overline.get());
542
68.7M
    if (diff != 0) return diff;
543
68.4M
    diff = m_strikeoutline.get().cmp(oth.m_strikeoutline.get());
544
68.4M
    if (diff != 0) return diff;
545
68.1M
    diff = m_underline.get().cmp(oth.m_underline.get());
546
68.1M
    if (diff != 0) return diff;
547
66.3M
    if (m_color.get() < oth.m_color.get()) return -1;
548
66.0M
    if (m_color.get() > oth.m_color.get()) return 1;
549
65.7M
    if (m_backgroundColor.get() < oth.m_backgroundColor.get()) return -1;
550
65.7M
    if (m_backgroundColor.get() > oth.m_backgroundColor.get()) return 1;
551
65.7M
    if (m_language.get() < oth.m_language.get()) return -1;
552
65.7M
    if (m_language.get() > oth.m_language.get()) return 1;
553
65.7M
    return diff;
554
65.7M
  }
555
556
protected:
557
  MWAWVariable<int> m_id /** font identificator*/;
558
  MWAWVariable<float> m_size /** font size */;
559
  MWAWVariable<bool> m_sizeIsRelative /** true if the size is percent */;
560
  MWAWVariable<float> m_deltaSpacing /** expand(&gt; 0), condensed(&lt; 0) depl*/;
561
  MWAWVariable<librevenge::RVNGUnit> m_deltaSpacingUnit /** the delta spacing unit */;
562
  MWAWVariable<float> m_widthStreching /** the width streching in percent */;
563
  MWAWVariable<Script> m_scriptPosition /** the sub/super script definition */;
564
  MWAWVariable<uint32_t> m_flags /** font attributes */;
565
  MWAWVariable<Line> m_overline /** overline attributes */;
566
  MWAWVariable<Line> m_strikeoutline /** overline attributes */;
567
  MWAWVariable<Line> m_underline /** underline attributes */;
568
  MWAWVariable<MWAWColor> m_color /** font color */;
569
  MWAWVariable<MWAWColor> m_backgroundColor /** font background color */;
570
  MWAWVariable<std::string> m_language /** the language if set */;
571
public:
572
  //! extra data
573
  std::string m_extra;
574
};
575
576
namespace MWAWFontManagerInternal
577
{
578
struct State;
579
}
580
581
//! a font manager which can be used to store fonts, ...
582
class MWAWFontManager
583
{
584
public:
585
  //! constructor
586
  explicit MWAWFontManager(std::shared_ptr<MWAWFontConverter> const &fontConverter);
587
  //! destructor
588
  ~MWAWFontManager();
589
  //! returns a span id which can be used to call the list
590
  int getId(MWAWFont const &font);
591
  //! returns the font corresponding to an id
592
  bool getFont(int id, MWAWFont &font) const;
593
  //! returns the font converter
594
  std::shared_ptr<MWAWFontConverter> getFontConverter();
595
protected:
596
  //! the state
597
  std::shared_ptr<MWAWFontManagerInternal::State> m_state;
598
private:
599
  MWAWFontManager(MWAWFontManager const &) = delete;
600
  MWAWFontManager &operator=(MWAWFontManager const &) = delete;
601
};
602
#endif
603
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: