Squashed 'libs/EXTERNAL/libezgl/' changes from fdc2113..172bcb4

172bcb4 Merge pull request #4 from mariobadr/save_pdf
c27f7d8 Fix canvas.cpp format
ad15c2d remove create_and_generate_X functions, directly calling cairo functions in pint_X functions
6fb7c27 Merge pull request #9 from kmurray/non_root_build_fix
86fbdbb Merge pull request #10 from kmurray/bump_example_cmake_version
a04d2c8 Bump CMake version for example program
19b2118 Fix non-root project variable condition
59ad0ff Merge pull request #8 from kmurray/non_primary_project_build
b9a057b Merge pull request #7 from kmurray/system_includes
98fe682 Merge pull request #6 from kmurray/bump_cmake_version
25a1b15 add print_pdf, print_png, print_svg functions to canvas.cpp, tested in basic_application.cpp
ad47d5a add print_pdf function to canvas.cpp to wrap up pdf functions, still testing
a65dd9f Do not build examples by default if EZGL is non-root cmake project
77cbb92 Treat GTK/X11 as system includes
4376ef2 Bump CMake version to 3.9
2ded816 add comments for pdf, png, svg functions
f848de3 add feature to generate pdf, png, and svg, finish testing
4dedc61 vpr: include cairo files for generating pdf and svg
29116ad add create surface functions for pdf, png, and svg in canvas.cpp

git-subtree-dir: libs/EXTERNAL/libezgl
git-subtree-split: 172bcb4b69d5009e10ea6c1f1df5cee6536f5aba
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8b157e7..164887e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,4 @@
-# require at least CMake version 3.0.2
-cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
 
 # create the project
 project(
@@ -21,6 +20,12 @@
 # a set of macros has been developed by Makman2 on GitHub to help with this
 list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gcr-cmake/macros)
 
+#Is ezgl the root cmake project?
+set(IS_ROOT_PROJECT TRUE)
+if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
+    set(IS_ROOT_PROJECT FALSE)
+endif()
+
 # include the configuration/compile time options for this library
 include(options.cmake)
 
@@ -47,6 +52,13 @@
 target_include_directories(
   ${PROJECT_NAME}
   PUBLIC include
+)
+
+#Treat GTK/X11 headers as system headers so they
+#do not generate compilation warnings
+target_include_directories(
+  ${PROJECT_NAME}
+  SYSTEM
   PUBLIC ${GTK3_INCLUDE_DIRS}
   PUBLIC ${X11_INCLUDE_DIRS}
 )
diff --git a/examples/basic-application/CMakeLists.txt b/examples/basic-application/CMakeLists.txt
index 4b8c8b0..42d1c0e 100644
--- a/examples/basic-application/CMakeLists.txt
+++ b/examples/basic-application/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
 
 project(
   basic-application
diff --git a/examples/basic-application/basic_application.cpp b/examples/basic-application/basic_application.cpp
index 7299e0d..11071b0 100644
--- a/examples/basic-application/basic_application.cpp
+++ b/examples/basic-application/basic_application.cpp
@@ -25,8 +25,6 @@
 #include "ezgl/application.hpp"
 #include "ezgl/graphics.hpp"
 
-#include <iostream>
-
 // Callback functions for event handling
 void act_on_mouse_press(ezgl::application *application, GdkEventButton *event, double x, double y);
 void act_on_mouse_move(ezgl::application *application, GdkEventButton *event, double x, double y);
@@ -537,7 +535,7 @@
 {
   // Update the status bar message
   application->update_message("Test Button Pressed");
-
+  
   // Redraw the main canvas
   application->refresh_drawing();
 
diff --git a/include/ezgl/canvas.hpp b/include/ezgl/canvas.hpp
index 58f0ce2..2b03102 100644
--- a/include/ezgl/canvas.hpp
+++ b/include/ezgl/canvas.hpp
@@ -25,6 +25,8 @@
 #include "ezgl/color.hpp"
 
 #include <cairo.h>
+#include <cairo-pdf.h>
+#include <cairo-svg.h>
 #include <gtk/gtk.h>
 
 #include <string>
@@ -103,7 +105,20 @@
    * The created renderer should be used only in the same callback in which it was created
    */
   renderer create_temporary_renderer();
-
+  
+  /**
+   * print_pdf, print_svg, and print_png generate a PDF, SVG, or PNG output file showing 
+   * all the graphical content of the current canvas. 
+   * 
+   * @param file_name   name of the output file
+   * @return            returns true if the function has successfully generated the output file, otherwise
+   *                    failed due to errors such as out of memory occurs. 
+   */
+  bool print_pdf(const char *file_name);
+  bool print_svg(const char *file_name);
+  bool print_png(const char *file_name);
+  
+  
 protected:
   // Only the ezgl::application can create and initialize a canvas object.
   friend class application;
diff --git a/options.cmake b/options.cmake
index d8cd220..59f85db 100644
--- a/options.cmake
+++ b/options.cmake
@@ -1,7 +1,7 @@
 option(
   EZGL_BUILD_EXAMPLES
   "Build the EZGL example executables."
-  ON
+  ${IS_ROOT_PROJECT} #Only build examples by default if EZGL is the root cmake project
 )
 
 option(
diff --git a/src/canvas.cpp b/src/canvas.cpp
index 6ad3916..0b19732 100644
--- a/src/canvas.cpp
+++ b/src/canvas.cpp
@@ -56,6 +56,98 @@
   return context;
 }
 
+bool canvas::print_pdf(const char *file_name)
+{
+  cairo_surface_t *surface;
+  cairo_t *context;
+
+  // create pdf surface based on canvas size
+  int const width = gtk_widget_get_allocated_width(m_drawing_area);
+  int const height = gtk_widget_get_allocated_height(m_drawing_area);
+  surface = cairo_pdf_surface_create(file_name, width, height);
+
+  if(surface == NULL)
+    return false; // failed to create due to errors such as out of memory
+  context = create_context(surface);
+
+  // draw on the newly created pdf surface & context
+  cairo_set_source_rgb(context, m_background_color.red / 255.0, m_background_color.green / 255.0,
+      m_background_color.blue / 255.0);
+  cairo_paint(context);
+
+  using namespace std::placeholders;
+  renderer g(context, std::bind(&camera::world_to_screen, m_camera, _1), &m_camera, surface);
+  m_draw_callback(g);
+
+  // free surface & context
+  cairo_surface_destroy(surface);
+  cairo_destroy(context);
+
+  return true;
+}
+
+bool canvas::print_svg(const char *file_name)
+{
+  cairo_surface_t *surface;
+  cairo_t *context;
+
+  // create svg surface based on canvas size
+  int const width = gtk_widget_get_allocated_width(m_drawing_area);
+  int const height = gtk_widget_get_allocated_height(m_drawing_area);
+  surface = cairo_svg_surface_create(file_name, width, height);
+
+  if(surface == NULL)
+    return false; // failed to create due to errors such as out of memory
+  context = create_context(surface);
+
+  // draw on the newly created svg surface & context
+  cairo_set_source_rgb(context, m_background_color.red / 255.0, m_background_color.green / 255.0,
+      m_background_color.blue / 255.0);
+  cairo_paint(context);
+
+  using namespace std::placeholders;
+  renderer g(context, std::bind(&camera::world_to_screen, m_camera, _1), &m_camera, surface);
+  m_draw_callback(g);
+
+  // free surface & context
+  cairo_surface_destroy(surface);
+  cairo_destroy(context);
+
+  return true;
+}
+
+bool canvas::print_png(const char *file_name)
+{
+  cairo_surface_t *surface;
+  cairo_t *context;
+
+  // create png surface based on canvas size
+  int const width = gtk_widget_get_allocated_width(m_drawing_area);
+  int const height = gtk_widget_get_allocated_height(m_drawing_area);
+  surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+
+  if(surface == NULL)
+    return false; // failed to create due to errors such as out of memory
+  context = create_context(surface);
+
+  // draw on the newly created png surface & context
+  cairo_set_source_rgb(context, m_background_color.red / 255.0, m_background_color.green / 255.0,
+      m_background_color.blue / 255.0);
+  cairo_paint(context);
+  using namespace std::placeholders;
+  renderer g(context, std::bind(&camera::world_to_screen, m_camera, _1), &m_camera, surface);
+  m_draw_callback(g);
+
+  // create png output file
+  cairo_surface_write_to_png(surface, file_name);
+
+  // free surface & context
+  cairo_surface_destroy(surface);
+  cairo_destroy(context);
+
+  return true;
+}
+
 gboolean canvas::configure_event(GtkWidget *widget, GdkEventConfigure *, gpointer data)
 {
   // User data should have been set during the signal connection.
@@ -101,9 +193,14 @@
   return FALSE;
 }
 
-canvas::canvas(std::string canvas_id, draw_canvas_fn draw_callback, rectangle coordinate_system, color background_color)
-    : m_canvas_id(std::move(canvas_id)), m_draw_callback(draw_callback), m_camera(coordinate_system),
-      m_background_color(background_color)
+canvas::canvas(std::string canvas_id,
+    draw_canvas_fn draw_callback,
+    rectangle coordinate_system,
+    color background_color)
+    : m_canvas_id(std::move(canvas_id))
+    , m_draw_callback(draw_callback)
+    , m_camera(coordinate_system)
+    , m_background_color(background_color)
 {
 }
 
@@ -157,8 +254,8 @@
 void canvas::redraw()
 {
   // Clear the screen and set the background color
-  cairo_set_source_rgb(m_context, m_background_color.red / 255.0,
-		       m_background_color.green / 255.0, m_background_color.blue / 255.0);
+  cairo_set_source_rgb(m_context, m_background_color.red / 255.0, m_background_color.green / 255.0,
+      m_background_color.blue / 255.0);
   cairo_paint(m_context);
 
   using namespace std::placeholders;
@@ -177,4 +274,4 @@
 
   return g;
 }
-}
+} // namespace ezgl