Coverage Report

Created: 2025-11-09 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wt/src/Wt/WFont.C
Line
Count
Source
1
/*
2
 * Copyright (C) 2008 Emweb bv, Herent, Belgium.
3
 *
4
 * See the LICENSE file for terms of use.
5
 */
6
#include "Wt/WFont.h"
7
#include "Wt/WStringStream.h"
8
#include "Wt/WWebWidget.h"
9
10
#include "DomElement.h"
11
12
#include <algorithm>
13
14
namespace Wt {
15
16
WFont::WFont()
17
0
  : widget_(nullptr),
18
0
    genericFamily_(FontFamily::Default),
19
0
    style_(FontStyle::Normal),
20
0
    variant_(FontVariant::Normal),
21
0
    weight_(FontWeight::Normal),
22
0
    weightValue_(400),
23
0
    size_(FontSize::Medium),
24
0
    familyChanged_(false),
25
0
    styleChanged_(false),
26
0
    variantChanged_(false),
27
0
    weightChanged_(false),
28
0
    sizeChanged_(false)
29
0
{ }
30
31
WFont::WFont(FontFamily family)
32
0
  : widget_(nullptr),
33
0
    genericFamily_(family),
34
0
    style_(FontStyle::Normal),
35
0
    variant_(FontVariant::Normal),
36
0
    weight_(FontWeight::Normal),
37
0
    weightValue_(400),
38
0
    size_(FontSize::Medium),
39
0
    familyChanged_(false),
40
0
    styleChanged_(false),
41
0
    variantChanged_(false),
42
0
    weightChanged_(false),
43
0
    sizeChanged_(false)
44
0
{ }
45
46
void WFont::setWebWidget(WWebWidget *w)
47
0
{
48
0
  widget_ = w;
49
0
}
50
51
bool WFont::operator==(const WFont& other) const
52
0
{
53
0
  return
54
0
       genericFamily_    == other.genericFamily_
55
0
    && specificFamilies_ == other.specificFamilies_
56
0
    && style_            == other.style_
57
0
    && variant_          == other.variant_
58
0
    && weight_           == other.weight_
59
0
    && weightValue_      == other.weightValue_
60
0
    && size_             == other.size_
61
0
    && sizeLength_       == other.sizeLength_;
62
0
}
63
64
bool WFont::operator!=(const WFont& other) const
65
0
{
66
0
  return !(*this == other);
67
0
}
68
69
void WFont::setFamily(FontFamily genericFamily,
70
                      const WString& specificFamilies)
71
0
{
72
0
  genericFamily_ = genericFamily;
73
0
  specificFamilies_ = specificFamilies;
74
0
  familyChanged_ = true;
75
0
  if (widget_) widget_->repaint(RepaintFlag::SizeAffected);
76
0
}
77
78
void WFont::setStyle(FontStyle style)
79
0
{
80
0
  style_ = style;
81
0
  styleChanged_ = true;
82
0
  if (widget_) widget_->repaint(RepaintFlag::SizeAffected);
83
0
}
84
85
void WFont::setVariant(FontVariant variant)
86
0
{
87
0
  variant_ = variant;
88
0
  variantChanged_ = true;
89
0
  if (widget_) widget_->repaint(RepaintFlag::SizeAffected);
90
0
}
91
92
void WFont::setWeight(FontWeight weight, int value)
93
0
{
94
0
  weight_ = weight;
95
0
  weightValue_ = value;
96
0
  weightChanged_ = true;
97
0
  if (widget_) widget_->repaint(RepaintFlag::SizeAffected);
98
0
}
99
100
FontWeight WFont::weight() const
101
0
{
102
0
  if (weight_ != FontWeight::Value)
103
0
    return weight_;
104
0
  else
105
0
    return weightValue_ >= 700 ? FontWeight::Bold : FontWeight::Normal;
106
0
}
107
108
int WFont::weightValue() const
109
0
{
110
0
  switch (weight_) {
111
0
  case FontWeight::Normal:
112
0
  case FontWeight::Lighter:
113
0
    return 400;
114
0
  case FontWeight::Bold:
115
0
  case FontWeight::Bolder:
116
0
    return 700;
117
0
  case FontWeight::Value:
118
0
    return weightValue_;
119
0
  }
120
121
0
  assert(false);
122
0
  return -1;
123
0
}
124
125
void WFont::setSize(FontSize size)
126
0
{
127
0
  size_ = size;
128
0
  sizeLength_ = WLength::Auto;
129
0
  sizeChanged_ = true;
130
0
  if (widget_) widget_->repaint(RepaintFlag::SizeAffected);
131
0
}
132
133
void WFont::setSize(const WLength& size)
134
0
{
135
0
  size_ = FontSize::FixedSize;
136
0
  sizeLength_ = size;
137
0
  sizeChanged_ = true;
138
0
  if (widget_) widget_->repaint(RepaintFlag::SizeAffected);
139
0
}
140
141
FontSize WFont::size(double mediumSize) const
142
0
{
143
0
  if (size_ != FontSize::FixedSize)
144
0
    return size_;
145
0
  else {
146
0
    double pixels = sizeLength_.toPixels();
147
148
0
    if (pixels == mediumSize)
149
0
      return FontSize::Medium;
150
0
    else if (pixels > mediumSize) {
151
0
      if (pixels < 1.2 * 1.19 * mediumSize)
152
0
        return FontSize::Large;
153
0
      else if (pixels < 1.2 * 1.2 * 1.19 * mediumSize)
154
0
        return FontSize::XLarge;
155
0
      else
156
0
        return FontSize::XXLarge;
157
0
    } else {
158
0
      if (pixels > mediumSize / 1.2 / 1.19)
159
0
        return FontSize::Small;
160
0
      else if (pixels > mediumSize / 1.2 / 1.2 / 1.19)
161
0
        return FontSize::XSmall;
162
0
      else
163
0
        return FontSize::XXSmall;
164
0
    }
165
0
  }
166
0
}
167
168
WLength WFont::sizeLength(double mediumSize) const
169
0
{
170
0
  switch (size_) {
171
0
  case FontSize::FixedSize:
172
0
    return sizeLength_;
173
0
  case FontSize::XXSmall:
174
0
    return WLength(mediumSize / 1.2 / 1.2 / 1.2);
175
0
  case FontSize::XSmall:
176
0
    return WLength(mediumSize / 1.2 / 1.2);
177
0
  case FontSize::Small:
178
0
    return WLength(mediumSize / 1.2);
179
0
  case FontSize::Medium:
180
0
    return WLength(mediumSize);
181
0
  case FontSize::Large:
182
0
    return WLength(mediumSize * 1.2);
183
0
  case FontSize::XLarge:
184
0
    return WLength(mediumSize * 1.2 * 1.2);
185
0
  case FontSize::XXLarge:
186
0
    return WLength(mediumSize * 1.2 * 1.2 * 1.2);
187
0
  case FontSize::Smaller:
188
0
    return WLength(1 / 1.2, LengthUnit::FontEm);
189
0
  case FontSize::Larger:
190
0
    return WLength(1.2, LengthUnit::FontEm);
191
0
  }
192
193
0
  assert(false);
194
0
  return WLength();
195
0
}
196
197
void WFont::updateDomElement(DomElement& element, bool fontall, bool all)
198
0
{
199
0
  if (familyChanged_ || fontall || all) {
200
0
    std::string family = cssFamily(fontall);
201
202
0
    if (!family.empty())
203
0
      element.setProperty(Property::StyleFontFamily, family);
204
205
0
    familyChanged_ = false;
206
0
  }
207
208
0
  if (styleChanged_ || fontall || all) {
209
0
    std::string style = cssStyle(fontall);
210
211
0
    if (!style.empty())
212
0
      element.setProperty(Property::StyleFontStyle, style);
213
214
0
    styleChanged_ = false;
215
0
  }
216
217
0
  if (variantChanged_ || fontall || all) {
218
0
    std::string variant = cssVariant(fontall);
219
220
0
    if (!variant.empty())
221
0
      element.setProperty(Property::StyleFontVariant, variant);
222
223
0
    variantChanged_ = false;
224
0
  }
225
226
0
  if (weightChanged_ || fontall || all) {
227
0
    std::string weight = cssWeight(fontall);
228
229
0
    if (!weight.empty())
230
0
      element.setProperty(Property::StyleFontWeight, weight);
231
232
0
    weightChanged_ = false;
233
0
  }
234
235
0
  if (sizeChanged_ || fontall || all) {
236
0
    std::string size = cssSize(fontall);
237
238
0
    if (!size.empty())
239
0
      element.setProperty(Property::StyleFontSize, size);
240
241
0
    sizeChanged_ = false;
242
0
  }
243
0
}
244
245
std::string WFont::cssStyle(bool all) const
246
0
{
247
0
  switch (style_) {
248
0
  case FontStyle::Normal:
249
0
    if (styleChanged_ || all)
250
0
      return "normal";
251
0
    break;
252
0
  case FontStyle::Italic: return "italic";
253
0
  case FontStyle::Oblique: return "oblique";
254
0
  }
255
256
0
  return std::string();
257
0
}
258
259
std::string WFont::cssVariant(bool all) const
260
0
{
261
0
  switch (variant_) {
262
0
  case FontVariant::Normal:
263
0
    if (variantChanged_ || all)
264
0
      return "normal";
265
0
    break;
266
0
  case FontVariant::SmallCaps:
267
0
    return "small-caps";
268
0
  }
269
270
0
  return std::string();
271
0
}
272
273
274
std::string WFont::cssWeight(bool all) const
275
0
{
276
0
  switch (weight_) {
277
0
  case FontWeight::Normal:
278
0
    if (weightChanged_ || all)
279
0
      return "normal";
280
0
    break;
281
0
  case FontWeight::Bold: return "bold";
282
0
  case FontWeight::Bolder:return "bolder";
283
0
  case FontWeight::Lighter: return "lighter";
284
0
  case FontWeight::Value: {
285
0
    int v = std::min(900, std::max(100, ((weightValue_ / 100))*100));
286
0
    return std::to_string(v);
287
0
  }
288
0
  }
289
290
0
  return std::string();
291
0
}
292
293
std::string WFont::cssSize(bool all) const
294
0
{
295
0
  switch (size_) {
296
0
  case FontSize::Medium:
297
0
    if (sizeChanged_ || all)
298
0
      return "medium";
299
0
    break;
300
0
  case FontSize::XXSmall: return "xx-small";
301
0
  case FontSize::XSmall: return "x-small";
302
0
  case FontSize::Small: return "small";
303
0
  case FontSize::Large: return "large" ;
304
0
  case FontSize::XLarge: return "x-large" ;
305
0
  case FontSize::XXLarge: return "xx-large";
306
0
  case FontSize::Smaller: return "smaller";
307
0
  case FontSize::Larger: return "larger";
308
0
  case FontSize::FixedSize: return sizeLength_.cssText();
309
0
  }
310
311
0
  return std::string();
312
0
}
313
314
std::string WFont::cssFamily(bool) const
315
0
{
316
0
  std::string family = specificFamilies_.toUTF8();
317
318
0
  if ((!family.empty()) &&
319
0
      genericFamily_ != FontFamily::Default)
320
0
    family += ',';
321
322
0
  switch (genericFamily_) {
323
0
  case FontFamily::Default:
324
0
    break;
325
0
  case FontFamily::Serif:
326
0
    family += "serif"; break;
327
0
  case FontFamily::SansSerif:
328
0
    family += "sans-serif"; break;
329
0
  case FontFamily::Cursive:
330
0
    family += "cursive"; break;
331
0
  case FontFamily::Fantasy:
332
0
    family += "fantasy"; break;
333
0
  case FontFamily::Monospace:
334
0
    family += "monospace"; break;
335
0
  }
336
337
0
  return family;
338
0
}
339
340
const std::string WFont::cssText(bool combined) const
341
0
{
342
0
  WStringStream result;
343
344
0
  if (combined) {
345
0
    std::string s;
346
0
    s = cssStyle(false);
347
0
    if (!s.empty())
348
0
      result << s << ' ';
349
350
0
    s = cssVariant(false);
351
0
    if (!s.empty())
352
0
      result << s << ' ';
353
354
0
    s = cssWeight(false);
355
0
    if (!s.empty())
356
0
      result << s << ' ';
357
358
0
    result << cssSize(true) << ' ';
359
360
0
    s = cssFamily(true);
361
0
    if (!s.empty())
362
0
      result << s << ' ';
363
0
    else
364
0
      result << s << " inherit";
365
0
  } else {
366
0
    std::string s;
367
0
    s = cssSize(false);
368
0
    if (!s.empty())
369
0
      result << "font-size: " << s << ";";
370
371
0
    s = cssStyle(false);
372
0
    if (!s.empty())
373
0
      result << "font-style: " << s << ";";
374
375
0
    s = cssVariant(false);
376
0
    if (!s.empty())
377
0
      result << "font-variant: " << s << ";";
378
379
0
    s = cssWeight(false);
380
0
    if (!s.empty())
381
0
      result << "font-weight: " << s << ";";
382
383
    // Last because of workaround in WVmlImage that searches for a ','
384
0
    s = cssFamily(false);
385
0
    if (!s.empty())
386
0
      result << "font-family: " << s << ";";
387
388
0
  }
389
390
0
  return result.str();
391
0
}
392
393
}