#Topic Illustrations

#Subtopic Image_Info_Color_Type_RGB_565
#Example
#Width 415
#Height 250
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "16-bit word", 5 + 20 * 8, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 85, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(low bits)", 5 + 20 * 1.5f, 137, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(high bits)", 5 + 20 * 6.5f, 187, font, paint, SkTextUtils::kCenter_Align);
    auto drawBoxText = [=](SkScalar e[], const char* s[], int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int width = n % 32 + 1;
        int lastN = n > 32 ? 32 : 0;
        for (; n >= lastN; --n) {
            for (int i = 0; i <= count; ++i) {
                int a = width - e[i];
                if (a == n || a == n + 1 || a == n - 32 || a == n - 31) {
                    char num[3] = {(char) ('0' + n / 10), (char) ('0' + n % 10), '\0'};
                    SkTextUtils::DrawString(canvas, n >= 10 ? num : &num[1], xPos, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                    break;
                }
            }
            xPos += 20;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 10, yPos + 10, font, p, SkTextUtils::kCenter_Align);
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 20, yPos, 5 + e[i] * 20, yPos + 15, p);
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 20, yPos + i * 15, 5 + e[count] * 20, yPos + i * 15, p);
        }
    };
    SkScalar edges[] = { 0, 5, 11, 16,
                         0, 3, 8,
                         0, 5, 8 };
    const char* labels[] = { "red", "green", "blue" };
    drawBoxText(&edges[0], &labels[0], 3, 15, 45);
    drawBoxText(&edges[4], &labels[1], 2, 7, 110);
    drawBoxText(&edges[7], &labels[0], 2, 7, 160);
}
##
##

#Subtopic Image_Info_Color_Type_ARGB_4444
#Example
#Width 415
#Height 250
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "16-bit word", 5 + 20 * 8, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 85, font, paint, SkTextUtils::kCenter_Align);
    auto drawBoxText = [=](SkScalar e[], const char* s[], int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int width = n % 32 + 1;
        int lastN = n > 32 ? 32 : 0;
        for (; n >= lastN; --n) {
            for (int i = 0; i <= count; ++i) {
                int a = width - e[i];
                if (a == n || a == n + 1 || a == n - 32 || a == n - 31) {
                    char num[3] = {(char) ('0' + n / 10), (char) ('0' + n % 10), '\0'};
                    SkTextUtils::DrawString(canvas, n >= 10 ? num : &num[1], xPos, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                    break;
                }
            }
            xPos += 20;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 10, yPos + 10, font, p, SkTextUtils::kCenter_Align);
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 20, yPos, 5 + e[i] * 20, yPos + 15, p);
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 20, yPos + i * 15, 5 + e[count] * 20, yPos + i * 15, p);
        }
    };
    SkScalar edges[] = { 0, 4, 8, 12, 16 };
    const char* labels[] = { "red", "green", "blue", "alpha" };
    drawBoxText(&edges[0], &labels[0], 4, 15, 45);
    drawBoxText(&edges[0], &labels[2], 2, 7, 110);
    drawBoxText(&edges[0], &labels[0], 2, 7, 160);
}
##
##

#Subtopic Image_Info_Color_Type_RGBA_8888
#Example
#Width 812
#Height 365
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "32-bit word", 5 + 20 * 16, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 85, font, paint, SkTextUtils::kCenter_Align);
    auto drawBoxText = [=](SkScalar e[], const char* s[], int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int width = n % 32 + 1;
        int lastN = n > 32 ? 32 : 0;
        for (; n >= lastN; --n) {
            for (int i = 0; i <= count; ++i) {
                int a = width - e[i];
                if (a == n || a == n + 1 || a == n - 32 || a == n - 31) {
                    char num[3] = {(char) ('0' + n / 10), (char) ('0' + n % 10), '\0'};
                    SkTextUtils::DrawString(canvas, n >= 10 ? num : &num[1], xPos, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                    break;
                }
            }
            xPos += 20;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 10, yPos + 10, font, p, SkTextUtils::kCenter_Align);
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 20, yPos, 5 + e[i] * 20, yPos + 15, p);
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 20, yPos + i * 15, 5 + e[count] * 20, yPos + i * 15, p);
        }
    };
    SkScalar edges[] = { 0, 8, 16, 24, 32 };
    const char* labels[] = { "alpha", "blue", "green", "red" };
    drawBoxText(edges, &labels[0], 4, 31, 45);
    drawBoxText(edges, &labels[3], 1, 7, 110);
    drawBoxText(edges, &labels[2], 1, 7, 160);
    drawBoxText(edges, &labels[1], 1, 7, 210);
    drawBoxText(edges, &labels[0], 1, 7, 260);
}
##
##

#Subtopic Image_Info_Color_Type_RGB_888
#Example
#Width 812
#Height 365
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "32-bit word", 5 + 20 * 16, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 85, font, paint, SkTextUtils::kCenter_Align);
    auto drawBoxText = [=](SkScalar e[], const char* s[], int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int width = n % 32 + 1;
        int lastN = n > 32 ? 32 : 0;
        for (; n >= lastN; --n) {
            for (int i = 0; i <= count; ++i) {
                int a = width - e[i];
                if (a == n || a == n + 1 || a == n - 32 || a == n - 31) {
                    char num[3] = {(char) ('0' + n / 10), (char) ('0' + n % 10), '\0'};
                    SkTextUtils::DrawString(canvas, n >= 10 ? num : &num[1], xPos, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                    break;
                }
            }
            xPos += 20;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 10, yPos + 10, font, p, SkTextUtils::kCenter_Align);
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 20, yPos, 5 + e[i] * 20, yPos + 15, p);
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 20, yPos + i * 15, 5 + e[count] * 20, yPos + i * 15, p);
        }
    };
    SkScalar edges[] = { 0, 8, 16, 24, 32 };
    const char* labels[] = { "(unused)", "blue", "green", "red" };
    drawBoxText(edges, &labels[0], 4, 31, 45);
    drawBoxText(edges, &labels[3], 1, 7, 110);
    drawBoxText(edges, &labels[2], 1, 7, 160);
    drawBoxText(edges, &labels[1], 1, 7, 210);
    drawBoxText(edges, &labels[0], 1, 7, 260);
}
##
##

#Subtopic Image_Info_Color_Type_BGRA_8888
#Example
#Width 812
#Height 365
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "32-bit word", 5 + 20 * 16, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 85, font, paint, SkTextUtils::kCenter_Align);
    auto drawBoxText = [=](SkScalar e[], const char* s[], int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int width = n % 32 + 1;
        int lastN = n > 32 ? 32 : 0;
        for (; n >= lastN; --n) {
            for (int i = 0; i <= count; ++i) {
                int a = width - e[i];
                if (a == n || a == n + 1 || a == n - 32 || a == n - 31) {
                    char num[3] = {(char) ('0' + n / 10), (char) ('0' + n % 10), '\0'};
                    SkTextUtils::DrawString(canvas, n >= 10 ? num : &num[1], xPos, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                    break;
                }
            }
            xPos += 20;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 10, yPos + 10, font, p, SkTextUtils::kCenter_Align);
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 20, yPos, 5 + e[i] * 20, yPos + 15, p);
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 20, yPos + i * 15, 5 + e[count] * 20, yPos + i * 15, p);
        }
    };
    SkScalar edges[] = { 0, 8, 16, 24, 32 };
    const char* labels[] = { "alpha", "red", "green", "blue" };
    drawBoxText(edges, &labels[0], 4, 31, 45);
    drawBoxText(edges, &labels[3], 1, 7, 110);
    drawBoxText(edges, &labels[2], 1, 7, 160);
    drawBoxText(edges, &labels[1], 1, 7, 210);
    drawBoxText(edges, &labels[0], 1, 7, 260);
}
##
##

#Subtopic Image_Info_Color_Type_RGBA_1010102
#Example
#Width 812
#Height 380
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "32-bit word", 5 + 20 * 16, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 85, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(low bits)", 5 + 20 * 4, 137, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(low bits)", 5 + 20 * 3, 187, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(high bits)", 5 + 20 * 7, 187, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(low bits)", 5 + 20 * 2, 237, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(high bits)", 5 + 20 * 6, 237, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(high bits)", 5 + 20 * 5, 287, font, paint, SkTextUtils::kCenter_Align);
    auto drawBoxText = [=](SkScalar e[], const char* s[], int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int width = n % 32 + 1;
        int lastN = n > 32 ? 32 : 0;
        for (; n >= lastN; --n) {
            for (int i = 0; i <= count; ++i) {
                int a = width - e[i];
                if (a == n || a == n + 1 || a == n - 32 || a == n - 31) {
                    char num[3] = {(char) ('0' + n / 10), (char) ('0' + n % 10), '\0'};
                    SkTextUtils::DrawString(canvas, n >= 10 ? num : &num[1], xPos, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                    break;
                }
            }
            xPos += 20;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 10, yPos + 10, font, p, SkTextUtils::kCenter_Align);
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 20, yPos, 5 + e[i] * 20, yPos + 15, p);
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 20, yPos + i * 15, 5 + e[count] * 20, yPos + i * 15, p);
        }
    };
    SkScalar edges[] = { 0, 2, 12, 22, 32,
                         0, 8,
                         0, 6, 8,
                         0, 4, 8,
                         0, 2, 8
                        };
    const char* labels[] = { "alpha", "blue", "green", "red" };
    drawBoxText(&edges[0], &labels[0], 4, 31, 45);
    drawBoxText(&edges[5], &labels[3], 1, 7, 110);
    drawBoxText(&edges[7], &labels[2], 2, 7, 160);
    drawBoxText(&edges[10], &labels[1], 2, 7, 210);
    drawBoxText(&edges[13], &labels[0], 2, 7, 260);
}
##
##

#Subtopic Image_Info_Color_Type_RGB_101010
#Example
#Width 812
#Height 380
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "32-bit word", 5 + 20 * 16, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 85, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(low bits)", 5 + 20 * 4, 137, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(low bits)", 5 + 20 * 3, 187, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(high bits)", 5 + 20 * 7, 187, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(low bits)", 5 + 20 * 2, 237, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(high bits)", 5 + 20 * 6, 237, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "(high bits)", 5 + 20 * 5, 287, font, paint, SkTextUtils::kCenter_Align);
    auto drawBoxText = [=](SkScalar e[], const char* s[], int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int width = n % 32 + 1;
        int lastN = n > 32 ? 32 : 0;
        for (; n >= lastN; --n) {
            for (int i = 0; i <= count; ++i) {
                int a = width - e[i];
                if (a == n || a == n + 1 || a == n - 32 || a == n - 31) {
                    char num[3] = {(char) ('0' + n / 10), (char) ('0' + n % 10), '\0'};
                    SkTextUtils::DrawString(canvas, n >= 10 ? num : &num[1], xPos, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                    break;
                }
            }
            xPos += 20;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 10, yPos + 10, font, p, SkTextUtils::kCenter_Align);
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 20, yPos, 5 + e[i] * 20, yPos + 15, p);
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 20, yPos + i * 15, 5 + e[count] * 20, yPos + i * 15, p);
        }
    };
    SkScalar edges[] = { 0, 2, 12, 22, 32,
                         0, 8,
                         0, 6, 8,
                         0, 4, 8,
                         0, 2, 8
                        };
    const char* labels[] = { "unused", "blue", "green", "red" };
    drawBoxText(&edges[0], &labels[0], 4, 31, 45);
    drawBoxText(&edges[5], &labels[3], 1, 7, 110);
    drawBoxText(&edges[7], &labels[2], 2, 7, 160);
    drawBoxText(&edges[10], &labels[1], 2, 7, 210);
    drawBoxText(&edges[13], &labels[0], 2, 7, 260);
}
##
##

#Subtopic Image_Info_Color_Type_RGBA_F16
#Example
#Width 812
#Height 685
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "64-bit word", 5 + 20 * 16, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 135, font, paint, SkTextUtils::kCenter_Align);
    for (int i = 0; i < 4; ++i) {
        SkTextUtils::DrawString(canvas, "(low bits)", 5 + 20 * 4, 187 + i * 100, font, paint, SkTextUtils::kCenter_Align);
        SkTextUtils::DrawString(canvas, "(high bits)", 5 + 20 * 4, 237 + i * 100, font, paint, SkTextUtils::kCenter_Align);
    }
    auto drawBoxText = [=](SkScalar e[], const char* s[], int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int width = n % 32 + 1;
        int lastN = n > 32 ? 32 : 0;
        for (; n >= lastN; --n) {
            for (int i = 0; i <= count; ++i) {
                int a = width - e[i];
                if (a == n || a == n + 1 || a == n - 32 || a == n - 31) {
                    char num[3] = {(char) ('0' + n / 10), (char) ('0' + n % 10), '\0'};
                    SkTextUtils::DrawString(canvas, n >= 10 ? num : &num[1], xPos, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                    break;
                }
            }
            xPos += 20;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 10, yPos + 10, font, p, SkTextUtils::kCenter_Align);
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 20, yPos, 5 + e[i] * 20, yPos + 15, p);
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 20, yPos + i * 15, 5 + e[count] * 20, yPos + i * 15, p);
        }
    };
    SkScalar edges[] = { 0, 16, 32,
                         0, 8
                       };
    const char* labels[] = { "alpha", "blue", "green", "red" };
    drawBoxText(&edges[0], &labels[0], 2, 63, 45);
    drawBoxText(&edges[0], &labels[2], 2, 31, 95);
    drawBoxText(&edges[3], &labels[3], 1, 7, 160);
    drawBoxText(&edges[3], &labels[3], 1, 7, 210);
    drawBoxText(&edges[3], &labels[2], 1, 7, 260);
    drawBoxText(&edges[3], &labels[2], 1, 7, 310);
    drawBoxText(&edges[3], &labels[1], 1, 7, 360);
    drawBoxText(&edges[3], &labels[1], 1, 7, 410);
    drawBoxText(&edges[3], &labels[0], 1, 7, 460);
    drawBoxText(&edges[3], &labels[0], 1, 7, 510);
}
##
##

#Subtopic Image_Info_Color_Type_RGBA_F32
#Example
#Width 812
#Height 685
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    canvas->scale(1.25f, 1.25f);
    SkPaint paint;
    paint.setAntiAlias(true);
    SkFont font(nullptr, 10);
    SkTextUtils::DrawString(canvas, "128-bit word", 5 + 20 * 16, 20, font, paint, SkTextUtils::kCenter_Align);
    SkTextUtils::DrawString(canvas, "little endian byte order", 5 + 20 * 4, 135, font, paint, SkTextUtils::kCenter_Align);
    for (int i = 0; i < 4; ++i) {
        SkTextUtils::DrawString(canvas, "(low bits)", 5 + 10 * 4, 187 + i * 100, font, paint, SkTextUtils::kCenter_Align);
        SkTextUtils::DrawString(canvas, "(high bits)", 105 + 10 * 4, 237 + i * 100, font, paint, SkTextUtils::kCenter_Align);
    }
    auto drawBoxText = [=](SkScalar e[], const char* s[], const char* nums[] , 
             int count, int n, SkScalar yPos) -> void {
        SkPaint p(paint);
        p.setColor(SK_ColorRED);
        SkScalar xPos = 15;
        int stringIndex = 0;
        for (int i = n; i >= 0; --i) {
            if (0 == i || n == i || 32 == i || 31 == i) {
                int x = xPos;
                if (2 == count) {
                    x += stringIndex * 12 + (stringIndex ? 8 : 0);
                }
                SkTextUtils::DrawString(canvas, nums[stringIndex], x, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                if (1 == count) {
                    SkTextUtils::DrawString(canvas, nums[stringIndex], xPos + 100, yPos - 5, font, p, SkTextUtils::kCenter_Align);
                }
                ++stringIndex;
            }
            xPos += 9;
        }
        p.setColor(SK_ColorBLACK);
        for (int i = 0; i < count; ++i) {
            SkTextUtils::DrawString(canvas, s[i], 5 + (e[i] + e[i + 1]) * 5, yPos + 10, font, p, SkTextUtils::kCenter_Align);
            if (1 == count) {
                SkTextUtils::DrawString(canvas, s[i], 105 + (e[i] + e[i + 1]) * 5, yPos + 10, font, p, SkTextUtils::kCenter_Align);
            }
        }
        p.setStyle(SkPaint::kStroke_Style);
        for (int i = 0; i <= count; ++i) {
            canvas->drawLine(5 + e[i] * 10, yPos, 5 + e[i] * 10, yPos + 15, p);
            if (1 == count) {
                canvas->drawLine(105 + e[i] * 10, yPos, 105 + e[i] * 10, yPos + 15, p);
            }
        }
        for (int i = 0; i < 2; ++i) {
            canvas->drawLine(5 + e[0] * 10, yPos + i * 15,
                             5 + e[count] * 10, yPos + i * 15, p);
            if (1 == count) {
                canvas->drawLine(105 + e[0] * 10, yPos + i * 15,
                                 105 + e[count] * 10, yPos + i * 15, p);
            }
        }
    };
    SkScalar edges[] = { 0, 32, 64,
                         0, 8
                       };
    const char* labels[] = { "alpha", "blue", "green", "red" };
    const char* nums128[] = { "127", "96", "95", "64"};
    const char* nums64[] = { "63", "32", "31", "0"};
    const char* nums8[] = { "7", "0"};
    drawBoxText(&edges[0], &labels[0], nums128, 2, 63, 45);
    drawBoxText(&edges[0], &labels[2], nums64, 2, 63, 95);
    drawBoxText(&edges[3], &labels[3], nums8, 1, 7, 160);
    drawBoxText(&edges[3], &labels[3], nums8, 1, 7, 210);
    drawBoxText(&edges[3], &labels[2], nums8, 1, 7, 260);
    drawBoxText(&edges[3], &labels[2], nums8, 1, 7, 310);
    drawBoxText(&edges[3], &labels[1], nums8, 1, 7, 360);
    drawBoxText(&edges[3], &labels[1], nums8, 1, 7, 410);
    drawBoxText(&edges[3], &labels[0], nums8, 1, 7, 460);
    drawBoxText(&edges[3], &labels[0], nums8, 1, 7, 510);
}
##
##

#Subtopic Blend_Mode_Overview_Porter_Duff
#Example
#Width 480
#Height 330
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    SkPaint srcPaint;
    srcPaint.setAntiAlias(true);
    SkPaint labelPaint = srcPaint;
    SkFont labelFont(nullptr, 16);
    SkPaint dstPaint = srcPaint;
    dstPaint.setColor(0xFF606080);
    SkFont dstFont(SkTypeface::MakeFromName("Roboto", SkFontStyle::Bold()), 80);

    SkBitmap srcBits;
    srcBits.allocN32Pixels(80, 84);
    SkCanvas srcCanvas(srcBits);
    srcPaint.setColor(0xFFcc6633);
    SkPath srcPath;
    const SkPoint points[] = {{20, 20}, {80, 45}, {45, 80}};
    srcPath.addPoly(points, SK_ARRAY_COUNT(points), true);
    srcBits.eraseColor(0);
    srcCanvas.drawPath(srcPath, srcPaint);

    canvas->drawColor(0, SkBlendMode::kClear);
    for (auto blend : { SkBlendMode::kSrc, SkBlendMode::kSrcATop, SkBlendMode::kSrcOver,
                        SkBlendMode::kSrcIn, SkBlendMode::kSrcOut,
                        SkBlendMode::kDst, SkBlendMode::kDstATop, SkBlendMode::kDstOver,
                        SkBlendMode::kDstIn, SkBlendMode::kDstOut,
                        SkBlendMode::kClear, SkBlendMode::kXor } ) {
        SkTextUtils::DrawString(canvas, "&", 50, 80, dstFont, dstPaint, SkTextUtils::kCenter_Align);
        srcPaint.setBlendMode(blend);
        canvas->drawBitmap(srcBits, 0, 0, &srcPaint);
        SkTextUtils::DrawString(canvas, SkBlendMode_Name(blend), 50, 100, labelFont, labelPaint, SkTextUtils::kCenter_Align);
        canvas->translate(80, 0);
        if (SkBlendMode::kSrcOut == blend || SkBlendMode::kDstOut == blend) {
            canvas->translate(-80 * 5, 100);
        }
    }
}
##
##

#Subtopic Blend_Mode_Overview_Porter_Duff_2
#Example
#Width 480
#Height 330
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    SkPaint srcPaint;
    srcPaint.setAntiAlias(true);
    SkPaint labelPaint = srcPaint;
    SkFont labelFont(nullptr, 16);
    SkPaint dstPaint = srcPaint;
    dstPaint.setColor(0xFF606080);
    SkFont dstFont(SkTypeface::MakeFromName("Roboto", SkFontStyle::Bold()), 80);

    srcPaint.setColor(0xFFcc6633);
    SkPath srcPath;
    const SkPoint points[] = {{20, 20}, {80, 45}, {45, 80}};
    srcPath.addPoly(points, SK_ARRAY_COUNT(points), true);
    canvas->drawColor(0, SkBlendMode::kClear);

    SkBitmap dstBits;
    dstBits.allocN32Pixels(80, 80);
    SkCanvas dstCanvas(dstBits);
    for (auto blend : { SkBlendMode::kSrc, SkBlendMode::kSrcATop, SkBlendMode::kSrcOver,
                        SkBlendMode::kSrcIn, SkBlendMode::kSrcOut,
                        SkBlendMode::kDst, SkBlendMode::kDstATop, SkBlendMode::kDstOver,
                        SkBlendMode::kDstIn, SkBlendMode::kDstOut,
                        SkBlendMode::kClear, SkBlendMode::kXor } ) {
        SkTextUtils::DrawString(canvas, "&", 50, 80, dstFont, dstPaint, SkTextUtils::kCenter_Align);
        srcPaint.setBlendMode(blend);
        canvas->drawPath(srcPath, srcPaint);
        SkTextUtils::DrawString(canvas, SkBlendMode_Name(blend), 50, 100, labelFont, labelPaint, SkTextUtils::kCenter_Align);
        canvas->translate(80, 0);
        if (SkBlendMode::kSrcOut == blend || SkBlendMode::kDstOut == blend) {
            canvas->translate(-80 * 5, 100);
        }
    }
}
##
##

#Subtopic Blend_Mode_Overview_Lighten_Darken
#Example
#Width 480
#Height 330
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    SkPaint srcPaint;
    srcPaint.setAntiAlias(true);
    SkPaint labelPaint = srcPaint;
    SkFont labelFont(nullptr, 16);
    SkPaint dstPaint = srcPaint;
    dstPaint.setColor(0xFF606080);
    SkFont dstFont(SkTypeface::MakeFromName("Roboto", SkFontStyle::Bold()), 80);

    srcPaint.setColor(0xFFcc6633);
    SkPath srcPath;
    const SkPoint points[] = {{20, 20}, {80, 45}, {45, 80}};
    srcPath.addPoly(points, SK_ARRAY_COUNT(points), true);
    canvas->drawColor(0, SkBlendMode::kClear);
    for (auto blend : { SkBlendMode::kPlus, SkBlendMode::kScreen, SkBlendMode::kOverlay,
            SkBlendMode::kDarken, SkBlendMode::kLighten, SkBlendMode::kColorDodge,
            SkBlendMode::kColorBurn, SkBlendMode::kHardLight, SkBlendMode::kSoftLight,
            SkBlendMode::kDifference, SkBlendMode::kExclusion, SkBlendMode::kMultiply } ) {
        SkTextUtils::DrawString(canvas, "&", 50, 80, dstFont, dstPaint, SkTextUtils::kCenter_Align);
        srcPaint.setBlendMode(blend);
        canvas->drawPath(srcPath, srcPaint);
        SkTextUtils::DrawString(canvas, SkBlendMode_Name(blend), 50, 100, labelFont, labelPaint,
                SkTextUtils::kCenter_Align);
        canvas->translate(90, 0);
        if (SkBlendMode::kLighten == blend || SkBlendMode::kDifference == blend) {
            canvas->translate(-90 * 5, 100);
        }
    }
}
##
##

#Subtopic Blend_Mode_Overview_Color_Blends
#Example
#Width 480
#Height 110
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    SkPaint srcPaint;
    srcPaint.setAntiAlias(true);
    SkPaint labelPaint = srcPaint;
    SkFont labelFont(nullptr, 16);
    SkPaint dstPaint = labelPaint;
    dstPaint.setColor(0xFF606080);
    SkFont dstFont(SkTypeface::MakeFromName("Roboto", SkFontStyle::Bold()), 80);

    srcPaint.setColor(0xFFcc6633);
    SkPath srcPath;
    const SkPoint points[] = {{20, 20}, {80, 45}, {45, 80}};
    srcPath.addPoly(points, SK_ARRAY_COUNT(points), true);
    canvas->drawColor(0, SkBlendMode::kClear);
    for (auto blend : { SkBlendMode::kHue, SkBlendMode::kSaturation, SkBlendMode::kColor,
                        SkBlendMode::kLuminosity } ) {
        SkTextUtils::DrawString(canvas, "&", 50, 80, dstFont, dstPaint, SkTextUtils::kCenter_Align);
        srcPaint.setBlendMode(blend);
        canvas->drawPath(srcPath, srcPaint);
        SkTextUtils::DrawString(canvas, SkBlendMode_Name(blend), 50, 100, labelFont, labelPaint,
                SkTextUtils::kCenter_Align);
        canvas->translate(90, 0);
    }
}
##
##

#Subtopic Blend_Mode_Overview_Modulate_Blend
#Example
#Width 480
#Height 110
#Function
###$
#include "SkTextUtils.h"
$$$#
##

void draw(SkCanvas* canvas) {
    SkPaint srcPaint;
    srcPaint.setAntiAlias(true);
    SkPaint labelPaint = srcPaint;
    SkFont labelFont(nullptr, 16);
    SkPaint dstPaint = srcPaint;
    dstPaint.setColor(0xFF606080);
    SkFont dstFont(SkTypeface::MakeFromName("Roboto", SkFontStyle::Bold()), 80);

    SkBitmap srcBits;
    srcBits.allocN32Pixels(80, 84);
    SkCanvas srcCanvas(srcBits);
    srcPaint.setColor(0xFFcc6633);
    SkPath srcPath;
    const SkPoint points[] = {{20, 20}, {80, 45}, {45, 80}};
    srcPath.addPoly(points, SK_ARRAY_COUNT(points), true);
    srcBits.eraseColor(0);
    srcCanvas.drawPath(srcPath, srcPaint);

    canvas->drawColor(0, SkBlendMode::kClear);
    srcPaint.setBlendMode(SkBlendMode::kModulate);
    for (auto step: { 1, 2 } ) {
        SkTextUtils::DrawString(canvas, "&", 50, 80, dstFont, dstPaint, SkTextUtils::kCenter_Align);
        if (1 == step) {
            canvas->drawBitmap(srcBits, 0, 0, &srcPaint);
            SkTextUtils::DrawString(canvas, "Bitmap", 50, 18, labelFont, labelPaint, SkTextUtils::kCenter_Align);
        } else {
            canvas->drawPath(srcPath, srcPaint);
            SkTextUtils::DrawString(canvas, "Geometry", 50, 18, labelFont, labelPaint, SkTextUtils::kCenter_Align);
        }
        SkTextUtils::DrawString(canvas, SkBlendMode_Name(SkBlendMode::kModulate), 50, 100, labelFont, labelPaint,
                SkTextUtils::kCenter_Align);
        canvas->translate(120, 0);
    }
}
##
##

#Subtopic Path_Arc
#Example
#Height 300
#Width 600
#Function
###$

struct data {
   const char* name;
   char super;
   int yn[10];
};

const data dataSet[] = {
{ "arcTo sweep",    '1', {1,  3, 1, 0, 0, 0, 0, 1, 0, 0 }},
{ "drawArc",         0,  {1, -1, 1, 1, 1, 1, 1, 0, 0, 0 }},
{ "addArc",          0,  {1,  1, 1, 4, 0, 1, 1, 1, 0, 0 }},
{ "arcTo tangents", '4', {0,  0, 0, 0, 0, 0, 0, 1, 1, 0 }},
{ "arcTo radii",    '5', {1,  0, 1, 0, 0, 0, 0, 1, 1, 0 }},
{ "conicTo",         0,  {1,  1, 0, 0, 0, 0, 0, 1, 1, 1 }}
};

#define __degree_symbol__ "\xC2" "\xB0"

const char* headers[] = {
    "Oval part",
    "force moveTo",
    "can draw 180" __degree_symbol__,
    "can draw 360" __degree_symbol__,
    "can draw greater than 360" __degree_symbol__,
    "ignored if radius is zero",
    "ignored if sweep is zero",
    "requires Path",
    "describes rotation",
    "describes perspective",
};

const char* yna[] = {
     "n/a",
     "no",
     "yes"
};
$$$#
##
void draw(SkCanvas* canvas) {
    SkPaint lp;
    lp.setAntiAlias(true);
    SkPaint tp(lp);
    SkPaint sp(tp);
    SkFont bf;
    bf.setEmbolden(true);
    SkFont sf(nullptr, 10);
    lp.setColor(SK_ColorGRAY);
    canvas->translate(0, 32);
    const int tl = 115;
    for (unsigned col = 0; col <= SK_ARRAY_COUNT(headers); ++col) {
       canvas->drawLine(tl + col * 35, 100, tl + col * 35, 250, lp);
       if (0 == col) {
          continue;
       }
       canvas->drawLine( tl +        col * 35, 100,  tl + 100  + col * 35,   0, lp);
       SkPoint pts[] = {{tl - 10.f + col * 35, 98}, {tl + 90.f + col * 35,  -2}};
       SkVector v = pts[1] - pts[0];
       v.normalize();
       SkMatrix matrix;
       matrix.setSinCos(v.fY, v.fX, pts[0].fX, pts[0].fY);
       canvas->save();
       canvas->concat(matrix);
       canvas->drawSimpleText(headers[col -1], strlen(headers[col -1]), SkTextEncoding::kUTF8,
            pts[0].fX, pts[0].fY, bf, lp);
       canvas->restore();
    }
    for (unsigned row = 0; row <= SK_ARRAY_COUNT(dataSet); ++row) {
        if (0 == row) {
            canvas->drawLine(tl, 100, tl + 350, 100, lp);
        } else {
            canvas->drawLine(5, 100 + row * 25, tl + 350, 100 + row * 25, lp);
        }
        if (row == SK_ARRAY_COUNT(dataSet)) {
            break;
        }
        canvas->drawSimpleText(dataSet[row].name, strlen(dataSet[row].name),
              SkTextEncoding::kUTF8, 5, 117 + row * 25, bf, lp);
        if (dataSet[row].super) {
            SkScalar width = bf.measureText(dataSet[row].name, strlen(dataSet[row].name),
                    SkTextEncoding::kUTF8);
            canvas->drawSimpleText(&dataSet[row].super, 1, SkTextEncoding::kUTF8,
                    8 + width, 112 + row * 25, sf, lp);
        }
        for (unsigned col = 0; col < SK_ARRAY_COUNT(headers); ++col) {
            int val = dataSet[row].yn[col];
            canvas->drawString(yna[SkTMin(2, val + 1)], tl + 5 + col * 35, 117 + row * 25, tp);
            if (val > 1) {
                char supe = '0' + val - 1;
                canvas->drawSimpleText(&supe, 1, SkTextEncoding::kUTF8,
                     tl + 25 + col * 35, 112 + row * 25, sf, lp);
            }
        }
    }
}
#Example ##
##

#Topic Illustrations ##