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, we usually privately alias that parent type to 374`INHERITED` within the class. That lets calls like `INHERITED::onFoo()` stand 375out visually. No need for `this->` when using `INHERITED::`. 376 377<!--?prettify?--> 378 379``` 380class GrDillPickle : public GrPickle { 381 ... 382 bool onTasty() const override { 383 return INHERITED::onTasty() 384 && fFreshDill; 385 } 386 ... 387private: 388 bool fFreshDill; 389 using INHERITED = GrPickle; 390}; 391``` 392 393Constructor initializers should be one per line, indented, with punctuation 394placed before the initializer. 395 396<!--?prettify?--> 397 398``` 399GrDillPickle::GrDillPickle() 400 : GrPickle() 401 , fSize(kDefaultPickleSize) { 402 ... 403} 404``` 405 406Constructors that take one argument should almost always be explicit, with 407exceptions made only for the (rare) automatic compatibility class. 408 409<!--?prettify?--> 410 411``` 412class Foo { 413 explicit Foo(int x); // Good. 414 Foo(float y); // Spooky implicit conversion from float to Foo. No no no! 415 ... 416}; 417``` 418 419Method calls within method calls should be prefixed with dereference of the 420'this' pointer. For example: 421 422<!--?prettify?--> 423 424``` 425this->method(); 426``` 427 428A common pattern for virtual methods in Skia is to include a public non-virtual 429(or final) method, paired with a private virtual method named "onMethodName". 430This ensures that the base-class method is always invoked and gives it control 431over how the virtual method is used, rather than relying on each subclass to 432call `INHERITED::onMethodName`. For example: 433 434<!--?prettify?--> 435 436``` 437class SkSandwich { 438public: 439 void assemble() { 440 // All sandwiches must have bread on the top and bottom. 441 this->addIngredient(kBread_Ingredient); 442 this->onAssemble(); 443 this->addIngredient(kBread_Ingredient); 444 } 445 bool cook() { 446 return this->onCook(); 447 } 448 449private: 450 // All sandwiches must implement onAssemble. 451 virtual void onAssemble() = 0; 452 // Sandwiches can remain uncooked by default. 453 virtual bool onCook() { return true; } 454}; 455 456class SkGrilledCheese : public SkSandwich { 457private: 458 void onAssemble() override { 459 this->addIngredient(kCheese_Ingredient); 460 } 461 bool onCook() override { 462 return this->toastOnGriddle(); 463 } 464}; 465 466class SkPeanutButterAndJelly : public SkSandwich { 467private: 468 void onAssemble() override { 469 this->addIngredient(kPeanutButter_Ingredient); 470 this->addIngredient(kGrapeJelly_Ingredient); 471 } 472}; 473``` 474 475## Integer Types 476 477We follow the Google C++ guide for ints and are slowly making older code conform 478to this 479 480(https://google.github.io/styleguide/cppguide.html#Integer_Types) 481 482Summary: Use `int` unless you have need a guarantee on the bit count, then use 483`stdint.h` types (`int32_t`, etc). Assert that counts, etc are not negative 484instead of using unsigned. Bitfields use `uint32_t` unless they have to be made 485shorter for packing or performance reasons. 486 487## Function Parameters 488 489Mandatory constant object parameters are passed to functions as const 490references. Optional constant object parameters are passed to functions as const 491pointers. Mutable object parameters are passed to functions as pointers. We very 492rarely pass anything by non-const reference. 493 494<!--?prettify?--> 495 496``` 497// src and paint are optional 498void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 499 const SkRect& dst, const SkPaint* paint = nullptr); 500 501// metrics is mutable (it is changed by the method) 502SkScalar SkPaint::getFontMetrics(FontMetric* metrics, SkScalar scale) const; 503 504``` 505 506If function arguments or parameters do not all fit on one line, the overflowing 507parameters may be lined up with the first parameter on the next line 508 509<!--?prettify?--> 510 511``` 512void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, 513 const SkPaint* paint = nullptr) { 514 this->drawBitmapRectToRect(bitmap, nullptr, dst, paint, 515 kNone_DrawBitmapRectFlag); 516} 517``` 518 519or all parameters placed on the next line and indented eight spaces 520 521<!--?prettify?--> 522 523``` 524void drawBitmapRect( 525 const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint = nullptr) { 526 this->drawBitmapRectToRect( 527 bitmap, nullptr, dst, paint, kNone_DrawBitmapRectFlag); 528} 529``` 530 531## Python 532 533Python code follows the 534[Google Python Style Guide](https://google.github.io/styleguide/pyguide.html). 535