Added initial rawfont code. Supports creation of raw and png font textures, plus...
[rawfont.git] / src / rawfont.c
1 #include <cairo.h>
2 #include <stdio.h>
3 #include <math.h>
4 #include <stdbool.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #define SURFACE_WIDTH (256)
9 #define SURFACE_HEIGHT (SURFACE_WIDTH)
10
11 #define CHAR_START ' '
12 #define CHAR_END ('~' + 2)
13
14 void GenerateFontFiles (char const * szFilePrefix, char const * szFontname, int nPoints, bool boItalic, bool boBold, bool boAntialiase);
15
16 int main (int argc, char *argv[])
17 {
18 GenerateFontFiles ("font01", "sans", 12, false, false, true);
19 GenerateFontFiles ("font02", "sans", 20, false, false, true);
20
21 return 0;
22 }
23
24 // "serif", "sans-serif", "cursive", "fantasy", "monospace"
25 void GenerateFontFiles (char const * szFilePrefix, char const * szFontname, int nPoints, bool boItalic, bool boBold, bool boAntialiase) {
26 unsigned char cCharacter;
27 float fXPos;
28 float fYPos;
29 float fMaxHeight;
30 char szPrint[2];
31 int nPos;
32 float fArea;
33 float fDimension;
34 int nDimension;
35 float fPower;
36 int nPower;
37 FILE * fhPositions;
38 FILE * fhData;
39 cairo_font_options_t * psFontOptions;
40 char szAll[(CHAR_END - CHAR_START + 1)];
41 float fDescent;
42 cairo_format_t eFormat = CAIRO_FORMAT_ARGB32;
43 unsigned char * pucData;
44 unsigned char ucAlpha;
45 unsigned char ucColour;
46 float fScaled;
47 cairo_font_slant_t eSlant;
48 cairo_font_weight_t eWeight;
49 char * szFilename;
50 int nPrefixLen;
51
52 nPrefixLen = strlen (szFilePrefix);
53 szFilename = (char *)malloc (nPrefixLen + 5);
54 strncpy (szFilename, szFilePrefix, nPrefixLen);
55
56 eSlant = (boItalic ? CAIRO_FONT_SLANT_ITALIC : CAIRO_FONT_SLANT_NORMAL);
57 eWeight = (boBold ? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);
58
59 // Establish the texture size needed
60 cairo_surface_t * psSurface = cairo_image_surface_create (eFormat, SURFACE_WIDTH, SURFACE_HEIGHT);
61 cairo_t * psContext = cairo_create (psSurface);
62 cairo_text_extents_t sExtents;
63 cairo_font_extents_t sFontExtents;
64
65 // "serif", "sans-serif", "cursive", "fantasy", "monospace"
66 cairo_select_font_face (psContext, szFontname, eSlant, eWeight);
67 cairo_set_font_size (psContext, nPoints);
68 cairo_set_source_rgb (psContext, 1.0, 1.0, 0.0);
69
70 if (!boAntialiase) {
71 psFontOptions = cairo_font_options_create ();
72 // CAIRO_ANTIALIAS_BEST
73 // CAIRO_ANTIALIAS_NONE
74 cairo_font_options_set_antialias (psFontOptions, CAIRO_ANTIALIAS_NONE);
75 //cairo_set_font_options (psContext, psFontOptions);
76 cairo_font_options_destroy (psFontOptions);
77 }
78
79 for (cCharacter = 0; cCharacter < (CHAR_END - CHAR_START); cCharacter++) {
80 szAll[cCharacter] = cCharacter + CHAR_START;
81 }
82 szAll[cCharacter] = 0;
83 cairo_text_extents (psContext, szAll, & sExtents);
84 fArea = sExtents.height * sExtents.width;
85
86 cairo_font_extents (psContext, & sFontExtents);
87 fMaxHeight = sFontExtents.height;
88 fDescent = sFontExtents.descent;
89
90 printf ("Max width: %f\n", sFontExtents.max_x_advance);
91 printf ("Max height: %f\n", fMaxHeight);
92
93 fDimension = sqrt (fArea);
94 nDimension = (fDimension + 1.0f);
95 fPower = ceil (log (fDimension) / log (2.0));
96 nPower = (fPower + 0.5f);
97 //printf ("Power: %d\n", nPower);
98 nDimension = pow (2, nPower);
99 printf ("Dimension: %d x %d\n", nDimension, nDimension);
100
101 cairo_destroy (psContext);
102 cairo_surface_destroy (psSurface);
103
104
105
106 // Recrease the surface but this time with a suitable size
107 psSurface = cairo_image_surface_create (eFormat, nDimension, nDimension);
108 psContext = cairo_create (psSurface);
109
110 cairo_select_font_face (psContext, szFontname, eSlant, eWeight);
111 cairo_set_font_size (psContext, nPoints);
112 cairo_set_source_rgb (psContext, 1.0, 1.0, 1.0);
113
114 if (!boAntialiase) {
115 psFontOptions = cairo_font_options_create ();
116 cairo_font_options_set_antialias (psFontOptions, CAIRO_ANTIALIAS_NONE);
117 //cairo_set_font_options (psContext, psFontOptions);
118 cairo_font_options_destroy (psFontOptions);
119 }
120
121 // Open the CSV file for the character details
122 strncpy (szFilename + nPrefixLen, ".csv", 5);
123 fhPositions = fopen (szFilename, "w");
124
125 // Render the characters to the texture
126 szPrint[1] = 0;
127 fXPos = 0.0f;
128 fYPos = fMaxHeight;
129 for (cCharacter = CHAR_START; cCharacter < CHAR_END; cCharacter++) {
130 szPrint[0] = cCharacter;
131 cairo_text_extents (psContext, szPrint, & sExtents);
132 if ((fXPos + sExtents.x_advance) > nDimension) {
133 fXPos = 0.0f;
134 fYPos += fMaxHeight;
135 }
136
137 cairo_move_to (psContext, fXPos, fYPos - fDescent);
138 cairo_show_text (psContext, szPrint);
139
140 fprintf (fhPositions, "%d, %d, %d, %d\n", (int)fXPos, (int)(fYPos - fMaxHeight), (int)sExtents.x_advance, (int)fMaxHeight);
141
142 fXPos += sExtents.x_advance;
143 fYPos += sExtents.y_advance;
144 }
145
146
147 close (fhPositions);
148
149 //cairo_text_extents (psContext, "Hello, world ", & sExtents);
150 //printf ("X bearing: %f\n", sExtents.x_bearing);
151 //printf ("Y bearing: %f\n", sExtents.y_bearing);
152 //printf ("Width: %f\n", sExtents.width);
153 //printf ("Height: %f\n", sExtents.height);
154 //printf ("X advance: %f\n", sExtents.x_advance);
155 //printf ("Y advance: %f\n", sExtents.y_advance);
156
157 cairo_surface_flush (psSurface);
158
159 // Output the texture as raw
160 pucData = cairo_image_surface_get_data (psSurface);
161 strncpy (szFilename + nPrefixLen, ".raw", 5);
162 fhData = fopen (szFilename, "wb");
163 for (nPos = 0; nPos < (nDimension * nDimension); nPos++) {
164 ucAlpha = pucData[(nPos * 4) + 3];
165
166 if (ucAlpha == 0u) {
167 fputc (0u, fhData);
168 fputc (0u, fhData);
169 fputc (0u, fhData);
170 fputc (0u, fhData);
171 }
172 else {
173 // Convert 'pre-multiplied alpha' to 'post-multiplied alpha'
174
175 // Red
176 ucColour = pucData[(nPos * 4) + 2];
177 fScaled = round (((float)ucColour) / (((float)ucAlpha) / 255.0f));
178 //printf ("R: %f, %u, %u\n", fScaled, ucColour, ucAlpha);
179 fputc (((unsigned char)fScaled), fhData);
180
181 // Green
182 ucColour = pucData[(nPos * 4) + 1];
183 fScaled = round (((float)ucColour) / (((float)ucAlpha) / 255.0f));
184 //printf ("G: %f, %u, %u\n", fScaled, ucColour, ucAlpha);
185 fputc (((unsigned char)fScaled), fhData);
186
187 // Blue
188 ucColour = pucData[(nPos * 4) + 0];
189 fScaled = round (((float)ucColour) / (((float)ucAlpha) / 255.0f));
190 //printf ("B: %f, %u, %u\n", fScaled, ucColour, ucAlpha);
191 fputc (((unsigned char)fScaled), fhData);
192
193 fputc (ucAlpha, fhData);
194 }
195 }
196 close (fhData);
197
198 // Output the texture as a PNG
199 cairo_destroy (psContext);
200 strncpy (szFilename + nPrefixLen, ".png", 5);
201 cairo_surface_write_to_png (psSurface, szFilename);
202 cairo_surface_destroy (psSurface);
203 }
204
205