blob: 2ffc0092f33d6e77612fe932a4d928ec56261887 [file] [log] [blame]
Mike Klein6bfe3f52017-05-05 13:49:00 -04001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9#include "sk_tool_utils.h"
10
11// Hue, Saturation, Color, and Luminosity blend modes are oddballs.
12// They nominally convert their inputs to unpremul, then to HSL, then
13// mix-and-match H,S,and L from Src and Dst, then convert back, then premul.
14//
15// Each mode's name describes the Src H,S,L components to keep, taking the
16// others from Dst, where Color == Hue + Saturation. Color and Luminosity
17// are each other's complements; Hue and Saturation have no complement.
18//
19// We have had many inconsistent implementations of these modes.
20// This GM tries to demonstrate unambigously how they should work.
21//
22// TODO: double- and triple-check expected colors
23// TODO: how does gamma-correction factor into this?
24
25DEF_SIMPLE_GM(hsl, canvas, 600, 100) {
26 SkPaint label;
27 sk_tool_utils::set_portable_typeface(&label);
28 label.setAntiAlias(true);
29
30 const char* comment = "HSL blend modes are correct when you see no circles in the squares.";
31 canvas->drawText(comment, strlen(comment), 10,10, label);
32
33 // Just to keep things reaaaal simple, we'll only use opaque colors.
34 SkPaint bg, fg;
35 bg.setColor(0xff00ff00); // Fully-saturated bright green, H = 120°, S = 100%, L = 50%.
36 fg.setColor(0xff7f3f7f); // Partly-saturated dim magenta, H = 300°, S = ~33%, L = ~37%.
37
38 struct {
39 SkBlendMode mode;
40 SkColor expected;
41 } tests[] = {
42 { SkBlendMode::kSrc, fg.getColor() },
43 { SkBlendMode::kDst, bg.getColor() },
44 { SkBlendMode::kHue, 0xffff00ff }, // bright magenta, H = 300°, S = 100%, L = 50%
45 { SkBlendMode::kSaturation, 0xff55aa55 }, // a duller green, H = 120°, S = ~33%, L = 50%
46 { SkBlendMode::kColor, 0xffaa55aa }, // a lighter fg, H = 300°, S = ~33%, L = 50%
47 { SkBlendMode::kLuminosity, 0xff00bd00 }, // a darker bg, H = 120°, S = 100%, L = ~37%
48 };
49 for (auto test : tests) {
50 canvas->drawRect({20,20,80,80}, bg);
51
52 fg.setBlendMode(test.mode);
53 canvas->drawRect({20,20,80,80}, fg);
54
55 SkPaint expected;
56 expected.setColor(test.expected);
57 canvas->drawCircle(50,50, 20, expected);
58
59 const char* name = SkBlendMode_Name(test.mode);
60 canvas->drawText(name, strlen(name), 20,90, label);
61
62 canvas->translate(100,0);
63 }
64}