1 /*
2 * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5
6 #include "CharacterStyle.h"
7
8
CharacterStyle()9 CharacterStyle::CharacterStyle()
10 :
11 fStyleData(new CharacterStyleData(), true)
12 {
13 }
14
15
CharacterStyle(const CharacterStyle & other)16 CharacterStyle::CharacterStyle(const CharacterStyle& other)
17 :
18 fStyleData(other.fStyleData)
19 {
20 }
21
22
23 CharacterStyle&
operator =(const CharacterStyle & other)24 CharacterStyle::operator=(const CharacterStyle& other)
25 {
26 if (this == &other)
27 return *this;
28
29 fStyleData = other.fStyleData;
30 return *this;
31 }
32
33
34 bool
operator ==(const CharacterStyle & other) const35 CharacterStyle::operator==(const CharacterStyle& other) const
36 {
37 if (this == &other)
38 return true;
39
40 if (fStyleData == other.fStyleData)
41 return true;
42
43 if (fStyleData.IsSet() && other.fStyleData.IsSet())
44 return *fStyleData == *other.fStyleData;
45
46 return false;
47 }
48
49
50 bool
operator !=(const CharacterStyle & other) const51 CharacterStyle::operator!=(const CharacterStyle& other) const
52 {
53 return !(*this == other);
54 }
55
56
57 bool
SetFont(const BFont & font)58 CharacterStyle::SetFont(const BFont& font)
59 {
60 CharacterStyleDataRef data = fStyleData->SetFont(font);
61 if (data == fStyleData)
62 return data->Font() == font;
63
64 fStyleData = data;
65 return true;
66 }
67
68
69 const BFont&
Font() const70 CharacterStyle::Font() const
71 {
72 return fStyleData->Font();
73 }
74
75
76 bool
SetFontSize(float size)77 CharacterStyle::SetFontSize(float size)
78 {
79 BFont font(Font());
80 font.SetSize(size);
81 return SetFont(font);
82 }
83
84
85 float
FontSize() const86 CharacterStyle::FontSize() const
87 {
88 return Font().Size();
89 }
90
91
92 bool
SetBold(bool bold)93 CharacterStyle::SetBold(bool bold)
94 {
95 uint16 face = Font().Face();
96 if ((bold && (face & B_BOLD_FACE) != 0)
97 || (!bold && (face & B_BOLD_FACE) == 0)) {
98 return true;
99 }
100
101 uint16 neededFace = face;
102 if (bold) {
103 neededFace |= B_BOLD_FACE;
104 neededFace &= ~B_REGULAR_FACE;
105 } else {
106 neededFace &= ~B_BOLD_FACE;
107 if (neededFace == 0)
108 neededFace |= B_REGULAR_FACE;
109 }
110
111 return SetFont(_FindFontForFace(neededFace));
112 }
113
114
115 bool
IsBold() const116 CharacterStyle::IsBold() const
117 {
118 return (Font().Face() & B_BOLD_FACE) != 0;
119 }
120
121
122 bool
SetItalic(bool italic)123 CharacterStyle::SetItalic(bool italic)
124 {
125 uint16 face = Font().Face();
126 if ((italic && (face & B_ITALIC_FACE) != 0)
127 || (!italic && (face & B_ITALIC_FACE) == 0)) {
128 return true;
129 }
130
131 uint16 neededFace = face;
132 if (italic) {
133 neededFace |= B_ITALIC_FACE;
134 neededFace &= ~B_REGULAR_FACE;
135 } else {
136 neededFace &= ~B_ITALIC_FACE;
137 if (neededFace == 0)
138 neededFace |= B_REGULAR_FACE;
139 }
140
141 return SetFont(_FindFontForFace(neededFace));
142 }
143
144
145 bool
IsItalic() const146 CharacterStyle::IsItalic() const
147 {
148 return (Font().Face() & B_ITALIC_FACE) != 0;
149 }
150
151
152 bool
SetAscent(float ascent)153 CharacterStyle::SetAscent(float ascent)
154 {
155 CharacterStyleDataRef data = fStyleData->SetAscent(ascent);
156 if (data == fStyleData)
157 return data->Ascent() == ascent;
158
159 fStyleData = data;
160 return true;
161 }
162
163
164 float
Ascent() const165 CharacterStyle::Ascent() const
166 {
167 return fStyleData->Ascent();
168 }
169
170
171 bool
SetDescent(float descent)172 CharacterStyle::SetDescent(float descent)
173 {
174 CharacterStyleDataRef data = fStyleData->SetDescent(descent);
175 if (data == fStyleData)
176 return data->Descent() == descent;
177
178 fStyleData = data;
179 return true;
180 }
181
182
183 float
Descent() const184 CharacterStyle::Descent() const
185 {
186 return fStyleData->Descent();
187 }
188
189
190 bool
SetWidth(float width)191 CharacterStyle::SetWidth(float width)
192 {
193 CharacterStyleDataRef data = fStyleData->SetWidth(width);
194 if (data == fStyleData)
195 return data->Width() == width;
196
197 fStyleData = data;
198 return true;
199 }
200
201
202 float
Width() const203 CharacterStyle::Width() const
204 {
205 return fStyleData->Width();
206 }
207
208
209 bool
SetGlyphSpacing(float spacing)210 CharacterStyle::SetGlyphSpacing(float spacing)
211 {
212 CharacterStyleDataRef data = fStyleData->SetGlyphSpacing(spacing);
213 if (data == fStyleData)
214 return data->GlyphSpacing() == spacing;
215
216 fStyleData = data;
217 return true;
218 }
219
220
221 float
GlyphSpacing() const222 CharacterStyle::GlyphSpacing() const
223 {
224 return fStyleData->GlyphSpacing();
225 }
226
227
228 bool
SetForegroundColor(uint8 r,uint8 g,uint8 b,uint8 a)229 CharacterStyle::SetForegroundColor(uint8 r, uint8 g, uint8 b, uint8 a)
230 {
231 return SetForegroundColor((rgb_color){ r, g, b, a });
232 }
233
234
235 bool
SetForegroundColor(color_which which)236 CharacterStyle::SetForegroundColor(color_which which)
237 {
238 CharacterStyleDataRef data = fStyleData->SetForegroundColor(which);
239 if (data == fStyleData)
240 return data->WhichForegroundColor() == which;
241
242 fStyleData = data;
243 return true;
244 }
245
246
247 bool
SetForegroundColor(rgb_color color)248 CharacterStyle::SetForegroundColor(rgb_color color)
249 {
250 CharacterStyleDataRef data = fStyleData->SetForegroundColor(color);
251 if (data == fStyleData)
252 return data->ForegroundColor() == color;
253
254 fStyleData = data;
255 return true;
256 }
257
258
259 rgb_color
ForegroundColor() const260 CharacterStyle::ForegroundColor() const
261 {
262 return fStyleData->ForegroundColor();
263 }
264
265
266 color_which
WhichForegroundColor() const267 CharacterStyle::WhichForegroundColor() const
268 {
269 return fStyleData->WhichForegroundColor();
270 }
271
272
273 bool
SetBackgroundColor(uint8 r,uint8 g,uint8 b,uint8 a)274 CharacterStyle::SetBackgroundColor(uint8 r, uint8 g, uint8 b, uint8 a)
275 {
276 return SetBackgroundColor((rgb_color){ r, g, b, a });
277 }
278
279
280 bool
SetBackgroundColor(color_which which)281 CharacterStyle::SetBackgroundColor(color_which which)
282 {
283 CharacterStyleDataRef data = fStyleData->SetBackgroundColor(which);
284 if (data == fStyleData)
285 return data->WhichBackgroundColor() == which;
286
287 fStyleData = data;
288 return true;
289 }
290
291
292 bool
SetBackgroundColor(rgb_color color)293 CharacterStyle::SetBackgroundColor(rgb_color color)
294 {
295 CharacterStyleDataRef data = fStyleData->SetBackgroundColor(color);
296 if (data == fStyleData)
297 return data->BackgroundColor() == color;
298
299 fStyleData = data;
300 return true;
301 }
302
303
304 rgb_color
BackgroundColor() const305 CharacterStyle::BackgroundColor() const
306 {
307 return fStyleData->BackgroundColor();
308 }
309
310
311 color_which
WhichBackgroundColor() const312 CharacterStyle::WhichBackgroundColor() const
313 {
314 return fStyleData->WhichBackgroundColor();
315 }
316
317
318 bool
SetStrikeOutColor(color_which which)319 CharacterStyle::SetStrikeOutColor(color_which which)
320 {
321 CharacterStyleDataRef data = fStyleData->SetStrikeOutColor(which);
322 if (data == fStyleData)
323 return data->WhichStrikeOutColor() == which;
324
325 fStyleData = data;
326 return true;
327 }
328
329
330 bool
SetStrikeOutColor(rgb_color color)331 CharacterStyle::SetStrikeOutColor(rgb_color color)
332 {
333 CharacterStyleDataRef data = fStyleData->SetStrikeOutColor(color);
334 if (data == fStyleData)
335 return data->StrikeOutColor() == color;
336
337 fStyleData = data;
338 return true;
339 }
340
341
342 rgb_color
StrikeOutColor() const343 CharacterStyle::StrikeOutColor() const
344 {
345 return fStyleData->StrikeOutColor();
346 }
347
348
349 color_which
WhichStrikeOutColor() const350 CharacterStyle::WhichStrikeOutColor() const
351 {
352 return fStyleData->WhichStrikeOutColor();
353 }
354
355
356 bool
SetUnderlineColor(color_which which)357 CharacterStyle::SetUnderlineColor(color_which which)
358 {
359 CharacterStyleDataRef data = fStyleData->SetUnderlineColor(which);
360 if (data == fStyleData)
361 return data->WhichUnderlineColor() == which;
362
363 fStyleData = data;
364 return true;
365 }
366
367
368 bool
SetUnderlineColor(rgb_color color)369 CharacterStyle::SetUnderlineColor(rgb_color color)
370 {
371 CharacterStyleDataRef data = fStyleData->SetUnderlineColor(color);
372 if (data == fStyleData)
373 return data->UnderlineColor() == color;
374
375 fStyleData = data;
376 return true;
377 }
378
379
380 rgb_color
UnderlineColor() const381 CharacterStyle::UnderlineColor() const
382 {
383 return fStyleData->UnderlineColor();
384 }
385
386
387 color_which
WhichUnderlineColor() const388 CharacterStyle::WhichUnderlineColor() const
389 {
390 return fStyleData->WhichUnderlineColor();
391 }
392
393
394 bool
SetStrikeOut(uint8 strikeOut)395 CharacterStyle::SetStrikeOut(uint8 strikeOut)
396 {
397 CharacterStyleDataRef data = fStyleData->SetStrikeOut(strikeOut);
398 if (data == fStyleData)
399 return data->StrikeOut() == strikeOut;
400
401 fStyleData = data;
402 return true;
403 }
404
405
406 uint8
StrikeOut() const407 CharacterStyle::StrikeOut() const
408 {
409 return fStyleData->StrikeOut();
410 }
411
412
413 bool
SetUnderline(uint8 underline)414 CharacterStyle::SetUnderline(uint8 underline)
415 {
416 #if 1
417 uint16 face = Font().Face();
418 if ((underline && (face & B_UNDERSCORE_FACE) != 0)
419 || (!underline && (face & B_UNDERSCORE_FACE) == 0)) {
420 return true;
421 }
422
423 uint16 neededFace = face;
424 if (underline) {
425 neededFace |= B_UNDERSCORE_FACE;
426 neededFace &= ~B_REGULAR_FACE;
427 } else {
428 neededFace &= ~B_UNDERSCORE_FACE;
429 if (neededFace == 0)
430 neededFace |= B_REGULAR_FACE;
431 }
432
433 return SetFont(_FindFontForFace(neededFace));
434 #else
435 // TODO: re-enable this instead of using B_UNDERSCORE_FACE when TextDocumentView actually
436 // implements drawing the fancy underline styles. Until then, we can at least get simple
437 // underlines.
438 CharacterStyleDataRef data = fStyleData->SetUnderline(underline);
439 if (data == fStyleData)
440 return data->Underline() == underline;
441
442 fStyleData = data;
443 return true;
444 #endif
445 }
446
447
448 uint8
Underline() const449 CharacterStyle::Underline() const
450 {
451 return fStyleData->Underline();
452 }
453
454
455 // #pragma mark - private
456
457
458 BFont
_FindFontForFace(uint16 face) const459 CharacterStyle::_FindFontForFace(uint16 face) const
460 {
461 BFont font(Font());
462 font.SetFamilyAndFace(NULL, face);
463
464 return font;
465 }
466
467