1--- 2title: 'Coding Style Guidelines' 3linkTitle: 'Coding Style Guidelines' 4--- 5 6These conventions have evolved over time. Some of the earlier code in both 7projects doesn't strictly adhere to the guidelines. However, as the code evolves 8we hope to make the existing code conform to the guildelines. 9 10## Files 11 12We use .cpp and .h as extensions for c++ source and header files. 13 14Headers that aren't meant for public consumption should be placed in src 15directories so that they aren't in a client's search path, or in include/private 16if they need to be used by public headers. 17 18We prefer to minimize includes. If forward declaring a name in a header is 19sufficient then that is preferred to an include. 20 21Forward declarations and file includes should be in alphabetical order. 22 23### No define before sktypes 24 25Do not use #if/#ifdef before including "SkTypes.h" (directly or indirectly). 26Most things you'd #if on tend to not yet be decided until SkTypes.h. 27 28We use 4 spaces, not tabs. 29 30We use Unix style endlines (LF). 31 32We prefer no trailing whitespace but aren't very strict about it. 33 34We wrap lines at 100 columns unless it is excessively ugly (use your judgement). 35 36## Naming 37 38Most externally visible types and functions use an Sk- prefix to designate 39they're part of Skia, but code in Ganesh uses Gr-. Nested types need not be 40prefixed. 41 42<!--?prettify?--> 43 44``` 45class SkClass { 46public: 47 class HelperClass { 48 ... 49 }; 50}; 51``` 52 53Data fields in structs, classes, and unions that have methods begin with 54lower-case f and are then camel-capped, to distinguish those fields from other 55variables. Types that are predominantly meant for direct field access don't need 56f-decoration. 57 58<!--?prettify?--> 59 60``` 61struct GrCar { 62 float milesDriven; 63 Color color; 64}; 65 66class GrMotorcyle { 67public: 68 float getMilesDriven() const { return fMilesDriven; } 69 void setMilesDriven(float milesDriven) { fMilesDriven = milesDriven; } 70 71 Color getColor() const { return fColor; } 72private: 73 float fMilesDriven; 74 Color fColor; 75}; 76``` 77 78Global variables are similar but prefixed with g and camel-capped. 79 80<!--?prettify?--> 81 82``` 83bool gLoggingEnabled; 84``` 85 86Local variables and arguments are camel-capped with no initial cap. 87 88<!--?prettify?--> 89 90``` 91int herdCats(const Array& cats) { 92 int numCats = cats.count(); 93} 94``` 95 96Variables declared `constexpr` or `const`, and whose value is fixed for the 97duration of the program, are named with a leading "k" and then camel-capped. 98 99<!--?prettify?--> 100 101``` 102int drawPicture() { 103 constexpr SkISize kPictureSize = {100, 100}; 104 constexpr float kZoom = 1.0f; 105} 106``` 107 108Enum values are also prefixed with k. Unscoped enum values are postfixed with an 109underscore and singular name of the enum name. The enum itself should be 110singular for exclusive values or plural for a bitfield. If a count is needed it 111is `k<singular enum name>Count` and not be a member of the enum (see example), 112or a kLast member of the enum is fine too. 113 114<!--?prettify?--> 115 116``` 117// Enum class does not need suffixes. 118enum class SkPancakeType { 119 kBlueberry, 120 kPlain, 121 kChocolateChip, 122}; 123``` 124 125<!--?prettify?--> 126 127``` 128// Enum should have a suffix after the enum name. 129enum SkDonutType { 130 kGlazed_DonutType, 131 kSprinkles_DonutType, 132 kChocolate_DonutType, 133 kMaple_DonutType, 134 135 kLast_DonutType = kMaple_DonutType 136}; 137 138static const SkDonutType kDonutTypeCount = kLast_DonutType + 1; 139``` 140 141<!--?prettify?--> 142 143``` 144enum SkSausageIngredientBits { 145 kFennel_SausageIngredientBit = 0x1, 146 kBeef_SausageIngredientBit = 0x2 147}; 148``` 149 150<!--?prettify?--> 151 152``` 153enum SkMatrixFlags { 154 kTranslate_MatrixFlag = 0x1, 155 kRotate_MatrixFlag = 0x2 156}; 157``` 158 159Macros are all caps with underscores between words. Macros that have greater 160than file scope should be prefixed SK or GR. 161 162Static non-class functions in implementation files are lower-case with 163underscores separating words: 164 165<!--?prettify?--> 166 167``` 168static inline bool tastes_like_chicken(Food food) { 169 return kIceCream_Food != food; 170} 171``` 172 173Externed functions or static class functions are camel-capped with an initial 174cap: 175 176<!--?prettify?--> 177 178``` 179bool SkIsOdd(int n); 180 181class SkFoo { 182public: 183 static int FooInstanceCount(); 184 185 // Not static. 186 int barBaz(); 187}; 188``` 189 190## Macros 191 192Ganesh macros that are GL-specific should be prefixed GR_GL. 193 194<!--?prettify?--> 195 196``` 197#define GR_GL_TEXTURE0 0xdeadbeef 198``` 199 200Ganesh prefers that macros are always defined and the use of `#if MACRO` rather 201than `#ifdef MACRO`. 202 203<!--?prettify?--> 204 205``` 206#define GR_GO_SLOWER 0 207... 208#if GR_GO_SLOWER 209 Sleep(1000); 210#endif 211``` 212 213The rest of Skia tends to use `#ifdef SK_MACRO` for boolean flags. 214 215## Braces 216 217Open braces don't get a newline. `else` and `else if` appear on same line as 218opening and closing braces unless preprocessor conditional compilation 219interferes. Braces are always used with `if`, `else`, `while`, `for`, and `do`. 220 221<!--?prettify?--> 222 223``` 224if (...) { 225 oneOrManyLines; 226} 227 228if (...) { 229 oneOrManyLines; 230} else if (...) { 231 oneOrManyLines; 232} else { 233 oneOrManyLines; 234} 235 236for (...) { 237 oneOrManyLines; 238} 239 240while (...) { 241 oneOrManyLines; 242} 243 244void function(...) { 245 oneOrManyLines; 246} 247 248if (!error) { 249 proceed_as_usual(); 250} 251#if HANDLE_ERROR 252else { 253 freak_out(); 254} 255#endif 256``` 257 258## Flow Control 259 260There is a space between flow control words and parentheses, and between 261parentheses and braces: 262 263<!--?prettify?--> 264 265``` 266while (...) { 267} 268 269do { 270} while (...); 271 272switch (...) { 273... 274} 275``` 276 277Cases and default in switch statements are indented from the switch. 278 279<!--?prettify?--> 280 281``` 282switch (color) { 283 case kBlue: 284 ... 285 break; 286 case kGreen: 287 ... 288 break; 289 ... 290 default: 291 ... 292 break; 293} 294``` 295 296Fallthrough from one case to the next is annotated with `[[fallthrough]]`. 297However, when multiple case statements in a row are used, they do not need the 298`[[fallthrough]]` annotation. 299 300<!--?prettify?--> 301 302``` 303switch (recipe) { 304 ... 305 case kSmallCheesePizza_Recipe: 306 case kLargeCheesePizza_Recipe: 307 ingredients |= kCheese_Ingredient | kDough_Ingredient | kSauce_Ingredient; 308 break; 309 case kCheeseOmelette_Recipe: 310 ingredients |= kCheese_Ingredient; 311 [[fallthrough]] 312 case kPlainOmelette_Recipe: 313 ingredients |= (kEgg_Ingredient | kMilk_Ingredient); 314 break; 315 ... 316} 317``` 318 319When a block is needed to declare variables within a case follow this pattern: 320 321<!--?prettify?--> 322 323``` 324switch (filter) { 325 ... 326 case kGaussian_Filter: { 327 Bitmap srcCopy = src->makeCopy(); 328 ... 329 } break; 330 ... 331}; 332``` 333 334## Classes 335 336Unless there is a need for forward declaring something, class declarations 337should be ordered `public`, `protected`, `private`. Each should be preceded by a 338newline. Within each visibility section (`public`, `private`), fields should not 339be intermixed with methods. It's nice to keep all data fields together at the 340end. 341 342<!--?prettify?--> 343 344``` 345class SkFoo { 346 347public: 348 ... 349 350protected: 351 ... 352 353private: 354 void barHelper(...); 355 ... 356 357 SkBar fBar; 358 ... 359}; 360``` 361 362Virtual functions that are overridden in derived classes should use override, 363and the virtual keyword should be omitted. 364 365<!--?prettify?--> 366 367``` 368void myVirtual() override { 369} 370``` 371 372If you call a method on a parent type that must stand out as specifically the 373parent's version of that method, such as `Parent::method()`. The `this->` that 374would normally be required before a method call on the current object is not 375necessary when using a scope qualifier. 376 377<!--?prettify?--> 378 379``` 380class GrDillPickle : public GrPickle { 381 ... 382 bool onTasty() const override { 383 return GrPickle::onTasty() 384 && fFreshDill; 385 } 386 ... 387private: 388 bool fFreshDill; 389}; 390``` 391 392Constructor initializers should be placed on the same line as the constructor, 393if they fit. Otherwise, each initializer should be on its own line, indented, 394with punctuation placed before the initializer. 395 396<!--?prettify?--> 397 398``` 399GrDillPickle::GrDillPickle() : GrPickle(), fSize(kDefaultPickleSize) {} 400 401GrDillPickle::GrDillPickle(float size, float crunchiness, const PickleOptions* options) 402 : GrPickle(options) 403 , fSize(size) 404 , fCrunchiness(crunchiness) {} 405``` 406 407Constructors that take one argument should almost always be explicit, with 408exceptions made only for the (rare) automatic compatibility class. 409 410<!--?prettify?--> 411 412``` 413class Foo { 414 explicit Foo(int x); // Good. 415 Foo(float y); // Spooky implicit conversion from float to Foo. No no no! 416 ... 417}; 418``` 419 420Method calls within method calls should be prefixed with dereference of the 421'this' pointer. For example: 422 423<!--?prettify?--> 424 425``` 426this->method(); 427``` 428 429A common pattern for virtual methods in Skia is to include a public non-virtual 430(or final) method, paired with a private virtual method named "onMethodName". 431This ensures that the base-class method is always invoked and gives it control 432over how the virtual method is used, rather than relying on each subclass to 433call `Parent::onMethodName()`. For example: 434 435<!--?prettify?--> 436 437``` 438class SkSandwich { 439public: 440 void assemble() { 441 // All sandwiches must have bread on the top and bottom. 442 this->addIngredient(kBread_Ingredient); 443 this->onAssemble(); 444 this->addIngredient(kBread_Ingredient); 445 } 446 bool cook() { 447 return this->onCook(); 448 } 449 450private: 451 // All sandwiches must implement onAssemble. 452 virtual void onAssemble() = 0; 453 // Sandwiches can remain uncooked by default. 454 virtual bool onCook() { return true; } 455}; 456 457class SkGrilledCheese : public SkSandwich { 458private: 459 void onAssemble() override { 460 this->addIngredient(kCheese_Ingredient); 461 } 462 bool onCook() override { 463 return this->toastOnGriddle(); 464 } 465}; 466 467class SkPeanutButterAndJelly : public SkSandwich { 468private: 469 void onAssemble() override { 470 this->addIngredient(kPeanutButter_Ingredient); 471 this->addIngredient(kGrapeJelly_Ingredient); 472 } 473}; 474``` 475 476## Integer Types 477 478We follow the Google C++ guide for ints and are slowly making older code conform 479to this 480 481(https://google.github.io/styleguide/cppguide.html#Integer_Types) 482 483Summary: Use `int` unless you have need a guarantee on the bit count, then use 484`stdint.h` types (`int32_t`, etc). Assert that counts, etc are not negative 485instead of using unsigned. Bitfields use `uint32_t` unless they have to be made 486shorter for packing or performance reasons. 487 488## Function Parameters 489 490Mandatory constant object parameters are passed to functions as const 491references. Optional constant object parameters are passed to functions as const 492pointers. Mutable object parameters are passed to functions as pointers. We very 493rarely pass anything by non-const reference. 494 495<!--?prettify?--> 496 497``` 498// src and paint are optional 499void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 500 const SkRect& dst, const SkPaint* paint = nullptr); 501 502// metrics is mutable (it is changed by the method) 503SkScalar SkPaint::getFontMetrics(FontMetric* metrics, SkScalar scale) const; 504 505``` 506 507If function arguments or parameters do not all fit on one line, the overflowing 508parameters may be lined up with the first parameter on the next line 509 510<!--?prettify?--> 511 512``` 513void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, 514 const SkPaint* paint = nullptr) { 515 this->drawBitmapRectToRect(bitmap, nullptr, dst, paint, 516 kNone_DrawBitmapRectFlag); 517} 518``` 519 520or all parameters placed on the next line and indented eight spaces 521 522<!--?prettify?--> 523 524``` 525void drawBitmapRect( 526 const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint = nullptr) { 527 this->drawBitmapRectToRect( 528 bitmap, nullptr, dst, paint, kNone_DrawBitmapRectFlag); 529} 530``` 531 532## Python 533 534Python code follows the 535[Google Python Style Guide](https://google.github.io/styleguide/pyguide.html). 536 537## Folder Organiziation 538 539Skia's public API should live in the `include` directory. Skia's private headers and implementation 540files should live in the `src` directory. The `modules` directory contains extra features that are 541built on top of Skia (`modules/skcms` being an exception) and can be used by clients. 542Private utilities to test Skia live in `tools` and can be used for reference but should not be used 543by clients. 544 545No header in `include` should depend on files in other directories (`modules/skcms` being an exception). 546This is to prevent private symbols from leaking into client code via transitive dependencies. 547