Added initial rawfont code. Supports creation of raw and png font textures, plus... master
authorDavid Llewellyn-Jones <david@flypig.co.uk>
Sun, 27 Apr 2014 14:17:04 +0000 (15:17 +0100)
committerDavid Llewellyn-Jones <david@flypig.co.uk>
Sun, 27 Apr 2014 14:17:04 +0000 (15:17 +0100)
build [new file with mode: 0755]
src/rawfont.c [new file with mode: 0644]

diff --git a/build b/build
new file mode 100755 (executable)
index 0000000..0322d49
--- /dev/null
+++ b/build
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+gcc -g -O2 -o rawfont src/rawfont.c $(pkg-config --cflags --libs cairo) -lm
+
diff --git a/src/rawfont.c b/src/rawfont.c
new file mode 100644 (file)
index 0000000..a9e1005
--- /dev/null
@@ -0,0 +1,205 @@
+#include <cairo.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SURFACE_WIDTH (256)
+#define SURFACE_HEIGHT (SURFACE_WIDTH)
+
+#define CHAR_START ' '
+#define CHAR_END ('~' + 2)
+
+void GenerateFontFiles (char const * szFilePrefix, char const * szFontname, int nPoints, bool boItalic, bool boBold, bool boAntialiase);
+
+int main (int argc, char *argv[])
+{
+       GenerateFontFiles ("font01", "sans", 12, false, false, true);
+       GenerateFontFiles ("font02", "sans", 20, false, false, true);
+
+       return 0;
+}
+
+// "serif", "sans-serif", "cursive", "fantasy", "monospace"
+void GenerateFontFiles (char const * szFilePrefix, char const * szFontname, int nPoints, bool boItalic, bool boBold, bool boAntialiase) {
+       unsigned char cCharacter;
+       float fXPos;
+       float fYPos;
+       float fMaxHeight;
+       char szPrint[2];
+       int nPos;
+       float fArea;
+       float fDimension;
+       int nDimension;
+       float fPower;
+       int nPower;
+       FILE * fhPositions;
+       FILE * fhData;
+       cairo_font_options_t * psFontOptions;
+       char szAll[(CHAR_END - CHAR_START + 1)];
+       float fDescent;
+       cairo_format_t eFormat = CAIRO_FORMAT_ARGB32;
+       unsigned char * pucData;
+       unsigned char ucAlpha;
+       unsigned char ucColour;
+       float fScaled;
+       cairo_font_slant_t eSlant;
+       cairo_font_weight_t eWeight;
+       char * szFilename;
+       int nPrefixLen;
+       
+       nPrefixLen = strlen (szFilePrefix);
+       szFilename = (char *)malloc (nPrefixLen + 5);
+       strncpy (szFilename, szFilePrefix, nPrefixLen);
+       
+       eSlant = (boItalic ? CAIRO_FONT_SLANT_ITALIC : CAIRO_FONT_SLANT_NORMAL);
+       eWeight = (boBold ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
+
+       // Establish the texture size needed
+       cairo_surface_t * psSurface = cairo_image_surface_create (eFormat, SURFACE_WIDTH, SURFACE_HEIGHT);
+       cairo_t * psContext = cairo_create (psSurface);
+       cairo_text_extents_t sExtents;
+       cairo_font_extents_t sFontExtents;
+
+       // "serif", "sans-serif", "cursive", "fantasy", "monospace"
+       cairo_select_font_face (psContext, szFontname, eSlant, eWeight);
+       cairo_set_font_size (psContext, nPoints);
+       cairo_set_source_rgb (psContext, 1.0, 1.0, 0.0);
+
+       if (!boAntialiase) {
+               psFontOptions = cairo_font_options_create ();
+               // CAIRO_ANTIALIAS_BEST
+               // CAIRO_ANTIALIAS_NONE
+               cairo_font_options_set_antialias (psFontOptions, CAIRO_ANTIALIAS_NONE);
+               //cairo_set_font_options (psContext, psFontOptions);
+               cairo_font_options_destroy (psFontOptions);
+       }
+
+       for (cCharacter = 0; cCharacter < (CHAR_END - CHAR_START); cCharacter++) {
+               szAll[cCharacter] = cCharacter + CHAR_START;
+       }
+       szAll[cCharacter] = 0;
+       cairo_text_extents (psContext, szAll, & sExtents);
+       fArea = sExtents.height * sExtents.width;
+
+       cairo_font_extents (psContext, & sFontExtents);
+       fMaxHeight = sFontExtents.height;
+       fDescent = sFontExtents.descent;
+
+       printf ("Max width:  %f\n", sFontExtents.max_x_advance);
+       printf ("Max height: %f\n", fMaxHeight);
+
+       fDimension = sqrt (fArea);
+       nDimension = (fDimension + 1.0f);
+       fPower = ceil (log (fDimension) / log (2.0));
+       nPower = (fPower + 0.5f);
+       //printf ("Power: %d\n", nPower);
+       nDimension = pow (2, nPower);
+       printf ("Dimension: %d x %d\n", nDimension, nDimension);
+
+       cairo_destroy (psContext);
+       cairo_surface_destroy (psSurface);
+
+
+
+       // Recrease the surface but this time with a suitable size
+       psSurface = cairo_image_surface_create (eFormat, nDimension, nDimension);
+       psContext = cairo_create (psSurface);
+
+       cairo_select_font_face (psContext, szFontname, eSlant, eWeight);
+       cairo_set_font_size (psContext, nPoints);
+       cairo_set_source_rgb (psContext, 1.0, 1.0, 1.0);
+
+       if (!boAntialiase) {
+               psFontOptions = cairo_font_options_create ();
+               cairo_font_options_set_antialias (psFontOptions, CAIRO_ANTIALIAS_NONE);
+               //cairo_set_font_options (psContext, psFontOptions);
+               cairo_font_options_destroy (psFontOptions);
+       }
+
+       // Open the CSV file for the character details
+       strncpy (szFilename + nPrefixLen, ".csv", 5);
+       fhPositions = fopen (szFilename, "w");
+
+       // Render the characters to the texture
+       szPrint[1] = 0;
+       fXPos = 0.0f;
+       fYPos = fMaxHeight;
+       for (cCharacter = CHAR_START; cCharacter < CHAR_END; cCharacter++) {
+               szPrint[0] = cCharacter;
+               cairo_text_extents (psContext, szPrint, & sExtents);
+               if ((fXPos + sExtents.x_advance) > nDimension) {
+                       fXPos = 0.0f;
+                       fYPos += fMaxHeight;
+               }
+
+               cairo_move_to (psContext, fXPos, fYPos - fDescent);
+               cairo_show_text (psContext, szPrint);
+
+               fprintf (fhPositions, "%d, %d, %d, %d\n", (int)fXPos, (int)(fYPos - fMaxHeight), (int)sExtents.x_advance, (int)fMaxHeight);
+               
+               fXPos += sExtents.x_advance;
+               fYPos += sExtents.y_advance;
+       }
+
+
+       close (fhPositions);
+
+       //cairo_text_extents (psContext, "Hello, world ", & sExtents);
+       //printf ("X bearing: %f\n", sExtents.x_bearing);
+       //printf ("Y bearing: %f\n", sExtents.y_bearing);
+       //printf ("Width: %f\n", sExtents.width);
+       //printf ("Height: %f\n", sExtents.height);
+       //printf ("X advance: %f\n", sExtents.x_advance);
+       //printf ("Y advance: %f\n", sExtents.y_advance);
+
+       cairo_surface_flush (psSurface);
+
+       // Output the texture as raw
+       pucData = cairo_image_surface_get_data (psSurface);
+       strncpy (szFilename + nPrefixLen, ".raw", 5);
+       fhData = fopen (szFilename, "wb");
+       for (nPos = 0; nPos < (nDimension * nDimension); nPos++) {
+               ucAlpha = pucData[(nPos * 4) + 3];
+
+               if (ucAlpha == 0u) {
+                       fputc (0u, fhData);
+                       fputc (0u, fhData);
+                       fputc (0u, fhData);
+                       fputc (0u, fhData);
+               }
+               else {
+                       // Convert 'pre-multiplied alpha' to 'post-multiplied alpha'
+
+                       // Red
+                       ucColour = pucData[(nPos * 4) + 2];
+                       fScaled = round (((float)ucColour) / (((float)ucAlpha) / 255.0f));
+                       //printf ("R: %f, %u, %u\n", fScaled, ucColour, ucAlpha);
+                       fputc (((unsigned char)fScaled), fhData);
+
+                       // Green
+                       ucColour = pucData[(nPos * 4) + 1];
+                       fScaled = round (((float)ucColour) / (((float)ucAlpha) / 255.0f));
+                       //printf ("G: %f, %u, %u\n", fScaled, ucColour, ucAlpha);
+                       fputc (((unsigned char)fScaled), fhData);
+
+                       // Blue
+                       ucColour = pucData[(nPos * 4) + 0];
+                       fScaled = round (((float)ucColour) / (((float)ucAlpha) / 255.0f));
+                       //printf ("B: %f, %u, %u\n", fScaled, ucColour, ucAlpha);
+                       fputc (((unsigned char)fScaled), fhData);
+
+                       fputc (ucAlpha, fhData);
+               }
+       }
+       close (fhData);
+
+       // Output the texture as a PNG
+       cairo_destroy (psContext);
+       strncpy (szFilename + nPrefixLen, ".png", 5);
+       cairo_surface_write_to_png (psSurface, szFilename);
+       cairo_surface_destroy (psSurface);
+}
+
+