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
9CharacterStyle::CharacterStyle()
10	:
11	fStyleData(new CharacterStyleData(), true)
12{
13}
14
15
16CharacterStyle::CharacterStyle(const CharacterStyle& other)
17	:
18	fStyleData(other.fStyleData)
19{
20}
21
22
23CharacterStyle&
24CharacterStyle::operator=(const CharacterStyle& other)
25{
26	if (this == &other)
27		return *this;
28
29	fStyleData = other.fStyleData;
30	return *this;
31}
32
33
34bool
35CharacterStyle::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.Get() != NULL && other.fStyleData.Get() != NULL)
44		return *fStyleData.Get() == *other.fStyleData.Get();
45
46	return false;
47}
48
49
50bool
51CharacterStyle::operator!=(const CharacterStyle& other) const
52{
53	return !(*this == other);
54}
55
56
57bool
58CharacterStyle::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
69const BFont&
70CharacterStyle::Font() const
71{
72	return fStyleData->Font();
73}
74
75
76bool
77CharacterStyle::SetFontSize(float size)
78{
79	BFont font(Font());
80	font.SetSize(size);
81	return SetFont(font);
82}
83
84
85float
86CharacterStyle::FontSize() const
87{
88	return Font().Size();
89}
90
91
92bool
93CharacterStyle::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		if ((face & B_ITALIC_FACE) != 0)
104			neededFace = B_BOLD_FACE | B_ITALIC_FACE;
105		else
106			neededFace = B_BOLD_FACE;
107	} else {
108		if ((face & B_ITALIC_FACE) != 0)
109			neededFace = B_ITALIC_FACE;
110		else
111			neededFace = B_REGULAR_FACE;
112	}
113
114	return SetFont(_FindFontForFace(neededFace));
115}
116
117
118bool
119CharacterStyle::IsBold() const
120{
121	return (Font().Face() & B_BOLD_FACE) != 0;
122}
123
124
125bool
126CharacterStyle::SetItalic(bool italic)
127{
128	uint16 face = Font().Face();
129	if ((italic && (face & B_ITALIC_FACE) != 0)
130		|| (!italic && (face & B_ITALIC_FACE) == 0)) {
131		return true;
132	}
133
134	uint16 neededFace = face;
135	if (italic) {
136		if ((face & B_BOLD_FACE) != 0)
137			neededFace = B_BOLD_FACE | B_ITALIC_FACE;
138		else
139			neededFace = B_ITALIC_FACE;
140	} else {
141		if ((face & B_BOLD_FACE) != 0)
142			neededFace = B_BOLD_FACE;
143		else
144			neededFace = B_REGULAR_FACE;
145	}
146
147	return SetFont(_FindFontForFace(neededFace));
148}
149
150
151bool
152CharacterStyle::IsItalic() const
153{
154	return (Font().Face() & B_ITALIC_FACE) != 0;
155}
156
157
158bool
159CharacterStyle::SetAscent(float ascent)
160{
161	CharacterStyleDataRef data = fStyleData->SetAscent(ascent);
162	if (data == fStyleData)
163		return data->Ascent() == ascent;
164
165	fStyleData = data;
166	return true;
167}
168
169
170float
171CharacterStyle::Ascent() const
172{
173	return fStyleData->Ascent();
174}
175
176
177bool
178CharacterStyle::SetDescent(float descent)
179{
180	CharacterStyleDataRef data = fStyleData->SetDescent(descent);
181	if (data == fStyleData)
182		return data->Descent() == descent;
183
184	fStyleData = data;
185	return true;
186}
187
188
189float
190CharacterStyle::Descent() const
191{
192	return fStyleData->Descent();
193}
194
195
196bool
197CharacterStyle::SetWidth(float width)
198{
199	CharacterStyleDataRef data = fStyleData->SetWidth(width);
200	if (data == fStyleData)
201		return data->Width() == width;
202
203	fStyleData = data;
204	return true;
205}
206
207
208float
209CharacterStyle::Width() const
210{
211	return fStyleData->Width();
212}
213
214
215bool
216CharacterStyle::SetGlyphSpacing(float spacing)
217{
218	CharacterStyleDataRef data = fStyleData->SetGlyphSpacing(spacing);
219	if (data == fStyleData)
220		return data->GlyphSpacing() == spacing;
221
222	fStyleData = data;
223	return true;
224}
225
226
227float
228CharacterStyle::GlyphSpacing() const
229{
230	return fStyleData->GlyphSpacing();
231}
232
233
234bool
235CharacterStyle::SetForegroundColor(uint8 r, uint8 g, uint8 b, uint8 a)
236{
237	return SetForegroundColor((rgb_color){ r, g, b, a });
238}
239
240
241bool
242CharacterStyle::SetForegroundColor(color_which which)
243{
244	CharacterStyleDataRef data = fStyleData->SetForegroundColor(which);
245	if (data == fStyleData)
246		return data->WhichForegroundColor() == which;
247
248	fStyleData = data;
249	return true;
250}
251
252
253bool
254CharacterStyle::SetForegroundColor(rgb_color color)
255{
256	CharacterStyleDataRef data = fStyleData->SetForegroundColor(color);
257	if (data == fStyleData)
258		return data->ForegroundColor() == color;
259
260	fStyleData = data;
261	return true;
262}
263
264
265rgb_color
266CharacterStyle::ForegroundColor() const
267{
268	return fStyleData->ForegroundColor();
269}
270
271
272color_which
273CharacterStyle::WhichForegroundColor() const
274{
275	return fStyleData->WhichForegroundColor();
276}
277
278
279bool
280CharacterStyle::SetBackgroundColor(uint8 r, uint8 g, uint8 b, uint8 a)
281{
282	return SetBackgroundColor((rgb_color){ r, g, b, a });
283}
284
285
286bool
287CharacterStyle::SetBackgroundColor(color_which which)
288{
289	CharacterStyleDataRef data = fStyleData->SetBackgroundColor(which);
290	if (data == fStyleData)
291		return data->WhichBackgroundColor() == which;
292
293	fStyleData = data;
294	return true;
295}
296
297
298bool
299CharacterStyle::SetBackgroundColor(rgb_color color)
300{
301	CharacterStyleDataRef data = fStyleData->SetBackgroundColor(color);
302	if (data == fStyleData)
303		return data->BackgroundColor() == color;
304
305	fStyleData = data;
306	return true;
307}
308
309
310rgb_color
311CharacterStyle::BackgroundColor() const
312{
313	return fStyleData->BackgroundColor();
314}
315
316
317color_which
318CharacterStyle::WhichBackgroundColor() const
319{
320	return fStyleData->WhichBackgroundColor();
321}
322
323
324bool
325CharacterStyle::SetStrikeOutColor(color_which which)
326{
327	CharacterStyleDataRef data = fStyleData->SetStrikeOutColor(which);
328	if (data == fStyleData)
329		return data->WhichStrikeOutColor() == which;
330
331	fStyleData = data;
332	return true;
333}
334
335
336bool
337CharacterStyle::SetStrikeOutColor(rgb_color color)
338{
339	CharacterStyleDataRef data = fStyleData->SetStrikeOutColor(color);
340	if (data == fStyleData)
341		return data->StrikeOutColor() == color;
342
343	fStyleData = data;
344	return true;
345}
346
347
348rgb_color
349CharacterStyle::StrikeOutColor() const
350{
351	return fStyleData->StrikeOutColor();
352}
353
354
355color_which
356CharacterStyle::WhichStrikeOutColor() const
357{
358	return fStyleData->WhichStrikeOutColor();
359}
360
361
362bool
363CharacterStyle::SetUnderlineColor(color_which which)
364{
365	CharacterStyleDataRef data = fStyleData->SetUnderlineColor(which);
366	if (data == fStyleData)
367		return data->WhichUnderlineColor() == which;
368
369	fStyleData = data;
370	return true;
371}
372
373
374bool
375CharacterStyle::SetUnderlineColor(rgb_color color)
376{
377	CharacterStyleDataRef data = fStyleData->SetUnderlineColor(color);
378	if (data == fStyleData)
379		return data->UnderlineColor() == color;
380
381	fStyleData = data;
382	return true;
383}
384
385
386rgb_color
387CharacterStyle::UnderlineColor() const
388{
389	return fStyleData->UnderlineColor();
390}
391
392
393color_which
394CharacterStyle::WhichUnderlineColor() const
395{
396	return fStyleData->WhichUnderlineColor();
397}
398
399
400bool
401CharacterStyle::SetStrikeOut(uint8 strikeOut)
402{
403	CharacterStyleDataRef data = fStyleData->SetStrikeOut(strikeOut);
404	if (data == fStyleData)
405		return data->StrikeOut() == strikeOut;
406
407	fStyleData = data;
408	return true;
409}
410
411
412uint8
413CharacterStyle::StrikeOut() const
414{
415	return fStyleData->StrikeOut();
416}
417
418
419bool
420CharacterStyle::SetUnderline(uint8 underline)
421{
422	CharacterStyleDataRef data = fStyleData->SetUnderline(underline);
423	if (data == fStyleData)
424		return data->Underline() == underline;
425
426	fStyleData = data;
427	return true;
428}
429
430
431uint8
432CharacterStyle::Underline() const
433{
434	return fStyleData->Underline();
435}
436
437
438// #pragma mark - private
439
440
441BFont
442CharacterStyle::_FindFontForFace(uint16 face) const
443{
444	BFont font(Font());
445
446	font_family family;
447	font_style style;
448	font.GetFamilyAndStyle(&family, &style);
449
450	int32 styleCount = count_font_styles(family);
451	for (int32 i = 0; i < styleCount; i++) {
452		uint16 styleFace;
453		if (get_font_style(family, i, &style, &styleFace) == B_OK) {
454			if (styleFace == face) {
455				font.SetFamilyAndStyle(family, style);
456				return font;
457			}
458		}
459	}
460
461	return font;
462}
463
464