WhatsCanvas Tutorials¶
This tutorial series introduces the WhatsCanvas 2D rendering library step by step. Each chapter is self-contained; reading them in order is recommended.
For the Chinese version, see zh/README.md.
Table of Contents¶
| Ch. | Title | Level | File |
|---|---|---|---|
| 00 | Project Overview and Boundaries | Overview | 00-whatscanvas-intro.md |
| 01 | Environment Setup and First Frame | Beginner | 01-environment-setup.md |
| 02 | Basic Shape Drawing | Beginner | 02-basic-shapes.md |
| 03 | Paint in Depth | Elementary | 03-paint-bindepth.md |
| 04 | Path and Curves | Elementary | 04-path-bindcurves.md |
| 05 | State Stack and Transforms | Elementary | 05-state-bindtransforms.md |
| 06 | Image Drawing | Intermediate | 06-image-bindrawing.md |
| 07 | Text Layout | Intermediate | 07-text-bindlayout.md |
| 08 | Layer Filters and Effects | Intermediate | 08-layer-filters.md |
| 09 | Windowed Presentation and Interaction | Advanced | 09-windowed-presentation.md |
| 10 | Multiple Backends and Fallback | Advanced | 10-multi-backend.md |
| 11 | Performance Optimization | Advanced | 11-performance.md |
| 12 | Cross-Platform in Practice | Advanced | 12-cross-platform.md |
Prerequisites¶
- A C++17 compiler (MSVC 2019+, GCC 9+, Clang 10+)
- CMake 3.16+
- WhatsCanvas 1.2.1+ (Get and Build)
Conventions¶
- Code in the tutorials uses the Software backend by default unless a chapter states otherwise.
Canvas::create/setSizetake physical pixel dimensions. After you set a DPR, the drawing APIs operate in logical coordinates.Paint::setTextSizetakes a logical unit; it does not recognize Androidspautomatically.- Short snippets inside a chapter explain individual APIs. End-of-chapter integrated examples with rendered output live under
examples/tutorials/as compilable source files. - Rendered images are produced by the Software backend example programs and saved as PNG, so text and shape edges can be inspected.
- Integrated example code blocks are generated from the corresponding
.cppfiles; after editing sources, runpwsh examples/tutorials/sync_docs.ps1. wsc::is the WhatsCanvas namespace prefix.
Dimensions, DPR, and Text Units (must read)¶
WhatsCanvas does not decide layout units on the host's behalf. Canvas width and height are physical pixels; setDevicePixelRatio establishes the mapping from logical coordinates to physical pixels:
logical width = physical width / DPR
logical height = physical height / DPR
physical output size = logical size × DPR
For example, a 720 × 820 offscreen buffer at DPR 2 provides a 360 × 410 logical drawing area:
constexpr int physicalWidth = 720;
constexpr int physicalHeight = 820;
constexpr float dpr = 2.0f;
auto canvas = wsc::Canvas::create(
wsc::Canvas::Backend::Software, physicalWidth, physicalHeight);
canvas->setDevicePixelRatio(dpr);
const float logicalWidth = physicalWidth / dpr; // 360
const float logicalHeight = physicalHeight / dpr; // 410
canvas->drawRect(wsc::RectF(0, 0, logicalWidth, logicalHeight), paint);
Coordinates, corner radii, stroke widths, and setTextSize are all in logical units. Do not additionally call canvas->scale(dpr, dpr), or content will be scaled twice. getWidth() and getHeight() still return physical sizes; when computing layout, use logical dimensions you have derived and stored yourself.
On Android you typically pass DisplayMetrics.density as the DPR. That way a Canvas logical unit acts as 1 dp. Text must also respect the user's font setting: the host should first convert sp to physical pixels, then divide by density, and only then pass the value to setTextSize:
val metrics = resources.displayMetrics
val density = metrics.density
val bodyTextPx = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP,
16f,
metrics,
)
val bodyTextLogical = bodyTextPx / density
nativeResize(surfaceWidthPx, surfaceHeightPx, density)
nativeSetBodyTextSize(bodyTextLogical)
On Android 14 and later, non-linear font scaling may apply. Do not compute text size manually with 16 * fontScale or scaledDensity. Use TypedValue.applyDimension and recompute text sizes when font settings change. Chapter 5 further covers DPR and the state matrix; Chapter 7 covers font size and line height; Chapters 9 and 12 cover how to handle sizing in desktop and Web hosts respectively.
Running the Integrated Examples¶
cmake -S . -B build -DWHATSCANVAS_BUILD_OPENGL=OFF -DWHATSCANVAS_BUILD_SOFTWARE=ON
cmake --build build --config Release --target chapter02_cards
./build/Release/chapter02_cards # Windows
Other integrated examples run the same way; replace the last target with the corresponding source file name.
Before committing, you can check whether the tutorial code blocks are still in sync with the sources: