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 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 116 CharacterStyle::IsBold() const 117 { 118 return (Font().Face() & B_BOLD_FACE) != 0; 119 } 120 121 122 bool 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 146 CharacterStyle::IsItalic() const 147 { 148 return (Font().Face() & B_ITALIC_FACE) != 0; 149 } 150 151 152 bool 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 165 CharacterStyle::Ascent() const 166 { 167 return fStyleData->Ascent(); 168 } 169 170 171 bool 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 184 CharacterStyle::Descent() const 185 { 186 return fStyleData->Descent(); 187 } 188 189 190 bool 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 203 CharacterStyle::Width() const 204 { 205 return fStyleData->Width(); 206 } 207 208 209 bool 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 222 CharacterStyle::GlyphSpacing() const 223 { 224 return fStyleData->GlyphSpacing(); 225 } 226 227 228 bool 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 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 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 260 CharacterStyle::ForegroundColor() const 261 { 262 return fStyleData->ForegroundColor(); 263 } 264 265 266 color_which 267 CharacterStyle::WhichForegroundColor() const 268 { 269 return fStyleData->WhichForegroundColor(); 270 } 271 272 273 bool 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 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 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 305 CharacterStyle::BackgroundColor() const 306 { 307 return fStyleData->BackgroundColor(); 308 } 309 310 311 color_which 312 CharacterStyle::WhichBackgroundColor() const 313 { 314 return fStyleData->WhichBackgroundColor(); 315 } 316 317 318 bool 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 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 343 CharacterStyle::StrikeOutColor() const 344 { 345 return fStyleData->StrikeOutColor(); 346 } 347 348 349 color_which 350 CharacterStyle::WhichStrikeOutColor() const 351 { 352 return fStyleData->WhichStrikeOutColor(); 353 } 354 355 356 bool 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 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 381 CharacterStyle::UnderlineColor() const 382 { 383 return fStyleData->UnderlineColor(); 384 } 385 386 387 color_which 388 CharacterStyle::WhichUnderlineColor() const 389 { 390 return fStyleData->WhichUnderlineColor(); 391 } 392 393 394 bool 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 407 CharacterStyle::StrikeOut() const 408 { 409 return fStyleData->StrikeOut(); 410 } 411 412 413 bool 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 449 CharacterStyle::Underline() const 450 { 451 return fStyleData->Underline(); 452 } 453 454 455 // #pragma mark - private 456 457 458 BFont 459 CharacterStyle::_FindFontForFace(uint16 face) const 460 { 461 BFont font(Font()); 462 font.SetFamilyAndFace(NULL, face); 463 464 return font; 465 } 466 467