1 | /* viewer-main.c: Main routine for viewers |
2 | * |
3 | * Copyright (C) 1999,2004,2005 Red Hat, Inc. |
4 | * Copyright (C) 2001 Sun Microsystems |
5 | * Copyright (C) 2006 Behdad Esfahbod |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Library General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2 of the License, or (at your option) any later version. |
11 | * |
12 | * This library is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Library General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Library General Public |
18 | * License along with this library; if not, write to the |
19 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
20 | * Boston, MA 02111-1307, USA. |
21 | */ |
22 | #include "config.h" |
23 | #include <errno.h> |
24 | #include <stdlib.h> |
25 | #include <stdio.h> |
26 | #include <string.h> |
27 | #include <locale.h> |
28 | |
29 | #include <glib.h> |
30 | #include <glib/gstdio.h> |
31 | |
32 | #ifdef G_OS_UNIX |
33 | #include <sys/wait.h> |
34 | #endif |
35 | |
36 | #include "viewer.h" |
37 | #include "viewer-render.h" |
38 | |
39 | int |
40 | main (int argc, |
41 | char **argv) |
42 | { |
43 | const PangoViewer *view; |
44 | gpointer instance; |
45 | PangoContext *context; |
46 | int run; |
47 | int width, height; |
48 | gpointer surface; |
49 | |
50 | g_set_prgname (prgname: "pango-view" ); |
51 | setlocale (LC_ALL, locale: "" ); |
52 | parse_options (argc, argv); |
53 | |
54 | view = opt_viewer; |
55 | |
56 | g_assert (view->id); |
57 | |
58 | instance = view->create (view); |
59 | context = view->get_context (instance); |
60 | width = height = 1; |
61 | surface = view->create_surface (instance, width, height); |
62 | view->render (instance, surface, context, &width, &height, NULL); |
63 | view->destroy_surface (instance, surface); |
64 | surface = view->create_surface (instance, width, height); |
65 | for (run = 0; run < MAX(1,opt_runs); run++) |
66 | view->render (instance, surface, context, &width, &height, NULL); |
67 | |
68 | if (opt_output) |
69 | { |
70 | if (!view->write) |
71 | fail (format: "%s viewer backend does not support writing" , view->name); |
72 | else |
73 | { |
74 | FILE *stream; |
75 | GPid pid = 0; |
76 | |
77 | if (view->write_suffix && g_str_has_suffix (str: opt_output, suffix: view->write_suffix)) |
78 | { |
79 | stream = g_fopen (filename: opt_output, modes: "wb" ); |
80 | if (!stream) |
81 | fail (format: "Cannot open output file %s: %s\n" , |
82 | opt_output, g_strerror (errno)); |
83 | } |
84 | else |
85 | { |
86 | int fd; |
87 | const gchar *convert_argv[5] = {"gm" , "convert" , "-" , "%s" }; |
88 | GError *error; |
89 | |
90 | convert_argv[3] = opt_output; |
91 | |
92 | if (!g_spawn_async_with_pipes (NULL, argv: (gchar **)(void*)convert_argv, NULL, |
93 | flags: G_SPAWN_DO_NOT_REAP_CHILD | |
94 | G_SPAWN_SEARCH_PATH | |
95 | G_SPAWN_STDOUT_TO_DEV_NULL | |
96 | G_SPAWN_STDERR_TO_DEV_NULL, |
97 | NULL, NULL, child_pid: &pid, standard_input: &fd, NULL, NULL, error: &error)) |
98 | fail (format: "When running GraphicsMagick 'gm convert' command: %s\n" , error->message); |
99 | stream = fdopen (fd: fd, modes: "wb" ); |
100 | } |
101 | view->write (instance, surface, stream, width, height); |
102 | fclose (stream: stream); |
103 | #ifdef G_OS_UNIX |
104 | if (pid) |
105 | waitpid (pid: pid, NULL, options: 0); |
106 | #endif |
107 | } |
108 | } |
109 | |
110 | if (opt_display) |
111 | { |
112 | char *title; |
113 | title = get_options_string (); |
114 | |
115 | if (view->display) |
116 | { |
117 | gpointer window = NULL; |
118 | gpointer state = NULL; |
119 | |
120 | if (view->create_window) |
121 | { |
122 | window = view->create_window (instance, title, width, height); |
123 | if (!window) |
124 | goto no_display; |
125 | } |
126 | |
127 | opt_display = FALSE; |
128 | while (1) |
129 | { |
130 | state = view->display (instance, surface, window, width, height, state); |
131 | if (state == GINT_TO_POINTER (-1)) |
132 | break; |
133 | |
134 | view->render (instance, surface, context, &width, &height, state); |
135 | } |
136 | |
137 | if (view->destroy_window) |
138 | view->destroy_window (instance, window); |
139 | } |
140 | no_display: |
141 | |
142 | /* If failed to display natively, call GraphicsMagick */ |
143 | if (opt_display) |
144 | { |
145 | int fd; |
146 | FILE *stream; |
147 | const gchar *display_argv[6] = {"gm" , "display" , "-title" , "%s" , "-" }; |
148 | GError *error = NULL; |
149 | GPid pid; |
150 | |
151 | if (!view->write) |
152 | fail (format: "%s viewer backend does not support displaying or writing" , view->name); |
153 | display_argv[3] = title; |
154 | |
155 | if (!g_spawn_async_with_pipes (NULL, argv: (gchar **)(void*)display_argv, NULL, |
156 | flags: G_SPAWN_DO_NOT_REAP_CHILD | |
157 | G_SPAWN_SEARCH_PATH | |
158 | G_SPAWN_STDOUT_TO_DEV_NULL | |
159 | G_SPAWN_STDERR_TO_DEV_NULL, |
160 | NULL, NULL, child_pid: &pid, standard_input: &fd, NULL, NULL, error: &error)) |
161 | fail (format: "When running GraphicsMagick 'gm display' command: %s\n" , error->message); |
162 | stream = fdopen (fd: fd, modes: "wb" ); |
163 | view->write (instance, surface, stream, width, height); |
164 | fclose (stream: stream); |
165 | #ifdef G_OS_UNIX |
166 | waitpid (pid: pid, NULL, options: 0); |
167 | #endif |
168 | g_spawn_close_pid (pid); |
169 | } |
170 | |
171 | g_free (mem: title); |
172 | } |
173 | |
174 | view->destroy_surface (instance, surface); |
175 | g_object_unref (object: context); |
176 | view->destroy (instance); |
177 | finalize (); |
178 | return 0; |
179 | } |
180 | |