1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <cairo.h>
21 #include <fontconfig/fontconfig.h>
22 #include <pango/pango.h>
23 #include <pango/pangoft2.h>
24 #include <gdk-pixbuf/gdk-pixbuf.h>
25 #include <lcms2.h>
26 #include <gexiv2/gexiv2.h>
27 #include <gegl.h>
28 
29 #include "libgimpbase/gimpbase.h"
30 
31 #include "sanity.h"
32 
33 #include "gimp-intl.h"
34 
35 
36 /*  early-stage tests  */
37 static gchar * sanity_check_gimp              (void);
38 static gchar * sanity_check_glib              (void);
39 static gchar * sanity_check_cairo             (void);
40 static gchar * sanity_check_pango             (void);
41 static gchar * sanity_check_fontconfig        (void);
42 static gchar * sanity_check_freetype          (void);
43 static gchar * sanity_check_gdk_pixbuf        (void);
44 static gchar * sanity_check_lcms              (void);
45 static gchar * sanity_check_gexiv2            (void);
46 static gchar * sanity_check_babl              (void);
47 static gchar * sanity_check_gegl              (void);
48 static gchar * sanity_check_filename_encoding (void);
49 
50 /*  late-stage tests  */
51 static gchar * sanity_check_gegl_ops          (void);
52 
53 
54 /*  public functions  */
55 
56 /* early-stage sanity check, performed before the call to app_run(). */
57 const gchar *
sanity_check_early(void)58 sanity_check_early (void)
59 {
60   gchar *abort_message = NULL;
61 
62   if (! abort_message)
63     abort_message = sanity_check_gimp ();
64 
65   if (! abort_message)
66     abort_message = sanity_check_glib ();
67 
68   if (! abort_message)
69     abort_message = sanity_check_cairo ();
70 
71   if (! abort_message)
72     abort_message = sanity_check_pango ();
73 
74   if (! abort_message)
75     abort_message = sanity_check_fontconfig ();
76 
77   if (! abort_message)
78     abort_message = sanity_check_freetype ();
79 
80   if (! abort_message)
81     abort_message = sanity_check_gdk_pixbuf ();
82 
83   if (! abort_message)
84     abort_message = sanity_check_lcms ();
85 
86   if (! abort_message)
87     abort_message = sanity_check_gexiv2 ();
88 
89   if (! abort_message)
90     abort_message = sanity_check_babl ();
91 
92   if (! abort_message)
93     abort_message = sanity_check_gegl ();
94 
95   if (! abort_message)
96     abort_message = sanity_check_filename_encoding ();
97 
98   return abort_message;
99 }
100 
101 /* late-stage sanity check, performed during app_run(), after the user
102  * configuration has been loaded.
103  */
104 const gchar *
sanity_check_late(void)105 sanity_check_late (void)
106 {
107   gchar *abort_message = NULL;
108 
109   /* the gegl ops test initializes all gegl ops; in particular, it initializes
110    * all the strings used by their properties, which appear in the ui.  it
111    * must be run after we've called language_init(), potentially overriding
112    * LANGUAGE according to the user config, or else all affected strings would
113    * use the translation corresponding to the system locale, regardless.
114    */
115   if (! abort_message)
116     abort_message = sanity_check_gegl_ops ();
117 
118   return abort_message;
119 }
120 
121 
122 /*  private functions  */
123 
124 
125 /*  early-stage tests  */
126 
127 static gboolean
sanity_check_version(guint major_version,guint required_major,guint minor_version,guint required_minor,guint micro_version,guint required_micro)128 sanity_check_version (guint major_version, guint required_major,
129                       guint minor_version, guint required_minor,
130                       guint micro_version, guint required_micro)
131 {
132   if (major_version > required_major)
133     return TRUE;
134 
135   if (major_version < required_major)
136     return FALSE;
137 
138   if (minor_version > required_minor)
139     return TRUE;
140 
141   if (minor_version < required_minor)
142     return FALSE;
143 
144   if (micro_version >= required_micro)
145     return TRUE;
146 
147   return FALSE;
148 }
149 
150 static gchar *
sanity_check_gimp(void)151 sanity_check_gimp (void)
152 {
153   if (GIMP_MAJOR_VERSION != gimp_major_version ||
154       GIMP_MINOR_VERSION != gimp_minor_version ||
155       GIMP_MICRO_VERSION != gimp_micro_version)
156     {
157       return g_strdup_printf
158         ("Libgimp version mismatch!\n\n"
159          "The GIMP binary cannot run with a libgimp version\n"
160          "other than its own. This is GIMP %d.%d.%d, but the\n"
161          "libgimp version is %d.%d.%d.\n\n"
162          "Maybe you have GIMP versions in both /usr and /usr/local ?",
163          GIMP_MAJOR_VERSION, GIMP_MINOR_VERSION, GIMP_MICRO_VERSION,
164          gimp_major_version, gimp_minor_version, gimp_micro_version);
165     }
166 
167   return NULL;
168 }
169 
170 static gchar *
sanity_check_glib(void)171 sanity_check_glib (void)
172 {
173 #define GLIB_REQUIRED_MAJOR 2
174 #define GLIB_REQUIRED_MINOR 56
175 #define GLIB_REQUIRED_MICRO 2
176 
177   const gchar *mismatch = glib_check_version (GLIB_REQUIRED_MAJOR,
178                                               GLIB_REQUIRED_MINOR,
179                                               GLIB_REQUIRED_MICRO);
180 
181   if (mismatch)
182     {
183       return g_strdup_printf
184         ("%s\n\n"
185          "GIMP requires GLib version %d.%d.%d or later.\n"
186          "Installed GLib version is %d.%d.%d.\n\n"
187          "Somehow you or your software packager managed\n"
188          "to install GIMP with an older GLib version.\n\n"
189          "Please upgrade to GLib version %d.%d.%d or later.",
190          mismatch,
191          GLIB_REQUIRED_MAJOR, GLIB_REQUIRED_MINOR, GLIB_REQUIRED_MICRO,
192          glib_major_version, glib_minor_version, glib_micro_version,
193          GLIB_REQUIRED_MAJOR, GLIB_REQUIRED_MINOR, GLIB_REQUIRED_MICRO);
194     }
195 
196 #undef GLIB_REQUIRED_MAJOR
197 #undef GLIB_REQUIRED_MINOR
198 #undef GLIB_REQUIRED_MICRO
199 
200   return NULL;
201 }
202 
203 static gchar *
sanity_check_cairo(void)204 sanity_check_cairo (void)
205 {
206 #define CAIRO_REQUIRED_MAJOR 1
207 #define CAIRO_REQUIRED_MINOR 12
208 #define CAIRO_REQUIRED_MICRO 2
209 
210   if (cairo_version () < CAIRO_VERSION_ENCODE (CAIRO_REQUIRED_MAJOR,
211                                                CAIRO_REQUIRED_MINOR,
212                                                CAIRO_REQUIRED_MICRO))
213     {
214       return g_strdup_printf
215         ("The Cairo version being used is too old!\n\n"
216          "GIMP requires Cairo version %d.%d.%d or later.\n"
217          "Installed Cairo version is %s.\n\n"
218          "Somehow you or your software packager managed\n"
219          "to install GIMP with an older Cairo version.\n\n"
220          "Please upgrade to Cairo version %d.%d.%d or later.",
221          CAIRO_REQUIRED_MAJOR, CAIRO_REQUIRED_MINOR, CAIRO_REQUIRED_MICRO,
222          cairo_version_string (),
223          CAIRO_REQUIRED_MAJOR, CAIRO_REQUIRED_MINOR, CAIRO_REQUIRED_MICRO);
224     }
225 
226 #undef CAIRO_REQUIRED_MAJOR
227 #undef CAIRO_REQUIRED_MINOR
228 #undef CAIRO_REQUIRED_MICRO
229 
230   return NULL;
231 }
232 
233 static gchar *
sanity_check_pango(void)234 sanity_check_pango (void)
235 {
236 #define PANGO_REQUIRED_MAJOR 1
237 #define PANGO_REQUIRED_MINOR 29
238 #define PANGO_REQUIRED_MICRO 4
239 
240   const gchar *mismatch = pango_version_check (PANGO_REQUIRED_MAJOR,
241                                                PANGO_REQUIRED_MINOR,
242                                                PANGO_REQUIRED_MICRO);
243 
244   if (mismatch)
245     {
246       const gint pango_major_version = pango_version () / 100 / 100;
247       const gint pango_minor_version = pango_version () / 100 % 100;
248       const gint pango_micro_version = pango_version () % 100;
249 
250       return g_strdup_printf
251         ("%s\n\n"
252          "GIMP requires Pango version %d.%d.%d or later.\n"
253          "Installed Pango version is %d.%d.%d.\n\n"
254          "Somehow you or your software packager managed\n"
255          "to install GIMP with an older Pango version.\n\n"
256          "Please upgrade to Pango version %d.%d.%d or later.",
257          mismatch,
258          PANGO_REQUIRED_MAJOR, PANGO_REQUIRED_MINOR, PANGO_REQUIRED_MICRO,
259          pango_major_version, pango_minor_version, pango_micro_version,
260          PANGO_REQUIRED_MAJOR, PANGO_REQUIRED_MINOR, PANGO_REQUIRED_MICRO);
261     }
262 
263 #undef PANGO_REQUIRED_MAJOR
264 #undef PANGO_REQUIRED_MINOR
265 #undef PANGO_REQUIRED_MICRO
266 
267   return NULL;
268 }
269 
270 static gchar *
sanity_check_fontconfig(void)271 sanity_check_fontconfig (void)
272 {
273   const gint fc_version = FcGetVersion ();
274 
275 #define FC_REQUIRED_MAJOR 2
276 #define FC_REQUIRED_MINOR 2
277 #define FC_REQUIRED_MICRO 0
278 
279   if (fc_version < ((FC_REQUIRED_MAJOR * 10000) +
280                     (FC_REQUIRED_MINOR *   100) +
281                     (FC_REQUIRED_MICRO *     1)))
282     {
283       const gint fc_major_version = fc_version / 100 / 100;
284       const gint fc_minor_version = fc_version / 100 % 100;
285       const gint fc_micro_version = fc_version % 100;
286 
287       return g_strdup_printf
288         ("The Fontconfig version being used is too old!\n\n"
289          "GIMP requires Fontconfig version %d.%d.%d or later.\n"
290          "The Fontconfig version loaded by GIMP is %d.%d.%d.\n\n"
291          "This may be caused by another instance of libfontconfig.so.1\n"
292          "being installed in the system, probably in /usr/X11R6/lib.\n"
293          "Please correct the situation or report it to someone who can.",
294          FC_REQUIRED_MAJOR, FC_REQUIRED_MINOR, FC_REQUIRED_MICRO,
295          fc_major_version, fc_minor_version, fc_micro_version);
296     }
297 
298 #undef FC_REQUIRED_MAJOR
299 #undef FC_REQUIRED_MINOR
300 #undef FC_REQUIRED_MICRO
301 
302   return NULL;
303 }
304 
305 static gchar *
sanity_check_freetype(void)306 sanity_check_freetype (void)
307 {
308   FT_Library ft_library;
309   FT_Int     ft_major_version;
310   FT_Int     ft_minor_version;
311   FT_Int     ft_micro_version;
312   FT_Int     ft_version;
313 
314 #define FT_REQUIRED_MAJOR 2
315 #define FT_REQUIRED_MINOR 1
316 #define FT_REQUIRED_MICRO 7
317 
318   if (FT_Init_FreeType (&ft_library) != 0)
319     g_error ("FT_Init_FreeType() failed");
320 
321   FT_Library_Version (ft_library,
322                       &ft_major_version,
323                       &ft_minor_version,
324                       &ft_micro_version);
325 
326   if (FT_Done_FreeType (ft_library) != 0)
327     g_error ("FT_Done_FreeType() failed");
328 
329   ft_version = (ft_major_version * 10000 +
330                 ft_minor_version *   100 +
331                 ft_micro_version *     1);
332 
333   if (ft_version < ((FT_REQUIRED_MAJOR * 10000) +
334                     (FT_REQUIRED_MINOR *   100) +
335                     (FT_REQUIRED_MICRO *     1)))
336     {
337       return g_strdup_printf
338         ("FreeType version too old!\n\n"
339          "GIMP requires FreeType version %d.%d.%d or later.\n"
340          "Installed FreeType version is %d.%d.%d.\n\n"
341          "Somehow you or your software packager managed\n"
342          "to install GIMP with an older FreeType version.\n\n"
343          "Please upgrade to FreeType version %d.%d.%d or later.",
344          FT_REQUIRED_MAJOR, FT_REQUIRED_MINOR, FT_REQUIRED_MICRO,
345          ft_major_version, ft_minor_version, ft_micro_version,
346          FT_REQUIRED_MAJOR, FT_REQUIRED_MINOR, FT_REQUIRED_MICRO);
347     }
348 
349 #undef FT_REQUIRED_MAJOR
350 #undef FT_REQUIRED_MINOR
351 #undef FT_REQUIRED_MICRO
352 
353   return NULL;
354 }
355 
356 static gchar *
sanity_check_gdk_pixbuf(void)357 sanity_check_gdk_pixbuf (void)
358 {
359 #define GDK_PIXBUF_REQUIRED_MAJOR 2
360 #define GDK_PIXBUF_REQUIRED_MINOR 30
361 #define GDK_PIXBUF_REQUIRED_MICRO 8
362 
363   if (! sanity_check_version (gdk_pixbuf_major_version, GDK_PIXBUF_REQUIRED_MAJOR,
364                               gdk_pixbuf_minor_version, GDK_PIXBUF_REQUIRED_MINOR,
365                               gdk_pixbuf_micro_version, GDK_PIXBUF_REQUIRED_MICRO))
366     {
367       return g_strdup_printf
368         ("GdkPixbuf version too old!\n\n"
369          "GIMP requires GdkPixbuf version %d.%d.%d or later.\n"
370          "Installed GdkPixbuf version is %d.%d.%d.\n\n"
371          "Somehow you or your software packager managed\n"
372          "to install GIMP with an older GdkPixbuf version.\n\n"
373          "Please upgrade to GdkPixbuf version %d.%d.%d or later.",
374          GDK_PIXBUF_REQUIRED_MAJOR, GDK_PIXBUF_REQUIRED_MINOR, GDK_PIXBUF_REQUIRED_MICRO,
375          gdk_pixbuf_major_version, gdk_pixbuf_minor_version, gdk_pixbuf_micro_version,
376          GDK_PIXBUF_REQUIRED_MAJOR, GDK_PIXBUF_REQUIRED_MINOR, GDK_PIXBUF_REQUIRED_MICRO);
377     }
378 
379 #undef GDK_PIXBUF_REQUIRED_MAJOR
380 #undef GDK_PIXBUF_REQUIRED_MINOR
381 #undef GDK_PIXBUF_REQUIRED_MICRO
382 
383   return NULL;
384 }
385 
386 static gchar *
sanity_check_lcms(void)387 sanity_check_lcms (void)
388 {
389 #define LCMS_REQUIRED_MAJOR 2
390 #define LCMS_REQUIRED_MINOR 8
391 
392   gint lcms_version = cmsGetEncodedCMMversion ();
393 
394   if (lcms_version < (LCMS_REQUIRED_MAJOR * 1000 +
395                       LCMS_REQUIRED_MINOR * 10))
396     {
397       const gint lcms_major_version = lcms_version / 1000;
398       const gint lcms_minor_version = lcms_version % 1000 / 10;
399 
400       return g_strdup_printf
401         ("Liblcms2 version too old!\n\n"
402          "GIMP requires LittleCMS version %d.%d or later.\n"
403          "Installed LittleCMS version is %d.%d.\n\n"
404          "Somehow you or your software packager managed\n"
405          "to install GIMP with an older LittleCMS version.\n\n"
406          "Please upgrade to LittleCMS version %d.%d or later.",
407          LCMS_REQUIRED_MAJOR, LCMS_REQUIRED_MINOR,
408          lcms_major_version, lcms_minor_version,
409          LCMS_REQUIRED_MAJOR, LCMS_REQUIRED_MINOR);
410     }
411 
412 #undef LCMS_REQUIRED_MAJOR
413 #undef LCMS_REQUIRED_MINOR
414 
415   return NULL;
416 }
417 
418 static gchar *
sanity_check_gexiv2(void)419 sanity_check_gexiv2 (void)
420 {
421 #ifdef GEXIV2_MAJOR_VERSION
422 
423 #define GEXIV2_REQUIRED_MAJOR 0
424 #define GEXIV2_REQUIRED_MINOR 10
425 #define GEXIV2_REQUIRED_MICRO 6
426 
427   gint gexiv2_version = gexiv2_get_version ();
428 
429   if (gexiv2_version < (GEXIV2_REQUIRED_MAJOR * 100 * 100 +
430                         GEXIV2_REQUIRED_MINOR * 100 +
431                         GEXIV2_REQUIRED_MICRO))
432     {
433       const gint gexiv2_major_version = gexiv2_version / 100 / 100;
434       const gint gexiv2_minor_version = gexiv2_version / 100 % 100;
435       const gint gexiv2_micro_version = gexiv2_version % 100;
436 
437       return g_strdup_printf
438         ("gexiv2 version too old!\n\n"
439          "GIMP requires gexiv2 version %d.%d.%d or later.\n"
440          "Installed gexiv2 version is %d.%d.%d.\n\n"
441          "Somehow you or your software packager managed\n"
442          "to install GIMP with an older gexiv2 version.\n\n"
443          "Please upgrade to gexiv2 version %d.%d.%d or later.",
444          GEXIV2_REQUIRED_MAJOR, GEXIV2_REQUIRED_MINOR, GEXIV2_REQUIRED_MICRO,
445          gexiv2_major_version, gexiv2_minor_version, gexiv2_micro_version,
446          GEXIV2_REQUIRED_MAJOR, GEXIV2_REQUIRED_MINOR, GEXIV2_REQUIRED_MICRO);
447     }
448 
449 #undef GEXIV2_REQUIRED_MAJOR
450 #undef GEXIV2_REQUIRED_MINOR
451 #undef GEXIV2_REQUIRED_MICRO
452 
453 #endif
454 
455   return NULL;
456 }
457 
458 static gchar *
sanity_check_babl(void)459 sanity_check_babl (void)
460 {
461   gint babl_major_version;
462   gint babl_minor_version;
463   gint babl_micro_version;
464 
465 #define BABL_REQUIRED_MAJOR 0
466 #define BABL_REQUIRED_MINOR 1
467 #define BABL_REQUIRED_MICRO 78
468 
469   babl_get_version (&babl_major_version,
470                     &babl_minor_version,
471                     &babl_micro_version);
472 
473   if (! sanity_check_version (babl_major_version, BABL_REQUIRED_MAJOR,
474                               babl_minor_version, BABL_REQUIRED_MINOR,
475                               babl_micro_version, BABL_REQUIRED_MICRO))
476     {
477       return g_strdup_printf
478         ("BABL version too old!\n\n"
479          "GIMP requires BABL version %d.%d.%d or later.\n"
480          "Installed BABL version is %d.%d.%d.\n\n"
481          "Somehow you or your software packager managed\n"
482          "to install GIMP with an older BABL version.\n\n"
483          "Please upgrade to BABL version %d.%d.%d or later.",
484          BABL_REQUIRED_MAJOR, BABL_REQUIRED_MINOR, BABL_REQUIRED_MICRO,
485          babl_major_version, babl_minor_version, babl_micro_version,
486          BABL_REQUIRED_MAJOR, BABL_REQUIRED_MINOR, BABL_REQUIRED_MICRO);
487     }
488 
489 #undef BABL_REQUIRED_MAJOR
490 #undef BABL_REQUIRED_MINOR
491 #undef BABL_REQUIRED_MICRO
492 
493   return NULL;
494 }
495 
496 static gchar *
sanity_check_gegl(void)497 sanity_check_gegl (void)
498 {
499   gint gegl_major_version;
500   gint gegl_minor_version;
501   gint gegl_micro_version;
502 
503 #define GEGL_REQUIRED_MAJOR 0
504 #define GEGL_REQUIRED_MINOR 4
505 #define GEGL_REQUIRED_MICRO 34
506 
507   gegl_get_version (&gegl_major_version,
508                     &gegl_minor_version,
509                     &gegl_micro_version);
510 
511   if (! sanity_check_version (gegl_major_version, GEGL_REQUIRED_MAJOR,
512                               gegl_minor_version, GEGL_REQUIRED_MINOR,
513                               gegl_micro_version, GEGL_REQUIRED_MICRO))
514     {
515       return g_strdup_printf
516         ("GEGL version too old!\n\n"
517          "GIMP requires GEGL version %d.%d.%d or later.\n"
518          "Installed GEGL version is %d.%d.%d.\n\n"
519          "Somehow you or your software packager managed\n"
520          "to install GIMP with an older GEGL version.\n\n"
521          "Please upgrade to GEGL version %d.%d.%d or later.",
522          GEGL_REQUIRED_MAJOR, GEGL_REQUIRED_MINOR, GEGL_REQUIRED_MICRO,
523          gegl_major_version, gegl_minor_version, gegl_micro_version,
524          GEGL_REQUIRED_MAJOR, GEGL_REQUIRED_MINOR, GEGL_REQUIRED_MICRO);
525     }
526 
527 #undef GEGL_REQUIRED_MAJOR
528 #undef GEGL_REQUIRED_MINOR
529 #undef GEGL_REQUIRED_MICRO
530 
531   return NULL;
532 }
533 
534 static gchar *
sanity_check_filename_encoding(void)535 sanity_check_filename_encoding (void)
536 {
537   gchar  *result;
538   GError *error = NULL;
539 
540   result = g_filename_to_utf8 ("", -1, NULL, NULL, &error);
541 
542   if (! result)
543     {
544       gchar *msg =
545         g_strdup_printf
546         (_("The configured filename encoding cannot be converted to UTF-8: "
547            "%s\n\n"
548            "Please check the value of the environment variable "
549            "G_FILENAME_ENCODING."),
550          error->message);
551 
552       g_error_free (error);
553 
554       return msg;
555     }
556 
557   g_free (result);
558 
559   result = g_filename_to_utf8 (gimp_directory (), -1, NULL, NULL, &error);
560 
561   if (! result)
562     {
563       gchar *msg =
564         g_strdup_printf
565         (_("The name of the directory holding the GIMP user configuration "
566            "cannot be converted to UTF-8: "
567            "%s\n\n"
568            "Your filesystem probably stores files in an encoding "
569            "other than UTF-8 and you didn't tell GLib about this. "
570            "Please set the environment variable G_FILENAME_ENCODING."),
571          error->message);
572 
573       g_error_free (error);
574 
575       return msg;
576     }
577 
578   g_free (result);
579 
580   return NULL;
581 }
582 
583 
584 /*  late-stage tests  */
585 
586 static gchar *
sanity_check_gegl_ops(void)587 sanity_check_gegl_ops (void)
588 {
589   static const gchar *required_ops[] =
590   {
591     "gegl:alien-map",
592     "gegl:bayer-matrix",
593     "gegl:bloom",
594     "gegl:buffer-sink",
595     "gegl:buffer-source",
596     "gegl:c2g",
597     "gegl:cache",
598     "gegl:cartoon",
599     "gegl:cell-noise",
600     "gegl:checkerboard",
601     "gegl:color",
602     "gegl:color-enhance",
603     "gegl:color-exchange",
604     "gegl:color-rotate",
605     "gegl:color-temperature",
606     "gegl:color-to-alpha",
607     "gegl:component-extract",
608     "gegl:convolution-matrix",
609     "gegl:copy-buffer",
610     "gegl:crop",
611     "gegl:cubism",
612     "gegl:deinterlace",
613     "gegl:difference-of-gaussians",
614     "gegl:diffraction-patterns",
615     "gegl:displace",
616     "gegl:distance-transform",
617     "gegl:dither",
618     "gegl:dropshadow",
619     "gegl:edge",
620     "gegl:edge-laplace",
621     "gegl:edge-neon",
622     "gegl:edge-sobel",
623     "gegl:emboss",
624     "gegl:engrave",
625     "gegl:exposure",
626     "gegl:fattal02",
627     "gegl:focus-blur",
628     "gegl:fractal-trace",
629     "gegl:gaussian-blur",
630     "gegl:gaussian-blur-selective",
631     "gegl:gegl",
632     "gegl:grid",
633     "gegl:high-pass",
634     "gegl:hue-chroma",
635     "gegl:illusion",
636     "gegl:image-gradient",
637     "gegl:invert-gamma",
638     "gegl:invert-linear",
639     "gegl:lens-blur",
640     "gegl:lens-distortion",
641     "gegl:lens-flare",
642     "gegl:linear-sinusoid",
643     "gegl:long-shadow",
644     "gegl:mantiuk06",
645     "gegl:map-absolute",
646     "gegl:map-relative",
647     "gegl:matting-global",
648     "gegl:maze",
649     "gegl:mean-curvature-blur",
650     "gegl:median-blur",
651     "gegl:mirrors",
652     "gegl:mono-mixer",
653     "gegl:mosaic",
654     "gegl:motion-blur-circular",
655     "gegl:motion-blur-linear",
656     "gegl:motion-blur-zoom",
657     "gegl:newsprint",
658     "gegl:noise-cie-lch",
659     "gegl:noise-hsv",
660     "gegl:noise-hurl",
661     "gegl:noise-pick",
662     "gegl:noise-rgb",
663     "gegl:noise-slur",
664     "gegl:noise-solid",
665     "gegl:noise-spread",
666     "gegl:normal-map",
667     "gegl:npd",
668     "gegl:oilify",
669     "gegl:opacity",
670     "gegl:over",
671     "gegl:panorama-projection",
672     "gegl:perlin-noise",
673     "gegl:photocopy",
674     "gegl:pixelize",
675     "gegl:polar-coordinates",
676     "gegl:recursive-transform",
677     "gegl:red-eye-removal",
678     "gegl:reinhard05",
679     "gegl:rgb-clip",
680     "gegl:ripple",
681     "gegl:saturation",
682     "gegl:scale-ratio",
683     "gegl:seamless-clone",
684     "gegl:sepia",
685     "gegl:shadows-highlights",
686     "gegl:shift",
687     "gegl:simplex-noise",
688     "gegl:shift",
689     "gegl:sinus",
690     "gegl:slic",
691     "gegl:snn-mean",
692     "gegl:softglow",
693     "gegl:spherize",
694     "gegl:spiral",
695     "gegl:stereographic-projection",
696     "gegl:stretch-contrast",
697     "gegl:stretch-contrast-hsv",
698     "gegl:stress",
699     "gegl:supernova",
700     "gegl:threshold",
701     "gegl:tile",
702     "gegl:tile-paper",
703     "gegl:tile-glass",
704     "gegl:tile-seamless",
705     "gegl:transform",
706     "gegl:translate",
707     "gegl:unsharp-mask",
708     "gegl:value-invert",
709     "gegl:value-propagate",
710     "gegl:variable-blur",
711     "gegl:video-degradation",
712     "gegl:vignette",
713     "gegl:warp",
714     "gegl:waterpixels",
715     "gegl:wavelet-blur",
716     "gegl:waves",
717     "gegl:whirl-pinch",
718     "gegl:write-buffer"
719   };
720 
721   gint i;
722 
723   for (i = 0; i < G_N_ELEMENTS (required_ops); i++)
724     {
725       if (! gegl_has_operation (required_ops[i]))
726         {
727           return g_strdup_printf
728             ("GEGL operation missing!\n\n"
729              "GIMP requires the GEGL operation \"%s\".\n"
730              "This operation cannot be found. Check your\n"
731              "GEGL install and ensure it has been compiled\n"
732              "with any dependencies required for GIMP.",
733              required_ops [i]);
734         }
735     }
736 
737   return NULL;
738 }
739