In this post I will be talking about P0267R0: A Proposal to Add 2D Graphics Rendering and Display to C++. This proposal will be discussed next week at the next ISO C++ Standardization meeting in Jacksonville.

P0267R0 comes out of C++’s SG13 HMI: Development of new proposals in selected human-machine interaction such as low-level graphics/pointing I/O primitives.

SG13 was created by Herb Sutter after the One C++ keynote talk he gave at GoingNative 2013.

Personal history

I started programming twenty years ago in high school. Back then I didn’t even have my own computer Below you have the cover of the book that was used to teach us Turbo Pascal:

Please notice the graphics on the book’s cover. That drawing was presented as an example in the book by the means of Borland Graphics Interface (BGI).

A couple of years ago I had to port a car navigation engine to an Unix-like operating system. The target computer had support for OpenGL ES, the navigation engine could display images on the map, but none of them came with a 2D graphics engine.

I ended up porting Cairo Graphics just to render some text into PNG images, and to rotate a car image on the map.

N3888

SG13 also used Cairo Graphics as base for their first proposal - N3888. In the meantime the proposal matured as P0267R0, and the API has changed a bit.

Fork

The reference implementation has been done by Michael B. McLaughlin - MVP Microsoft.

The implementation has Visual C++ project files with pre-compiled binaries for Windows, and autotools support for Linux. This is due to the fact that Cairo Graphics comes from Linux world and they provide a makefile to compile on Windows. Michael McLaughlin has documented his work to build Cairo Graphics for Windows. Shiver.

Luckily there is a tool for cross platform C++ project building – CMake! This week I added CMake support for the reference implementation, see my fork at github: https://github.com/cristianadam/io2d.

Hello World

As it turns out the application code Michael B. McLaughlin used to test the implementation doesn’t compile out of the box. So I decided to write a simple “Hello World” application.

I had a look at the minimal C program using Cairo and decided to do the same with io2d. In the example the “Hello World” string is being rendered with a blue brush and saved as a PNG graphics file.

io2d doesn’t have support for PNG graphics files, or other graphics file format for that matter. So I had to come up with something easy. I choose the TGA file format, because one just has to write a 18 bytes header and then dump the raw image bytes. And no, BMP file format is not easy

#include <io2d.h> #include <fstream> #include "tga_header.h" namespace io2d = std::experimental::io2d; void save_surface_to_tga_file(io2d::image_surface& surface, std:: string const & fileName) { tga::header tga_header; tga_header.image_type = tga::image_type::true_color; tga_header.image_spec.width = surface.width(); tga_header.image_spec.height = surface.height(); tga_header.image_spec.depth = 32 ; tga_header.image_spec.descriptor.top = 1 ; std::ofstream ofs(fileName, std::ofstream::binary); ofs.write( reinterpret_cast < const char *>(&tga_header), sizeof (tga_header)); auto bytes = surface.data(); ofs.write( reinterpret_cast < const char *>(&bytes[ 0 ]), bytes.size()); } int main () { io2d::image_surface image(io2d::format::argb32, 240 , 80 ); io2d::simple_font_face consolas( " Consolas " , io2d::font_slant::normal, io2d::font_weight::bold); image.font_face(consolas); image.font_size( 3 2 .0 ); io2d::brush cyan(io2d::rgba_color::cyan()); image.brush(cyan); image.render_text( " Hello World " , { 2 0 .0 , 5 0 .0 }); save_surface_to_tga_file(image, " hello.tga " ); }

The code used to save the TGA file is bigger than the code used to render the image

tga_header.h contains the code found at this StackOverflow question. Thank you Brandon!

The CMakeLists.txt file looks like this:

cmake_minimum_required(VERSION 2.8.12) project(hello CXX) add_executable(hello hello.cpp) target_link_libraries(hello ${IO2D_LIBRARY}) target_include_directories(hello PRIVATE ${IO2D_INCLUDE_DIR}) if (WIN32) target_compile_definitions(hello PRIVATE CAIRO_WIN32_STATIC_BUILD _WIN32_WINNT=0x0600) endif()

After running hello.exe I ended up with hello.tga which looks like this when opened with The GIMP:

It worked!

C++17?

From Michael Wong’s blog post: C++17 content (a prediction) we can see that Graphics TS is not meant to be included in C++17

I really do hope that SG13’s Graphics TS will be part of C++ sooner than later, because graphics programming is so much fun!