Simple Graphics

SimpleGraphics.zip – Public domain C source code for SimpleGraphics library.

When I first started programming in DOS, the languages I used (Modula-2, and C) had basic graphics capabilities. My first C compiler was Microsoft Quick C, it had a graphics library “graph.h”. This provided a few basic primitives for drawing and changing the screen mode into graphics mode. As DOS was a single threaded operating system things were pretty easy. In your main function you could set the video mode to graphics and then draw some shapes with a few lines of code. There were no event loops and callbacks to worry about, and the graphics primitives were very simple.

With Windows (and other modern OSes) things become more difficult and easier at the same time. Doing complex things is easier because there are far more capabilities provided by the system. On the other hand however doing simple things takes longer to setup. With Quick C I could set video mode with one call and then draw a line with another call and my simple program was done. To write a Windows program that just draws one line takes a lot more setup.

I enjoyed playing around with the graphics functions back in the DOS days, and I sometimes feel nostalgic and want to relive some of those moments. I had a look around on the Internet for a very basic graphic library that was cross platform and did not require many dependencies. I wanted to be able to write a simple program that drew shapes with only a few lines of code. Unfortunately I could not find what I was looking for on the Internet. Typically the libraries out there are large and can do all sorts of fancy things. Also I did not find any that had a license I like (I like Public Domain). So I set about writing my own one.

I had the following goals for the library

  1. Must be contained within one single C file and one corresponding H file
  2. Must not required extra modules that do not come standard with a system
  3. Must work for Windows, OSX, and Linux
  4. Needs to provide basic drawing primitives: Lines, simple polygons both filled and non-filled.
  5. Public Domain!

Point 5 is pretty easy, I wrote it so I can do what I want with it and I only like public domain.

Drawing graphics in any system is not my speciality, in fact I have never done it in Windows nor OSX nor Linux before! For Windows I used GDI to do the drawing. I have written Win32 GUI apps before so am familiar with the windows message loop. I found OSX to be difficult because I wanted to write it only using C, and OSX likes to use Objective C as its main interfaces. However, OSX comes with OpenGL and GLUT standard, these have C interfaces. So I wrote the OSX version using OpenGL which I have never used before. I choose to use OpenGL for Linux too because I didn’t want to have to do a third implementation.

OSX has a limitation I found out which is the graphics calls all have to come from the main thread. This messed up my initial implementation design. I wanted the graphics library to create a thread to perform all the graphics functions in the background. So I redesigned it so that instead the main “run” function creates a thread for the main application to continue its work in, and it takes over the main thread. Its not as I would prefer it, and unnecessary for Windows, but I wanted it to be consistent across platforms.

I am quite pleased with the end result, not that it quite is an end result yet. It has been a lot of fun writing it, but the main reason I did it is because of the next thing I want to work on which needs this as base. I am releasing the source code of the library, but with a warning that it should not be consider complete or even stable. As I use it more I will fix it up more, but right now it works for the examples, but it has not been tested particularly well. It doesn’t really handle the window being closed particular well for example.

The following code is an example program which shows how simple it is to use.

////////////////////////////////////////////////////////////////////////////////
//  SimpleGraphicsTest
//
//  Test program for SimpleGraphics
//
//  This is free and unencumbered software released into the public domain
//  July 2013 waterjuice.org
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
//  IMPORTS
////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "LibSimpleGraphics.h"

////////////////////////////////////////////////////////////////////////////////
//  FUNCTIONS
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
//  GraphicsMain
//
//  Graphics function
////////////////////////////////////////////////////////////////////////////////
void
    GraphicsMain
    (
        void*   Unused
    )
{
    char buffer [100];
    char* ptr;
    (void) Unused;

    SgFillRectangle( SgXY(100,100), SgXY(200, 200), SgRGB(250, 200, 0) );
    SgDrawRectangle( SgXY(100,100), SgXY(200, 200), SgRGB(0, 0, 0) );

    SgFillRectangle( SgXY(130, 130), SgXY(135, 135), SgRGB(100, 100, 240) );
    SgDrawRectangle( SgXY(130, 130), SgXY(135, 135), SgRGB(0, 0, 0) );

    SgFillRectangle( SgXY(165, 130), SgXY(170, 135), SgRGB(100, 100, 240) );
    SgDrawRectangle( SgXY(165, 130), SgXY(170, 135), SgRGB(0, 0, 0) );

    SgDrawLine( SgXY(120, 160), SgXY(130, 170), SgRGB(0, 0, 0) );
    SgDrawLine( SgXY(130, 170), SgXY(170, 170), SgRGB(0, 0, 0) );
    SgDrawLine( SgXY(170, 170), SgXY(180, 160), SgRGB(0, 0, 0) );

    // Wait for user to press enter before returning and closing window
    ptr = fgets( buffer, sizeof(buffer), stdin );
    (void)ptr;
}

////////////////////////////////////////////////////////////////////////////////
//  main
//
//  Entry point
////////////////////////////////////////////////////////////////////////////////
int
    main
    (
        void
    )
{
    SimpleGraphicsRun( 300, 300, "Hello World", GraphicsMain, 0 );

    return 0;
}

The function SimpleGraphicsRun needs to be run from the main thread (because of OSX requirements). The first 2 parameters are the window size, the third is the window title, the fourth is the function where execution will continue, the final parameter is a context pointer that is passed to the function specified before. SimpleGraphicsRun will create the window and create a new thread which is passed to the specified function. When that function returns the window will be closed.

The results of the above example are:

Example1_Windows-280x300.png
Windows

Example1_OSX-281x300.png

OSX

Example1_Linux-275x300.png

Linux (Ubuntu)

The results look the same in all three platforms. Goal achieved!

A fancier example:

example2

With this example I put delays into the drawing so that it looked more interesting.

SimpleGraphics.zip – This has the C source code for the SimpleGraphics library and the example code for the above two examples. SimpleGraphics is a cross platform very basic graphics library using GDI and OpenGL. The zip file also contains compiled binaries for Windows, OSX, and Linux. This is free and unencumbered software released into the public domain.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s