]> git.cworth.org Git - spritext/commitdiff
Initial import of Richard's spritext project
authorCarl Worth <cworth@cworth.org>
Tue, 19 Jun 2007 06:33:50 +0000 (23:33 -0700)
committerCarl Worth <cworth@cworth.org>
Tue, 19 Jun 2007 06:33:50 +0000 (23:33 -0700)
Makefile [new file with mode: 0644]
floor.html [new file with mode: 0644]
spritext.c [new file with mode: 0644]
spritext.html [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..17fc628
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+CFLAGS  = -g -Wall
+
+CFLAGS  += `pkg-config cairo --cflags`
+CFLAGS  += `freetype-config --cflags`
+LDFLAGS += `pkg-config cairo --libs`
+LDFLAGS += `freetype-config --libs`
+
+spritext: spritext.o -lcgic
+
+clean:
+       rm -f *.o spritext
diff --git a/floor.html b/floor.html
new file mode 100644 (file)
index 0000000..411d6f9
--- /dev/null
@@ -0,0 +1,138 @@
+<html>
+<head>
+<title>Dynamic Web 2.0 Button using jQuery</title>
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript" src="jquery.corner.js"></script>
+
+<script type="text/javascript">
+
+var fontInfo = {};
+
+var fontName = "Verdana";
+var fontSize = 12;
+
+function getFontImageUrl() {
+  return '/cgi-bin/spritext.cgi?format=png'
+    + '&fontname=' + fontName
+    + '&fontsize=' + fontSize;
+}
+
+function getFontImage() {
+  var newImg = new Image();
+  newImg.src = getFontImageUrl();
+}
+
+function getFontInfoAndUpdate() {
+  $.getJSON("/cgi-bin/spritext.cgi", { fontname: fontName, fontsize: fontSize, format: "json" }, function(json) {
+    fontInfo = json;
+    updateButton($("#input").val());
+  });
+}
+
+$(function(){
+
+  $("#fontsize").change(function() {
+    fontSize = $("#fontsize").val();
+    getFontImage();
+    getFontInfoAndUpdate();
+  }).change();
+
+//  $("#button").corner("15px");
+
+  $("#input").keyup(function() {
+    updateButton($(this).val());
+  });
+
+});
+
+var SPACE_WIDTH = 25;
+var LETTER_SPACING = 60;
+var widthMap = {A:31,B:32,C:33,D:35,E:32,F:30,G:34,H:35,I:18,J:15,K:32,L:30,M:39,N:35,O:36,P:30,Q:35,R:34,S:31,T:30,U:34,V:31,W:43,X:31,Y:29,Z:31};
+
+function getLetterWidth(letter, fontSize) {
+  return widthMap[letter.toUpperCase()] * 1.5;
+}
+
+function updateButton(text) {
+  var letters = $("#letters");
+  letters.empty();
+  var btnWidth = 0;
+  var letter = 'A';
+  var previous = 'A';
+  for (var i = 0; i < text.length; i++)
+  {
+    letter = text[i];
+    if (letter == ' ')
+    {
+      letters.append($(document.createElement('div'))
+        .css({float: 'left', width: fontSize * 0.5, height: fontSize})
+      );
+    }
+    else
+    {
+//      var className = 'Verdana60';
+      var glyphInfo = fontInfo['u' + letter.charCodeAt(0)];
+//      var xPos = -((letterUC.charCodeAt(0) - "A".charCodeAt(0)) * LETTER_SPACING);
+//      var yPos = -2;
+//      var lWidth = getLetterWidth(letter, 60);
+      var marginLeft = 0;
+      if (letter == 'O')
+        marginLeft = -10;
+      letters.append($(document.createElement('div'))
+        .css({float: 'left',
+              width: glyphInfo.w, height: fontSize,
+             'background': (-glyphInfo.x) + 'px ' + (-glyphInfo.y) + 'px'
+               + ' url(' + getFontImageUrl() + ')'
+               + ' no-repeat',
+             'margin-left': marginLeft
+        })
+      );
+      btnWidth += glyphInfo.w + 1;
+    }
+    previous = letter;
+  }
+
+//  $("#button").width(btnWidth);
+}
+
+</script>
+<style type="text/css">
+
+#letters difev {
+  float: left;
+  height: 100px;
+  background: transparent  no-repeat;
+}
+
+#letters .Verdanavds60 {
+  background: url(http://localhost/cgi-bin/spritext.cgi?fontname=Verdana&fontsize=60);
+}
+
+#letters {
+  width: 600px;
+}
+
+.space {
+  width: 25px;
+}
+
+</style>
+</head>
+<body>
+
+Font Size: <input type="text" id="fontsize" name="fontsize" value="12" />
+
+<div>
+Floor text: <input type="text" id="input" value="Sh"></input>
+</div>
+
+<br>
+
+<div id="letters"></div>
+
+</body>
+</html>
+
diff --git a/spritext.c b/spritext.c
new file mode 100644 (file)
index 0000000..87feeae
--- /dev/null
@@ -0,0 +1,339 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include <cairo.h>
+#include <cairo-ft.h>
+#include <cgic.h>
+#ifndef CAIRO_HAS_PNG_FUNCTIONS
+#error This program requires cairo with PNG support
+#endif
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
+
+#define TRUE (1==1)
+#define FALSE (!TRUE)
+
+static cairo_status_t
+stdio_write (void *closure, const unsigned char *data, unsigned int length);
+
+double
+get_max_width (cairo_t *cr, char *characters);
+
+double
+get_max_height (cairo_t *cr, char *characters);
+
+void
+out_stroke (cairo_t *cr)
+{
+    
+}
+
+int
+cgiMain ()
+{
+    char outputJson = FALSE;
+
+    char characters[] = {
+      '!', '"', '#', '$', '%', '&','\'', '(',
+      ')', '*', '+', ',', '-', '.', '/', '0',
+      '1', '2', '3', '4', '5', '6', '7', '8',
+      '9', ':', ';', '<', '=', '>', '?', '@',
+      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+      'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+      'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+      'Y', 'Z', '[','\\', ']', '^', '_', '`',
+      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+      'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+      'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+      'y', 'z', '{', '|', '}', '~'
+    };
+
+    int i;
+
+    /* QueryString */
+    char fontname[20];
+    int fontsize;
+    char format[5];
+    char fillcolor[20];
+    cgiFormStringNoNewlines("fontname", fontname, 20);
+    cgiFormInteger("fontsize", &fontsize, 50);
+    cgiFormStringNoNewlines("format", format, 5);
+    cgiFormStringNoNewlines("fillcolor", fillcolor, 20);
+
+    int fillcolor_red;
+    int fillcolor_green;
+    int fillcolor_blue;
+    sscanf (fillcolor, " rgb : %d , %d , %d ", &fillcolor_red, &fillcolor_green, &fillcolor_blue);
+
+    if ( format[0] == 'j' && format[1] == 's' && format[2] == 'o' && format[3] == 'n' )
+      outputJson = TRUE;
+
+    if (outputJson)
+    {
+      cgiHeaderContentType("application/json");
+    } else {
+      cgiHeaderContentType("image/png");
+    }
+
+    int error;  
+    FT_Library         library;
+    FT_Face    ft_face;
+    FT_Bool     use_kerning;
+    FT_UInt     left_index, right_index;
+    FT_Vector   kerning;
+
+    error = FT_Init_FreeType( &library );
+    if ( error )
+      printf("error");
+
+    error = FT_New_Face( library,"/srv/rdworth.org/cgi-bin/Verdana.ttf",
+                         0,
+                         &ft_face );
+    if ( error == FT_Err_Unknown_File_Format )
+        printf("File opened. Font format unsupported.");
+    else if ( error )
+        printf("Could not be open or read or broken.");
+
+    use_kerning = FT_HAS_KERNING( ft_face );
+
+    /* Compute max-width and max-height */
+    cairo_surface_t *surface;
+    cairo_t *cr;
+    cairo_font_face_t *cr_face;
+
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                         1, 1);
+
+    cr = cairo_create (surface);
+
+/*
+    cairo_select_font_face (cr, fontname,
+                      CAIRO_FONT_SLANT_NORMAL,
+                      CAIRO_FONT_WEIGHT_NORMAL);
+*/
+    cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
+    cairo_set_font_face (cr, cr_face);
+
+    cairo_set_font_size (cr, fontsize);
+
+    cairo_set_line_width (cr, 1.0);
+
+    double max_width = get_max_width(cr, characters);
+    double max_height = get_max_height(cr, characters);
+
+    cairo_font_face_destroy (cr_face);
+
+    cairo_destroy (cr);
+
+    cairo_surface_destroy(surface);
+
+    /* Draw */
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        (max_width + 8) * 10,
+                                         (max_height + 8) * 10);
+
+    cr = cairo_create (surface);
+
+/*
+    cairo_select_font_face (cr, fontname,
+                      CAIRO_FONT_SLANT_NORMAL,
+                      CAIRO_FONT_WEIGHT_NORMAL);
+*/
+    cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
+    cairo_set_font_face (cr, cr_face);
+
+    cairo_set_font_size (cr, fontsize);
+
+    cairo_text_extents_t extents;
+    double x = 0.0;
+    double y = 0.0;
+
+    if (outputJson)
+      printf("{");
+
+    cairo_translate (cr, 0, -(max_height / 2.50));
+
+//    cairo_translate (cr, 0, -5.0);
+
+    char string[2];
+    string[1] = '\0';
+    for (i = 0; i < ARRAY_SIZE(characters); i++)
+    {
+      if (i % 10 == 0)
+      {
+        x = 0.;
+        y += max_height + 8;
+      }
+      string[0] = characters[i];
+
+      cairo_text_extents (cr, string, &extents);
+
+      if (outputJson)
+      {
+        if (i > 0)
+          printf (",\n");
+        printf ("u%i:{", characters[i]);
+        printf ("x:%.1f,y:%.1f,w:%.1f,h:%.1f",
+                x,
+                y - (max_height * 1.15),
+                extents.width + extents.x_bearing,
+                extents.height);
+        int j;
+        for ( j = 0; j < ARRAY_SIZE(characters); j++ )
+        {
+          right_index = FT_Get_Char_Index( ft_face, characters[i] );
+          left_index = FT_Get_Char_Index( ft_face, characters[j] );
+    
+          FT_Get_Kerning( ft_face, left_index, right_index,
+                          FT_KERNING_UNSCALED, &kerning );
+    
+          if ( kerning.x )
+            printf(",k%d:%d", characters[j], kerning.x);
+        }
+
+        printf ("}");
+      }
+
+      x -= extents.x_bearing;
+  
+      cairo_move_to (cr, x, y);
+      cairo_set_source_rgb (cr, 0., 0., 0.); // black
+      if ( 0 <= fillcolor_red && fillcolor_red <= 255.0
+        && 0 <= fillcolor_green && fillcolor_green <= 255.0
+        && 0 <= fillcolor_blue && fillcolor_blue <= 255.0 )
+        cairo_set_source_rgb (cr, fillcolor_red / 255.0, fillcolor_green / 255.0, fillcolor_blue / 255.0);
+      cairo_text_path (cr, string);
+      cairo_fill (cr);
+
+      x += extents.x_bearing;
+      x += max_width + 8;
+    }
+
+/*
+    int thick_width = 4;
+    int thin_width = 0;
+
+    for (c = 'A'; c <= 'I'; c++)
+    {
+      string[0] = c;
+      int spacing = ((c - 'A') * letterspacing) + 1;
+
+
+      cairo_save(cr);
+
+      cairo_move_to (cr, spacing, 0);
+      cairo_text_path (cr, string);
+//      cairo_set_source_rgb (cr, 0.1, 0.2, 0.2); // gray
+      cairo_set_source_rgb (cr, 0.8, 0.8, 0.85); // silver
+      cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+
+      cairo_push_group (cr);
+      cairo_set_line_width (cr, thick_width);
+      cairo_stroke_preserve (cr);
+      cairo_set_line_width (cr, thin_width);
+      cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+      cairo_stroke_preserve (cr);
+      cairo_fill (cr);
+      cairo_pop_group_to_source (cr);
+
+      cairo_paint (cr);
+
+      cairo_restore(cr);
+
+      cairo_move_to (cr, spacing, 0);
+      cairo_text_path (cr, string);
+      cairo_set_source_rgb (cr, 0.4, 0.45, 0.7); // blue
+
+      cairo_fill (cr);
+    }
+*/
+
+    cairo_scale (cr, 1, -1);
+    cairo_push_group (cr);
+/*
+
+    cairo_pattern_t *gradient;
+
+    for (i = 0; i < 9; i++)
+    {
+      char c[2];
+      strncpy(c, STRING + i, 1);
+      c[1] = '\0';
+      int spacing = (i * letterspacing) + 1;
+      cairo_move_to (cr, spacing, -3);
+      cairo_show_text (cr, c);
+
+    }
+      cairo_pop_group_to_source (cr);
+
+      gradient = cairo_pattern_create_linear (0, 0, 0, -fontsize);
+      cairo_pattern_add_color_stop_rgba (gradient, 0.0, 1, 1, 1, 0.5);
+      cairo_pattern_add_color_stop_rgba (gradient, 0.7, 1, 1, 1, 0.0);
+
+      cairo_mask (cr, gradient);
+
+      cairo_pattern_destroy (gradient);
+*/
+    if (outputJson)
+    {
+      printf("}");
+    } else {
+      cairo_surface_write_to_png_stream (surface, stdio_write, cgiOut);
+    }
+
+    cairo_destroy (cr);
+
+    cairo_surface_destroy (surface);
+
+    return 0;
+}
+
+static cairo_status_t
+stdio_write (void *closure, const unsigned char *data, unsigned int length)
+{
+    FILE *file = closure;
+    if (fwrite (data, 1, length, file) == length)
+       return CAIRO_STATUS_SUCCESS;
+    else
+       return CAIRO_STATUS_WRITE_ERROR;
+}
+
+double
+get_max_width(cairo_t *cr, char *characters)
+{
+  int i;
+  double max_width = 0.;
+  char string[2];
+  string[1] = '\0';
+  for (i = 0; i < ARRAY_SIZE(characters); i++) {
+    cairo_text_extents_t extents;
+    string[0] = characters[i];
+    cairo_text_extents (cr, string, &extents);
+    if ((extents.width + (extents.x_bearing * 2)) > max_width)
+      max_width = extents.width + (extents.x_bearing * 2);
+  }
+  return max_width;
+}
+
+double
+get_max_height(cairo_t *cr, char *characters)
+{
+  int i;
+  double max_height = 0.;
+  char string[2];
+  string[1] = '\0';
+  for (i = 0; i < ARRAY_SIZE(characters); i++) {
+    cairo_text_extents_t extents;
+    string[0] = characters[i];
+    cairo_text_extents (cr, string, &extents);
+//    if ((extents.height - extents.y_bearing) > max_height)
+//      max_height = extents.height - extents.y_bearing;
+    if ((extents.height) > max_height)
+      max_height = extents.height;
+  }
+  return max_height;
+}
+
diff --git a/spritext.html b/spritext.html
new file mode 100644 (file)
index 0000000..bf6c439
--- /dev/null
@@ -0,0 +1,245 @@
+<!DOCTYPE html 
+     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<head>
+<title>spritext</title>
+
+<style type="text/css">
+
+label {
+  margin-right: 10px;
+}
+
+#color {
+  float: left;
+}
+
+.swatch-container {
+  float: left;
+  margin: 4px;
+  padding: 4px;
+}
+
+.swatch-container:hover {
+  margin: 3px;
+  border: 1px dotted #aabbee;
+  background-color: #f3f4f5;
+}
+
+.swatch {
+  cursor: pointer;
+  border: 1px solid gray;
+  width: 25px;
+  height: 25px;
+}
+
+.swatch-container.current {
+  margin: 3px;
+  border: 1px dotted #99aadd;
+  background-color: #e2e3e4;
+}
+
+</style>
+
+<script type="text/javascript" src="jquery.js"></script>
+<script type="text/javascript">
+
+var fontsizes = [10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70];
+
+var fontnames = ["Arial", "Arial Black", 
+"Bitstream Charter",
+"Chandas", "Comic Sans MS", "Courier New",
+"Gentium", "Georgia", 
+"Impact", 
+"Jamrul",
+"Kochi Gothic",
+"MgOpen Canonica", "MgOpen Cosmetica", "MgOpen Modata", 
+"Nimbus Roman No9 L", 
+"Rekha",
+"Samanata", "Sans", "Serif",
+"Times New Roman", "TlwgTypewriter", "Trebuchet MS", "TSCu_Comic", "TSCu_Paranar", 
+"URW Bookman L", "URW Chancery L", "URW Gothic L", "URW Palladio L", 
+"Verdana"];
+
+var colors = ["#EEEEEE", "#FFFFFF", "#F9F7ED", "#FFFF88", "#CDEB8B", "#C3D9FF", "#36393D",
+"#FF1A00", "#CC0000", "#FF7400", "#008C00", "#006E2E", "#4096EE", "#FF0084",
+"#D15600", "#C79810", "#73880A", "#6BBA70", "#3F4C6B", "#356AA0", "#D01F3C"
+];
+
+var cgiUrl = "http://localhost/cgi-bin/spritext.cgi";
+
+var fontInfo = {};
+
+var fontName = "Verdana";
+
+var fontSize = 12;
+
+var options = {fontname:null, fontsize:30};
+
+var fontImageUrl = "http://localhost/cgi-bin/spritext.cgi";
+
+$(function(){
+
+  $("#previewInput").keyup(function() {
+    getFontInfoAndUpdate();
+  }).keyup();
+
+  $(fontsizes).each(function(i) {
+    var option = $(document.createElement('option'));
+    option.val(fontsizes[i]);
+    option.text(fontsizes[i].toString());
+    $("#fontSize").append(option);
+  });
+
+  $(fontnames).each(function(i) {
+    var option = $(document.createElement('option'));
+    option.val(fontnames[i]);
+    option.text(fontnames[i]);
+    $("#fontName").append(option);
+  });
+
+  $(colors).each(function(i) {
+    var swatchContainer = $(document.createElement('div'))
+      .addClass('swatch-container');
+    if (!(i % 7))
+      swatchContainer.css('clear', 'left');
+    var swatch = $(document.createElement('div'))
+      .addClass('swatch')
+      .css({'background-color':colors[i]});
+    swatch.click(function() {
+      $('.current').removeClass('current');
+      var swatch = $(this);
+      swatch.parent().addClass('current');
+      setOption('fillcolor', swatch.css('background-color').replace(/\s/g, ''));
+    });
+    swatchContainer.append(swatch);
+    $("#color").append(swatchContainer);
+  });
+
+  $("#fontSize").change(function() {
+    fontSize = $("#fontSize").val();
+    setOption('fontsize', $("#fontSize").val());
+  });
+
+  $("#fontName").change(function() {
+    setOption('fontname', $("#fontName").val());
+  });
+
+});
+
+function setOption(name, value)
+{
+  options[name] = value;
+  var src = cgiUrl + '?t=t';
+  for ( var property in options )
+  {
+    if (options[property])
+      src += '&' + property + '=' + options[property];
+  }
+  fontImageUrl = src;
+  $("#imgCgi").attr('src', fontImageUrl);
+  getFontInfoAndUpdate();
+}
+
+function getFontInfoAndUpdate() {
+  alert(fontName);
+  alert(fontSize);
+  $.getJSON("/cgi-bin/spritext.cgi", { fontname: fontName, fontsize: fontSize, format: "json" }, function(json) {
+    alert(json.toString());
+    fontInfo = json;
+    updatePreview();
+  });
+}
+
+function updatePreview() {
+  var text = $("#previewInput").val()
+  var letters = $("#letters");
+  letters.empty();
+  var btnWidth = 0;
+  var letter = 'A';
+  var previous = 'A';
+  for (var i = 0; i < text.length; i++)
+  {
+    letter = text[i];
+    if (letter == ' ')
+    {
+      letters.append($(document.createElement('div'))
+        .css({float: 'left', width: fontSize * 0.5, height: fontSize})
+      );
+    }
+    else
+    {
+      var glyphInfo = fontInfo['u' + letter.charCodeAt(0)];
+      if (glyphInfo) {
+        var marginLeft = 0;
+        if (letter == 'O')
+          marginLeft = -10;
+        letters.append($(document.createElement('div'))
+          .css({float: 'left',
+                width: glyphInfo.w, height: fontSize,
+               'background': (-glyphInfo.x) + 'px ' + (-glyphInfo.y) + 'px'
+                 + ' url(' + fontImageUrl + ')'
+                 + ' no-repeat',
+               'margin-left': marginLeft, border:'1px solid green'
+          })
+        );
+        btnWidth += glyphInfo.w + 1;
+      }
+    }
+    previous = letter;
+  }
+}
+
+</script>
+
+</head>
+
+<body>
+
+<fieldset style="float:left;width:350px;">
+<legend>Create Font</legend>
+
+<div>
+<label for="fontSize">Font Size:</label><select id="fontSize"></select>
+</div>
+
+<div>
+<label for="fontName">Font Face:</label><select id="fontName"></select>
+</div>
+
+<div>
+<label>Color:</label>
+<div id="color"></div>
+</div>
+
+</fieldset>
+
+<fieldset style="float:left; width:300px;">
+<legend>Use Font</legend>
+<div>
+Enter text: <input type="text" id="previewInput" value="Spritext"></input>
+</div>
+
+<br>
+
+<div id="preview">
+<div id="letters"></div>
+</div>
+
+</fieldset>
+
+<fieldset style="clear:left;">
+<legend>Preview Font</legend>
+
+<div style="clear:left;">
+<img id="imgCgi" src="http://localhost/cgi-bin/spritext.cgi&fontsize=30" style="padding:1px;border:1px solid black;" />
+</div>
+
+</fieldset>
+
+</body>
+
+</html>
+