Back to Skiasharp

SkiaSharp & HarfBuzz Domain Knowledge

.agents/skills/api-docs/references/skia-patterns.md

4.148.03.6 KB
Original Source

SkiaSharp & HarfBuzz Domain Knowledge

Domain-specific facts for documenting SkiaSharp and HarfBuzzSharp APIs. Always verify claims against source code — this file provides key facts but is not exhaustive.

Verification Rule

Before documenting byte layouts, struct defaults, or API overloads:

  1. Read the source file in binding/ for the C# type
  2. For native types (color formats, packed values), check the C/C++ header
  3. Never guess a byte layout — either verify it or leave it out

Two Libraries, Different Conventions

SkiaSharp wraps Skia (C++) and HarfBuzz (C). They have different conventions. Never assume one works like the other because the C# types look similar.

Color Types

TypeFormatPacked LayoutVerified From
SKColor (Skia)ARGB0xAARRGGBBinclude/core/SkColor.h
hb_color_t (HarfBuzz)BGRA0xBBGGRRAAharfbuzz/src/hb-common.h

Proof for hb_color_t: HB_COLOR(b,g,r,a) calls HB_TAG(b,g,r,a) which expands to (b<<24)|(g<<16)|(r<<8)|a. So blue is bits 31-24 (high byte), alpha is bits 7-0 (low byte). The accessors confirm: hb_color_get_alpha(c) = c & 0xFF, hb_color_get_blue(c) = c >> 24.

  • SKColor has alpha in the high byte. Standard .NET Color.ToArgb() order.
  • hb_color_t has blue in the high byte, alpha in the low byte.
  • SKFontPaletteOverride.Color is sk_color_t = SKColor (ARGB).
  • Face.GetPaletteColors() returns hb_color_t values (BGRA).

Do NOT describe both as "RGBA" just because both are uint32.

Naming Conventions

Color Type Suffixes

SuffixMeaningExample
No suffix or a at endHas alphaRgba8888, Bgra8888
x at endPadding — NOT alphaRgb888x, RgbF16F16F16x

The x means the fourth component is unused padding for alignment. The type is opaque.

Channel Order

The letters in the name specify channel order in memory: Rgba = R first, A last. Bgra = B first, A last. Match the docs to the name.

Type Categories

When documenting SkiaSharp types, match the disposal and threading guidance to the type's category:

CategoryExamplesThreadingDisposal
Mutable native objectsSKCanvas, SKPaint, SKPathNOT thread-safeMust dispose
Immutable native objectsSKImage, SKShader, SKDataThread-safeMust dispose
Value typesSKColor, SKPoint, SKRectThread-safeNo disposal

In examples: mutable types need using, immutable types need using, value types do not.

Struct Defaults

C# structs zero-initialize. When documenting struct properties:

  • Check what 0 means for each field — it may not be a usable default
  • Do not assume a "typical" value is the default (e.g., 72 DPI is NOT the default for a zero-initialized struct)
  • If the library provides a constant like SKDocument.DefaultRasterDpi, document that separately from the struct's zero-initialized state

API Surface Verification

When writing code examples:

  • Verify the exact overload exists by reading the source file
  • Do not fabricate overloads that "should" exist (e.g., passing a struct to a method that only accepts scalar parameters)
  • If no suitable overload exists for an example, show direct property/field usage instead
  • SKColor to uint requires an explicit cast: (uint)SKColors.Red

String Handling

APIs that parse fixed-length strings often pad or truncate silently. Always read the method body to check actual behavior — don't assume "must be exactly N characters" if the source pads/truncates instead of throwing.