]>
gitweb.michael.orlitzky.com - libsvgtiny.git/blob - examples/svgtiny_display_x11.c
ca746402fc0c57b7dc5f4654cabe69d5254530b0
2 * This file is part of Libsvgtiny
3 * Licensed under the MIT License,
4 * http://opensource.org/licenses/mit-license.php
5 * Copyright 2009-2010 James Bursa <james@semichrome.net>
9 * This example loads an SVG using libsvgtiny and then displays it in an X11
12 * Functions of interest for libsvgtiny use are:
13 * main() - loads an SVG using svgtiny_create() and svgtiny_parse()
14 * event_diagram_expose() - renders the SVG by stepping through the shapes
16 * A GNUMakefile is provided to ease compilation. To build the example
17 * program against the system copy of libsvgtiny, you can simply run,
21 * Or, if you are developing libsvgtiny and want to build against your
22 * local copy, you can run,
24 * $ CPPFLAGS="-I../include" make
26 * to ensure that your (local) copy of the headers are used. You will
27 * need to modify this further if libsvgtiny is not installed on the
28 * system where you're developing. In addition to the "-I" directive
29 * above, you'll need both
31 * CPPFLAGS="-L/path/to/your/libsvgtiny/build/directory"
34 * to tell your compiler to link against the local libsvgtiny and
37 * Finally, when you want to _run_ the example program using your
38 * local copy of libsvgtiny (whether or not a system copy is
39 * installed), you'll need to set
41 * LD_LIBRARY_PATH=/path/to/your/libsvgtiny/build/directory
43 * The shared-library build directory is platform-specific, but it
44 * should look something like,
46 * build-x86_64-pc-linux-gnu-x86_64-pc-linux-gnu-release-lib-shared
57 #include <sys/types.h>
61 #include <X11/keysym.h>
63 #include <cairo-xlib.h>
67 struct svgtiny_diagram
*diagram
;
69 Window diagram_window
;
70 Atom wm_protocols_atom
, wm_delete_window_atom
;
78 void update_window_title(void);
80 void event_diagram_key_press(XKeyEvent
*key_event
);
81 void event_diagram_expose(const XExposeEvent
*expose_event
);
82 void render_path(cairo_t
*cr
, float scale
, struct svgtiny_shape
*path
);
83 void die(const char *message
);
89 int main(int argc
, char *argv
[])
99 fprintf(stderr
, "Usage: %s FILE\n", argv
[0]);
104 /* load file into memory buffer */
105 fd
= fopen(svg_path
, "rb");
111 if (stat(svg_path
, &sb
)) {
117 buffer
= malloc(size
);
119 fprintf(stderr
, "Unable to allocate %lld bytes\n",
124 n
= fread(buffer
, 1, size
, fd
);
132 /* create svgtiny object */
133 diagram
= svgtiny_create();
135 fprintf(stderr
, "svgtiny_create failed\n");
140 code
= svgtiny_parse(diagram
, buffer
, size
, svg_path
, 1000, 1000);
141 if (code
!= svgtiny_OK
) {
142 fprintf(stderr
, "svgtiny_parse failed: ");
144 case svgtiny_OUT_OF_MEMORY
:
145 fprintf(stderr
, "svgtiny_OUT_OF_MEMORY");
147 case svgtiny_LIBDOM_ERROR
:
148 fprintf(stderr
, "svgtiny_LIBDOM_ERROR");
150 case svgtiny_NOT_SVG
:
151 fprintf(stderr
, "svgtiny_NOT_SVG");
153 case svgtiny_SVG_ERROR
:
154 fprintf(stderr
, "svgtiny_SVG_ERROR: line %i: %s",
156 diagram
->error_message
);
158 case svgtiny_LIBCSS_ERROR
:
159 fprintf(stderr
, "svgtiny_LIBCSS_ERROR");
162 fprintf(stderr
, "unknown svgtiny_code %i", code
);
165 fprintf(stderr
, "\n");
170 /*printf("viewbox 0 0 %u %u\n",
171 diagram->width, diagram->height);*/
180 svgtiny_free(diagram
);
187 * Initialize X11 interface.
191 display
= XOpenDisplay(NULL
);
193 die("XOpenDisplay failed: is DISPLAY set?");
195 diagram_window
= XCreateSimpleWindow(display
,
196 DefaultRootWindow(display
),
197 0, 0, diagram
->width
, diagram
->height
, 0, 0, 0);
199 update_window_title();
201 XMapWindow(display
, diagram_window
);
202 XSelectInput(display
, diagram_window
,
206 StructureNotifyMask
);
208 wm_protocols_atom
= XInternAtom(display
, "WM_PROTOCOLS", False
);
209 wm_delete_window_atom
= XInternAtom(display
, "WM_DELETE_WINDOW", False
);
210 XSetWMProtocols(display
, diagram_window
, &wm_delete_window_atom
, 1);
215 * Free X11 interface.
219 XCloseDisplay(display
);
224 * Update window title to show current state.
226 void update_window_title(void)
232 svg_path_copy
= strdup(svg_path
);
233 if (!svg_path_copy
) {
234 fprintf(stderr
, "out of memory\n");
238 base_name
= basename(svg_path_copy
);
240 snprintf(title
, sizeof title
, "%s (%i%%) - svgtiny",
241 base_name
, (int) roundf(scale
* 100.0));
243 XStoreName(display
, diagram_window
, title
);
250 * Handle an X11 event.
255 XNextEvent(display
, &event
);
257 switch (event
.type
) {
259 if (event
.xkey
.window
== diagram_window
) {
260 event_diagram_key_press(&event
.xkey
);
264 if (event
.xexpose
.window
== diagram_window
) {
265 event_diagram_expose(&event
.xexpose
);
269 if (event
.xclient
.message_type
== wm_protocols_atom
&&
270 event
.xclient
.format
== 32 &&
271 (Atom
) event
.xclient
.data
.l
[0] ==
272 wm_delete_window_atom
)
276 /*printf("unknown event %i\n", event.type);*/
283 * Handle an X11 KeyPress event in the diagram window.
285 void event_diagram_key_press(XKeyEvent
*key_event
)
288 float new_scale
= scale
;
289 unsigned int width
, height
;
291 key_sym
= XLookupKeysym(key_event
, 0);
327 else if (5 < new_scale
)
330 if (new_scale
== scale
)
334 width
= diagram
->width
* scale
;
335 height
= diagram
->height
* scale
;
340 XResizeWindow(display
, diagram_window
, width
, height
);
341 XClearArea(display
, diagram_window
, 0, 0, 0, 0, True
);
342 update_window_title();
347 * Handle an X11 Expose event of the diagram window.
349 void event_diagram_expose(const XExposeEvent
*expose_event
)
351 cairo_surface_t
*surface
;
353 cairo_status_t status
;
356 if (expose_event
->count
!= 0)
359 surface
= cairo_xlib_surface_create(display
, diagram_window
,
360 DefaultVisual(display
, DefaultScreen(display
)),
361 diagram
->width
* scale
, diagram
->height
* scale
);
363 fprintf(stderr
, "cairo_xlib_surface_create failed\n");
367 cr
= cairo_create(surface
);
368 status
= cairo_status(cr
);
369 if (status
!= CAIRO_STATUS_SUCCESS
) {
370 fprintf(stderr
, "cairo_create failed: %s\n",
371 cairo_status_to_string(status
));
373 cairo_surface_destroy(surface
);
377 cairo_set_source_rgba(cr
, 1, 1, 1, 1);
380 for (i
= 0; i
!= diagram
->shape_count
; i
++) {
381 if (diagram
->shape
[i
].path
) {
382 render_path(cr
, scale
, &diagram
->shape
[i
]);
384 } else if (diagram
->shape
[i
].text
) {
385 cairo_set_source_rgba(cr
,
386 svgtiny_RED(diagram
->shape
[i
].stroke
) / 255.0,
387 svgtiny_GREEN(diagram
->shape
[i
].stroke
) / 255.0,
388 svgtiny_BLUE(diagram
->shape
[i
].stroke
) / 255.0,
389 diagram
->shape
[i
].stroke_opacity
);
391 scale
* diagram
->shape
[i
].text_x
,
392 scale
* diagram
->shape
[i
].text_y
);
393 cairo_show_text(cr
, diagram
->shape
[i
].text
);
397 status
= cairo_status(cr
);
398 if (status
!= CAIRO_STATUS_SUCCESS
) {
399 fprintf(stderr
, "cairo error: %s\n",
400 cairo_status_to_string(status
));
402 cairo_surface_destroy(surface
);
407 cairo_surface_destroy(surface
);
412 * Render an svgtiny path using cairo.
414 void render_path(cairo_t
*cr
, float scale
, struct svgtiny_shape
*path
)
419 for (j
= 0; j
!= path
->path_length
; ) {
420 switch ((int) path
->path
[j
]) {
421 case svgtiny_PATH_MOVE
:
423 scale
* path
->path
[j
+ 1],
424 scale
* path
->path
[j
+ 2]);
427 case svgtiny_PATH_CLOSE
:
428 cairo_close_path(cr
);
431 case svgtiny_PATH_LINE
:
433 scale
* path
->path
[j
+ 1],
434 scale
* path
->path
[j
+ 2]);
437 case svgtiny_PATH_BEZIER
:
439 scale
* path
->path
[j
+ 1],
440 scale
* path
->path
[j
+ 2],
441 scale
* path
->path
[j
+ 3],
442 scale
* path
->path
[j
+ 4],
443 scale
* path
->path
[j
+ 5],
444 scale
* path
->path
[j
+ 6]);
452 if (path
->fill
!= svgtiny_TRANSPARENT
) {
453 cairo_set_source_rgba(cr
,
454 svgtiny_RED(path
->fill
) / 255.0,
455 svgtiny_GREEN(path
->fill
) / 255.0,
456 svgtiny_BLUE(path
->fill
) / 255.0,
458 cairo_fill_preserve(cr
);
460 if (path
->stroke
!= svgtiny_TRANSPARENT
) {
461 cairo_set_source_rgba(cr
,
462 svgtiny_RED(path
->stroke
) / 255.0,
463 svgtiny_GREEN(path
->stroke
) / 255.0,
464 svgtiny_BLUE(path
->stroke
) / 255.0,
465 path
->stroke_opacity
);
466 cairo_set_line_width(cr
, scale
* path
->stroke_width
);
467 cairo_stroke_preserve(cr
);
473 * Exit with fatal error.
475 void die(const char *message
)
477 fprintf(stderr
, "%s\n", message
);