From 01a1d1cdaaed1e50ff9f0bcd1152c2a5d43ad61a Mon Sep 17 00:00:00 2001 From: David Llewellyn-Jones Date: Sun, 27 Apr 2014 15:17:04 +0100 Subject: [PATCH 1/1] Added initial rawfont code. Supports creation of raw and png font textures, plus character positioning csv. --- build | 4 + src/rawfont.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100755 build create mode 100644 src/rawfont.c diff --git a/build b/build new file mode 100755 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 index 0000000..a9e1005 --- /dev/null +++ b/src/rawfont.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include + +#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); +} + + -- 2.25.1