Andrew Top | 200ce4b | 2018-01-29 13:43:50 -0800 | [diff] [blame] | 1 | Skia's Stable C API |
| 2 | =================== |
| 3 | |
| 4 | <div style="text-align:center"> |
| 5 | <strong>EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL<br> |
| 6 | DO NOT USE — FOR INTERNAL TESTING ONLY</strong> |
| 7 | </div> |
| 8 | |
| 9 | Several issues hinder the development of a stable ABI (application |
| 10 | binary interface) for Skia: |
| 11 | |
| 12 | 1. Skia's C++ API changes a lot from version to version. Skia's two |
| 13 | largest clients, Android and Chrome, are kept up to date by the |
| 14 | Skia team, but that can not happen for every client. |
| 15 | 2. Skia's headers will only match the compiled skia libraries if |
| 16 | configured identically. |
| 17 | |
| 18 | To mitigate these two issues, Skia is experimenting with the |
| 19 | introduction of a C API. This will change more slowly than the C++ |
| 20 | interface and, once API version 1.0.0 is announced, |
| 21 | backwards-incompatable changes will be avoided whenever possible. |
| 22 | |
| 23 | Here is an example program that uses the C api. To try it out, get the file |
| 24 | [`skia-c-example.c`](./skia-c-example.c). |
| 25 | |
| 26 | <!--?prettify lang=c?--> |
| 27 | |
| 28 | #include <stdio.h> |
| 29 | |
| 30 | #include "sk_data.h" |
| 31 | #include "sk_image.h" |
| 32 | #include "sk_canvas.h" |
| 33 | #include "sk_surface.h" |
| 34 | #include "sk_paint.h" |
| 35 | #include "sk_path.h" |
| 36 | |
| 37 | static sk_surface_t* make_surface(int32_t w, int32_t h) { |
| 38 | sk_imageinfo_t info; |
| 39 | info.width = w; |
| 40 | info.height = h; |
| 41 | info.colorType = sk_colortype_get_default_8888(); |
| 42 | info.alphaType = PREMUL_SK_ALPHATYPE; |
| 43 | return sk_surface_new_raster(&info, NULL); |
| 44 | } |
| 45 | |
| 46 | static void emit_png(const char* path, sk_surface_t* surface) { |
| 47 | sk_image_t* image = sk_surface_new_image_snapshot(surface); |
| 48 | sk_data_t* data = sk_image_encode(image); |
| 49 | sk_image_unref(image); |
| 50 | FILE* f = fopen(path, "wb"); |
| 51 | fwrite(sk_data_get_data(data), sk_data_get_size(data), 1, f); |
| 52 | fclose(f); |
| 53 | sk_data_unref(data); |
| 54 | } |
| 55 | |
| 56 | void draw(sk_canvas_t* canvas) { |
| 57 | sk_paint_t* fill = sk_paint_new(); |
| 58 | sk_paint_set_color(fill, sk_color_set_argb(0xFF, 0x00, 0x00, 0xFF)); |
| 59 | sk_canvas_draw_paint(canvas, fill); |
| 60 | |
| 61 | sk_paint_set_color(fill, sk_color_set_argb(0xFF, 0x00, 0xFF, 0xFF)); |
| 62 | sk_rect_t rect; |
| 63 | rect.left = 100.0f; |
| 64 | rect.top = 100.0f; |
| 65 | rect.right = 540.0f; |
| 66 | rect.bottom = 380.0f; |
| 67 | sk_canvas_draw_rect(canvas, &rect, fill); |
| 68 | |
| 69 | sk_paint_t* stroke = sk_paint_new(); |
| 70 | sk_paint_set_color(stroke, sk_color_set_argb(0xFF, 0xFF, 0x00, 0x00)); |
| 71 | sk_paint_set_antialias(stroke, true); |
| 72 | sk_paint_set_stroke(stroke, true); |
| 73 | sk_paint_set_stroke_width(stroke, 5.0f); |
| 74 | sk_path_t* path = sk_path_new(); |
| 75 | |
| 76 | sk_path_move_to(path, 50.0f, 50.0f); |
| 77 | sk_path_line_to(path, 590.0f, 50.0f); |
| 78 | sk_path_cubic_to(path, -490.0f, 50.0f, 1130.0f, 430.0f, 50.0f, 430.0f); |
| 79 | sk_path_line_to(path, 590.0f, 430.0f); |
| 80 | sk_canvas_draw_path(canvas, path, stroke); |
| 81 | |
| 82 | sk_paint_set_color(fill, sk_color_set_argb(0x80, 0x00, 0xFF, 0x00)); |
| 83 | sk_rect_t rect2; |
| 84 | rect2.left = 120.0f; |
| 85 | rect2.top = 120.0f; |
| 86 | rect2.right = 520.0f; |
| 87 | rect2.bottom = 360.0f; |
| 88 | sk_canvas_draw_oval(canvas, &rect2, fill); |
| 89 | |
| 90 | sk_path_delete(path); |
| 91 | sk_paint_delete(stroke); |
| 92 | sk_paint_delete(fill); |
| 93 | } |
| 94 | |
| 95 | int main() { |
| 96 | sk_surface_t* surface = make_surface(640, 480); |
| 97 | sk_canvas_t* canvas = sk_surface_get_canvas(surface); |
| 98 | draw(canvas); |
| 99 | emit_png("skia-c-example.png", surface); |
| 100 | sk_surface_unref(surface); |
| 101 | return 0; |
| 102 | } |
| 103 | |
| 104 | <a href="https://fiddle.skia.org/c/6c6c01438d9c3d80e9c22e606359432e"><img src="https://fiddle.skia.org/i/6c6c01438d9c3d80e9c22e606359432e_raster.png" alt=""></a> |
| 105 | |
| 106 | Example |
| 107 | ------- |
| 108 | |
| 109 | The following proof-of-concept workflow currently works on MacOS and |
| 110 | Ubuntu. |
| 111 | |
| 112 | 1. Compile Skia as a shared library: |
| 113 | |
| 114 | <!--?prettify lang=sh?--> |
| 115 | |
| 116 | cd ...../skia |
| 117 | bin/sync |
| 118 | gn gen out/Shared --args='is_official_build=true is_component_build=true' |
| 119 | ninja -C out/Shared |
| 120 | SKIA_LIB_DIR="${PWD}/out/Shared" |
| 121 | |
| 122 | 2. Compile, link, and run the example program: |
| 123 | |
| 124 | <!--?prettify lang=sh?--> |
| 125 | |
| 126 | cc -o skia-c-example -I include/c \ |
| 127 | experimental/c-api-example/skia-c-example.c \ |
| 128 | "$SKIA_LIB_DIR"/libskia.* -Wl,-rpath -Wl,"$SKIA_LIB_DIR" |
| 129 | ./skia-c-example |
Xiaoming Shi | 73dfa20 | 2020-03-12 11:31:35 -0700 | [diff] [blame] | 130 | bin/sysopen skia-c-example.png |