summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blend.txt12
-rw-r--r--pics.c88
2 files changed, 84 insertions, 16 deletions
diff --git a/blend.txt b/blend.txt
index b2b4763..72927cc 100644
--- a/blend.txt
+++ b/blend.txt
@@ -9,16 +9,14 @@ there, when it is 0, the image isn't there at all. In other words, the
alpha channel describes the the shape of the image, it does not
describe opacity. The reason we have alpha values between 0 and 1 is
so that the shape can be antialiased. The way to think of images with
-an alpha channel in the Porter/Duff model is as irregularly shaped
-pieces of cardboard, not as colored glass.
+an alpha channel is as irregularly shaped pieces of cardboard, not as
+colored glass.
Consider these two images:
SRC ("triangle") DEST ("ampersand")
-If we combine them and zoom in on one pixel, we get this:
-
-Each individual pixel can be divided into four regions:
+When we combine them, each pixel can be divided into four regions:
\ /
\ /
@@ -140,9 +138,7 @@ other formulas than just { C_s, C_d, 0 }. With one additional blend
mode, 'plus', the ADD operator falls out as well.
This model is a simple and coherent way to extend the Porter/Duff
-compositing algebra with blend modes. If we were to generalize the
-operators in pixman/cairo/X11, this is the model we should be looking
-at.
+compositing algebra with blend modes.
CSS compositing spec
diff --git a/pics.c b/pics.c
index d9b571e..1dc33a3 100644
--- a/pics.c
+++ b/pics.c
@@ -3,6 +3,9 @@
#define CHECK_SIZE 16
+#define SOURCE_COLOR 0.8, 0.5, 0.2
+#define DEST_COLOR 0.2, 0.2, 0.4
+
static cairo_t *
get_cairo (int width, int height)
{
@@ -55,7 +58,7 @@ draw_ampersand (cairo_t *cr)
CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 80);
cairo_text_path (cr, "&");
- cairo_set_source_rgb (cr, 0.2, 0.2, 0.4);
+ cairo_set_source_rgb (cr, DEST_COLOR);
cairo_fill (cr);
}
@@ -66,7 +69,7 @@ draw_polygon (cairo_t *cr)
cairo_rel_line_to (cr, 65, 35);
cairo_rel_line_to (cr, -38, 35);
- cairo_set_source_rgb (cr, 0.8, 0.3, 0.2);
+ cairo_set_source_rgb (cr, SOURCE_COLOR);
cairo_fill (cr);
}
@@ -135,7 +138,6 @@ centered_text (cairo_t *cr, double x, double y, const char *text)
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_new_path (cr);
- cairo_set_source_rgb (cr, 0, 0, 0);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_set_font_size (cr, 14.0);
cairo_text_path (cr, text);
@@ -184,6 +186,7 @@ draw_cell (cairo_t *cr,
draw_source (cr);
}
+ cairo_set_source_rgb (cr, 0, 0, 0);
centered_text (cr,
x + CELL_WIDTH / 2.0 - 20.0,
y + CELL_HEIGHT - 30, name);
@@ -216,23 +219,92 @@ static void
create_op (cairo_operator_t op, const char *name, const char *filename)
{
cairo_t *cr = get_cairo (CELL_WIDTH + 20, CELL_HEIGHT);
- char fn[64] = { 0 };
cairo_move_to (cr, 0, 0);
draw_cell (cr, 30, 10, op, name);
- snprintf (fn, 63, "%s.png", filename);
- finish (cr, fn);
+ finish (cr, filename);
+}
+
+static void
+clear_to_white (cairo_t *cr)
+{
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+}
+
+static void
+draw_pixel_box (cairo_t *cr)
+{
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_rectangle (cr, 1, 1, 178, 178);
+ cairo_move_to (cr, 1, 1);
+ cairo_line_to (cr, 179, 179);
+ cairo_move_to (cr, 179, 1);
+ cairo_line_to (cr, 1, 179);
+ cairo_stroke (cr);
+}
+
+static void
+general_pixel_diagram (const char *filename)
+{
+ cairo_t *cr = get_cairo (180, 180);
+
+ clear_to_white (cr);
+ draw_pixel_box (cr);
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ centered_text (cr, 90, 45, "Both");
+ centered_text (cr, 35, 90, "Source");
+ centered_text (cr, 145, 90, "Dest");
+ centered_text (cr, 90, 147, "Neither");
+
+ finish (cr, filename);
+}
+
+static void
+dest_atop_diagram (const char *filename)
+{
+ cairo_t *cr = get_cairo (180, 180);
+
+ cairo_move_to (cr, 1, 1);
+ cairo_line_to (cr, 90, 90);
+ cairo_line_to (cr, 179, 1);
+ cairo_set_source_rgb (cr, DEST_COLOR);
+ cairo_fill (cr);
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ centered_text (cr, 90, 45, "Both");
+
+ cairo_move_to (cr, 1, 1);
+ cairo_line_to (cr, 90, 90);
+ cairo_line_to (cr, 1, 179);
+ cairo_set_source_rgb (cr, SOURCE_COLOR);
+ cairo_fill (cr);
+
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ centered_text (cr, 35, 90, "Source");
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ centered_text (cr, 145, 90, "Dest");
+ centered_text (cr, 90, 147, "Neither");
+
+ draw_pixel_box (cr);
+
+ finish (cr, filename);
}
int
main (int argc, char *argv)
{
- create_ampersand ();
- create_polygon ();
+ create_op (CAIRO_OPERATOR_SOURCE, "Source", "source.png");
+ create_op (CAIRO_OPERATOR_DEST, "Destination", "dest.png");
create_op (CAIRO_OPERATOR_COLOR_DODGE, "Color Dodge", "colordodge.png");
create_op (CAIRO_OPERATOR_DEST_ATOP, "Dest Atop", "destatop.png");
create_op (CAIRO_OPERATOR_OVER, "Over", "over.png");
create_porter_duff_table ();
+ general_pixel_diagram ("diagram.png");
+ dest_atop_diagram ("destatop-diagram.png");
}