xref: /haiku/src/apps/haikudepot/textview/CharacterStyle.cpp (revision 9cd2a23203746b3c62ac86f7c8486abd81ef09ad)
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