xref: /haiku/src/apps/haikudepot/textview/CharacterStyle.cpp (revision 4a850ca730d8282b5b924e49e09b4ba4d6db7f54)
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 
9 CharacterStyle::CharacterStyle()
10 	:
11 	fStyleData(new CharacterStyleData(), true)
12 {
13 }
14 
15 
16 CharacterStyle::CharacterStyle(const CharacterStyle& other)
17 	:
18 	fStyleData(other.fStyleData)
19 {
20 }
21 
22 
23 CharacterStyle&
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
35 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
51 CharacterStyle::operator!=(const CharacterStyle& other) const
52 {
53 	return !(*this == other);
54 }
55 
56 
57 bool
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&
70 CharacterStyle::Font() const
71 {
72 	return fStyleData->Font();
73 }
74 
75 
76 bool
77 CharacterStyle::SetFontSize(float size)
78 {
79 	BFont font(Font());
80 	font.SetSize(size);
81 	return SetFont(font);
82 }
83 
84 
85 float
86 CharacterStyle::FontSize() const
87 {
88 	return Font().Size();
89 }
90 
91 
92 bool
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 		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 
118 bool
119 CharacterStyle::IsBold() const
120 {
121 	return (Font().Face() & B_BOLD_FACE) != 0;
122 }
123 
124 
125 bool
126 CharacterStyle::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 
151 bool
152 CharacterStyle::IsItalic() const
153 {
154 	return (Font().Face() & B_ITALIC_FACE) != 0;
155 }
156 
157 
158 bool
159 CharacterStyle::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 
170 float
171 CharacterStyle::Ascent() const
172 {
173 	return fStyleData->Ascent();
174 }
175 
176 
177 bool
178 CharacterStyle::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 
189 float
190 CharacterStyle::Descent() const
191 {
192 	return fStyleData->Descent();
193 }
194 
195 
196 bool
197 CharacterStyle::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 
208 float
209 CharacterStyle::Width() const
210 {
211 	return fStyleData->Width();
212 }
213 
214 
215 bool
216 CharacterStyle::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 
227 float
228 CharacterStyle::GlyphSpacing() const
229 {
230 	return fStyleData->GlyphSpacing();
231 }
232 
233 
234 bool
235 CharacterStyle::SetForegroundColor(uint8 r, uint8 g, uint8 b, uint8 a)
236 {
237 	return SetForegroundColor((rgb_color){ r, g, b, a });
238 }
239 
240 
241 bool
242 CharacterStyle::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 
253 bool
254 CharacterStyle::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 
265 rgb_color
266 CharacterStyle::ForegroundColor() const
267 {
268 	return fStyleData->ForegroundColor();
269 }
270 
271 
272 color_which
273 CharacterStyle::WhichForegroundColor() const
274 {
275 	return fStyleData->WhichForegroundColor();
276 }
277 
278 
279 bool
280 CharacterStyle::SetBackgroundColor(uint8 r, uint8 g, uint8 b, uint8 a)
281 {
282 	return SetBackgroundColor((rgb_color){ r, g, b, a });
283 }
284 
285 
286 bool
287 CharacterStyle::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 
298 bool
299 CharacterStyle::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 
310 rgb_color
311 CharacterStyle::BackgroundColor() const
312 {
313 	return fStyleData->BackgroundColor();
314 }
315 
316 
317 color_which
318 CharacterStyle::WhichBackgroundColor() const
319 {
320 	return fStyleData->WhichBackgroundColor();
321 }
322 
323 
324 bool
325 CharacterStyle::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 
336 bool
337 CharacterStyle::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 
348 rgb_color
349 CharacterStyle::StrikeOutColor() const
350 {
351 	return fStyleData->StrikeOutColor();
352 }
353 
354 
355 color_which
356 CharacterStyle::WhichStrikeOutColor() const
357 {
358 	return fStyleData->WhichStrikeOutColor();
359 }
360 
361 
362 bool
363 CharacterStyle::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 
374 bool
375 CharacterStyle::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 
386 rgb_color
387 CharacterStyle::UnderlineColor() const
388 {
389 	return fStyleData->UnderlineColor();
390 }
391 
392 
393 color_which
394 CharacterStyle::WhichUnderlineColor() const
395 {
396 	return fStyleData->WhichUnderlineColor();
397 }
398 
399 
400 bool
401 CharacterStyle::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 
412 uint8
413 CharacterStyle::StrikeOut() const
414 {
415 	return fStyleData->StrikeOut();
416 }
417 
418 
419 bool
420 CharacterStyle::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 
431 uint8
432 CharacterStyle::Underline() const
433 {
434 	return fStyleData->Underline();
435 }
436 
437 
438 // #pragma mark - private
439 
440 
441 BFont
442 CharacterStyle::_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