head 1.6; access; symbols; locks; strict; comment @ * @; 1.6 date 2005.07.29.07.48.07; author behdad; state Exp; branches; next 1.5; commitid 284a42e9df0e4567; 1.5 date 2005.05.17.15.24.39; author cworth; state Exp; branches; next 1.4; commitid 22b4428a0cb74567; 1.4 date 2005.05.17.14.31.43; author cworth; state Exp; branches; next 1.3; commitid 2e0428a004e4567; 1.3 date 2004.10.18.22.37.34; author cworth; state Exp; branches; next 1.2; 1.2 date 2004.10.18.21.11.44; author cworth; state Exp; branches; next 1.1; 1.1 date 2004.10.18.14.43.47; author cworth; state Exp; branches; next ; desc @@ 1.6 log @2005-07-29 Behdad Esfahbod */ /* This simple demo demonstrates how cairo may be used to draw * old-fashioned widgets with bevels that depend on lines exactly * 1-pixel wide. * * This demo is really only intended to demonstrate how someone might * emulate antique graphics, and this style is really not recommended * for future code. Some notes: * * 1) We're not going for pixel-perfect emulation of crusty graphics * here. Notice that the checkmark is rendered nicely by cairo * without jaggies. * * 2) The use of opaque highlight/lowlight colors here is particularly * passé. A much more interesting approach would blend translucent * colors over an arbitrary background. * * 3) This widget style is optimized for device-pixels. As such, it * won't scale up very well, (except for integer scale * factors). I'd be more interested to see future widget schemes * that look good at all scales. * * One way to get better-looking graphics at all scales might be to * introduce some device-pixel snapping into cairo for * horizontal/vertical path components. Then, a lot of the 0.5 * adjustments could disappear from code like this, and then this code * could become more scalable. */ #include #include #include #define WIDTH 100 #define HEIGHT 70 #define STRIDE (WIDTH * 4) unsigned char image[STRIDE*HEIGHT]; typedef struct hex_color { uint16_t r, g, b; } hex_color_t; hex_color_t BG_COLOR = { 0xd4, 0xd0, 0xc8 }; hex_color_t HI_COLOR_1 = { 0xff, 0xff, 0xff }; hex_color_t HI_COLOR_2 = { 0xd4, 0xd0, 0xc8 }; hex_color_t LO_COLOR_1 = { 0x80, 0x80, 0x80 }; hex_color_t LO_COLOR_2 = { 0x40, 0x40, 0x40 }; hex_color_t BLACK = { 0, 0, 0 }; static void set_hex_color (cairo_t *cr, hex_color_t color) { cairo_set_source_rgb (cr, color.r / 255.0, color.g / 255.0, color.b / 255.0); } static void bevel_box (cairo_t *cr, int x, int y, int width, int height) { cairo_save (cr); cairo_set_line_width (cr, 1.0); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); /* Fill and highlight */ set_hex_color (cr, HI_COLOR_1); cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); /* 2nd highlight */ set_hex_color (cr, HI_COLOR_2); cairo_move_to (cr, x + 1.5, y + height - 1.5); cairo_rel_line_to (cr, width - 3, 0); cairo_rel_line_to (cr, 0, - (height - 3)); cairo_stroke (cr); /* 1st lowlight */ set_hex_color (cr, LO_COLOR_1); cairo_move_to (cr, x + .5, y + height - 1.5); cairo_rel_line_to (cr, 0, - (height - 2)); cairo_rel_line_to (cr, width - 2, 0); cairo_stroke (cr); /* 2nd lowlight */ set_hex_color (cr, LO_COLOR_2); cairo_move_to (cr, x + 1.5, y + height - 2.5); cairo_rel_line_to (cr, 0, - (height - 4)); cairo_rel_line_to (cr, width - 4, 0); cairo_stroke (cr); cairo_restore (cr); } static void bevel_circle (cairo_t *cr, int x, int y, int width) { double radius = (width-1)/2.0 - 0.5; cairo_save (cr); cairo_set_line_width (cr, 1); /* Fill and Highlight */ set_hex_color (cr, HI_COLOR_1); cairo_arc (cr, x+radius+1.5, y+radius+1.5, radius, 0, 2* M_PI); cairo_fill (cr); /* 2nd highlight */ set_hex_color (cr, HI_COLOR_2); cairo_arc (cr, x+radius+0.5, y+radius+0.5, radius, 0, 2 * M_PI); cairo_stroke (cr); /* 1st lowlight */ set_hex_color (cr, LO_COLOR_1); cairo_arc (cr, x+radius+0.5, y+radius+0.5, radius, 3 * M_PI_4, 7 * M_PI_4); cairo_stroke (cr); /* 2nd lowlight */ set_hex_color (cr, LO_COLOR_2); cairo_arc (cr, x+radius+1.5, y+radius+1.5, radius, 3 * M_PI_4, 7 * M_PI_4); cairo_stroke (cr); cairo_restore (cr); } /* Slightly smaller than specified to match interior size of bevel_box */ static void flat_box (cairo_t *cr, int x, int y, int width, int height) { cairo_save (cr); /* Fill background */ set_hex_color (cr, HI_COLOR_1); cairo_rectangle (cr, x+1, y+1, width-2, height-2); cairo_fill (cr); /* Stroke outline */ cairo_set_line_width (cr, 1.0); set_hex_color (cr, BLACK); cairo_rectangle (cr, x + 1.5, y + 1.5, width - 3, height - 3); cairo_stroke (cr); cairo_restore (cr); } static void flat_circle (cairo_t *cr, int x, int y, int width) { double radius = (width - 1) / 2.0; cairo_save (cr); /* Fill background */ set_hex_color (cr, HI_COLOR_1); cairo_arc (cr, x+radius+0.5, y+radius+0.5, radius-1, 0, 2 * M_PI); cairo_fill (cr); /* Fill background */ cairo_set_line_width (cr, 1.0); set_hex_color (cr, BLACK); cairo_arc (cr, x+radius+0.5, y+radius+0.5, radius-1, 0, 2 * M_PI); cairo_stroke (cr); cairo_restore (cr); } static void groovy_box (cairo_t *cr, int x, int y, int width, int height) { cairo_save (cr); /* Highlight */ set_hex_color (cr, HI_COLOR_1); cairo_set_line_width (cr, 2); cairo_rectangle (cr, x + 1, y + 1, width - 2, height - 2); cairo_stroke (cr); /* Lowlight */ set_hex_color (cr, LO_COLOR_1); cairo_set_line_width (cr, 1); cairo_rectangle (cr, x + 0.5, y + 0.5, width - 2, height - 2); cairo_stroke (cr); cairo_restore (cr); } #define CHECK_BOX_SIZE 13 #define CHECK_COLOR BLACK typedef enum {UNCHECKED, CHECKED} checked_status_t; static void check_box (cairo_t *cr, int x, int y, checked_status_t checked) { cairo_save (cr); bevel_box (cr, x, y, CHECK_BOX_SIZE, CHECK_BOX_SIZE); if (checked) { set_hex_color (cr, CHECK_COLOR); cairo_move_to (cr, x + 3, y + 5); cairo_rel_line_to (cr, 2.5, 2); cairo_rel_line_to (cr, 4.5, -4); cairo_rel_line_to (cr, 0, 3); cairo_rel_line_to (cr, -4.5, 4); cairo_rel_line_to (cr, -2.5, -2); cairo_close_path (cr); cairo_fill (cr); } cairo_restore (cr); } #define RADIO_SIZE CHECK_BOX_SIZE #define RADIO_DOT_COLOR BLACK static void radio_button (cairo_t *cr, int x, int y, checked_status_t checked) { cairo_save (cr); bevel_circle (cr, x, y, RADIO_SIZE); if (checked) { set_hex_color (cr, RADIO_DOT_COLOR); cairo_arc (cr, x + (RADIO_SIZE-1) / 2.0 + 0.5, y + (RADIO_SIZE-1) / 2.0 + 0.5, (RADIO_SIZE-1) / 2.0 - 3.5, 0, 2 * M_PI); cairo_fill (cr); } cairo_restore (cr); } static void draw_bevels (cairo_t *cr, int width, int height) { int check_room = (width - 20) / 3; int check_pad = (check_room - CHECK_BOX_SIZE) / 2; groovy_box (cr, 5, 5, width - 10, height - 10); check_box (cr, 10+check_pad, 10+check_pad, UNCHECKED); check_box (cr, check_room+10+check_pad, 10+check_pad, CHECKED); flat_box (cr, 2 * check_room+10+check_pad, 10+check_pad, CHECK_BOX_SIZE, CHECK_BOX_SIZE); radio_button (cr, 10+check_pad, check_room+10+check_pad, UNCHECKED); radio_button (cr, check_room+10+check_pad, check_room+10+check_pad, CHECKED); flat_circle (cr, 2 * check_room+10+check_pad, check_room+10+check_pad, CHECK_BOX_SIZE); } int main (void) { cairo_t *cr; cairo_surface_t *surface; surface = cairo_image_surface_create_for_data (image, CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT, STRIDE); cr = cairo_create (surface); cairo_rectangle (cr, 0, 0, WIDTH, HEIGHT); set_hex_color (cr, BG_COLOR); cairo_fill (cr); draw_bevels (cr, WIDTH, HEIGHT); cairo_surface_write_to_png (surface, "bevels.png"); cairo_destroy (cr); cairo_surface_destroy (surface); return 0; } @ 1.5 log @ * bevels.c: * caps_joins.c: * hering.c: * outline.c: * snapping.c: * spiral.c: * splines_tolerance.c: * star_and_ring.c: * stars.c: * text-rotate.c: * text.c: Remove stale includes of write_png.h. @ text @d181 2 a184 2 double radius = (width - 1) / 2.0; @ 1.4 log @ * Makefile: * bevels.c: (set_hex_color), (main): * caps_joins.c: (main), (stroke_v_twice), (draw_caps_joins): * hering.c: (main), (draw_hering): * outline.c: (main), (create_gradient), (draw_outlines): * snapping.c: (snap_point_for_fill), (snap_point_for_stroke), (snap_line_width), (snap_path_for_fill), (snap_path_for_stroke), (draw_nested), (main): * spiral.c: (main), (draw_spiral): * splines_tolerance.c: (main), (draw_splines): * star_and_ring.c: (star_path), (fill_ring), (fill_star), (main): * stars.c: (main), (draw_stars): * text-rotate.c: (main): * text.c: (box_text), (box_glyphs), (main): Update all programs to match recent cairo API changes. @ text @a57 2 #include "write_png.h" @ 1.3 log @ (bevel_circle): Fix circular widgets to match style of squares. @ text @d56 1 d64 1 a64 1 char image[STRIDE*HEIGHT]; d81 1 a81 1 cairo_set_rgb_color (cr, d295 1 d297 3 a299 4 cr = cairo_create (); cairo_set_target_image (cr, image, CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT, STRIDE); d307 1 a307 1 write_png_argb32 (image, "bevels.png", WIDTH, HEIGHT, STRIDE); d311 2 @ 1.2 log @ (draw_bevels): Add sample radio buttons to demonstrate that circles work as well as rectangles. @ text @d132 1 a132 1 /* Highlight */ d136 6 a141 1 cairo_close_path (cr); d144 1 a144 1 /* Lowlight */ d147 7 a153 1 0, 2 * M_PI); d262 3 a264 3 x + (RADIO_SIZE-1) / 2.0, y + (RADIO_SIZE-1) / 2.0, (RADIO_SIZE-1) / 2.0 - 3, @ 1.1 log @ * bevels.c: Add bevel example showing lines of 1-pixel width. @ text @d59 2 a60 2 #define WIDTH 60 #define HEIGHT 60 d124 26 d156 1 a156 1 cairo_rectangle (cr, x, y, width, height); d162 24 a185 1 cairo_rectangle (cr, x + 0.5, y + 0.5, width - 1, height - 1); d238 23 d264 1 a264 1 int check_room = (width - 20) / 2; d269 8 a276 4 check_box (cr, 10 + check_pad, 10 + check_pad, UNCHECKED); check_box (cr, 10 + check_pad, 10 + check_room + check_pad, CHECKED); flat_box (cr, 10 + check_room + check_pad + 1, 10 + check_pad + 1, CHECK_BOX_SIZE-2, CHECK_BOX_SIZE-2); @