On Wed, Jan 7, 2009 at 1:04 AM, Colin D Bennett <co...@gibibit.com> wrote:
> On Tue, 06 Jan 2009 16:18:15 +0200
> Vesa Jääskeläinen <ch...@nic.fi> wrote:
>
>> Bean wrote:
>> > Hi,
>> >
>> > This patch converts existing font to pf2. It uses the freetype2
>> > library, so it can support most common file format, like bdf,
>> > pcf.gz, ttf, etc.
>
> Wow!  Thanks, Bean.  That is great!
>
>> > Usage: grub-mkfont [OPTIONS] FONT_FILES
>> >
>> > Options:
>> >   -o, --output=FILE_NAME    set output file name
>> >   -i, --index=N             set font index
>> >   -n, --name=S              set font name
>> >   -s, --size=N              set font size
>> >   -d, --desc=N              set font descent
>> >   -b, --bold                convert to bold font
>> >   -a, --auto-hint           enable autohint
>> >   --no-bitmap               don't use bitmap glyth
>> >   -h, --help                display this message and exit
>> >   -V, --version             print version information and exit
>> >   -v, --verbose             print verbose message
>>
>> Whoa... that was fast. I hope Colin didn't start yet with his
>> implementation.
>
> Nope, I didn't.  And I guess I won't bother making the Java converter
> build with gcj in the GRUB makefile.

Hi Colin,

BTW, there seems to be some new tags in the pf2 file created by java
converter, perhaps you can update the wiki page sometime ?

The new patch contains small bug fix for the device_width variable.

-- 
Bean
diff --git a/DISTLIST b/DISTLIST
index 22be10b..521aec4 100644
--- a/DISTLIST
+++ b/DISTLIST
@@ -424,6 +424,7 @@ util/grub-fstest.c
 util/grub-mkconfig.in
 util/grub-mkconfig_lib.in
 util/grub-mkdevicemap.c
+util/grub-mkfont.c
 util/grub-pe2elf.c
 util/grub-probe.c
 util/hostdisk.c
diff --git a/Makefile.in b/Makefile.in
index 8cc0f1a..d411b64 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -95,6 +95,8 @@ enable_grub_emu = @enable_grub_emu@
 enable_grub_fstest = @enable_grub_fstest@
 enable_grub_pe2elf = @enable_grub_pe2elf@
 enable_lzo = @enable_lzo@
+freetype_cflags = @freetype_cflags@
+freetype_libs = @freetype_libs@
 
 ### General variables.
 
diff --git a/conf/common.rmk b/conf/common.rmk
index 78a7dc5..45bf7a5 100644
--- a/conf/common.rmk
+++ b/conf/common.rmk
@@ -45,6 +45,12 @@ grub_fstest_SOURCES = util/grub-fstest.c util/hostfs.c 
util/misc.c   \
        disk/mdraid_linux.c disk/dmraid_nvidia.c                        \
        grub_fstest_init.c
 
+# For grub-mkfont.
+bin_UTILITIES += grub-mkfont
+grub_mkfont_SOURCES = util/grub-mkfont.c util/misc.c
+grub_mkfont_CFLAGS = $(freetype_cflags)
+grub_mkfont_LDFLAGS = $(freetype_libs)
+
 # For the parser.
 grub_script.tab.c grub_script.tab.h: normal/parser.y
        $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/normal/parser.y
diff --git a/configure.ac b/configure.ac
index ad6429f..3248ece 100644
--- a/configure.ac
+++ b/configure.ac
@@ -127,6 +127,16 @@ if test "x$YACC" = x; then
   AC_MSG_ERROR([bison is not found])
 fi
 
+AC_CHECK_PROGS([FREETYPE], [freetype-config])
+if test "x$FREETYPE" = x; then
+  AC_MSG_ERROR([freetype-config is not found])
+fi
+
+freetype_cflags=`freetype-config --cflags`
+freetype_libs=`freetype-config --libs`
+AC_SUBST([freetype_cflags])
+AC_SUBST([freetype_libs])
+
 for file in /usr/src/unifont.bdf ; do
   if test -e $file ; then
     AC_SUBST([UNIFONT_BDF], [$file])
diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c
new file mode 100644
index 0000000..9dffeef
--- /dev/null
+++ b/util/grub-mkfont.c
@@ -0,0 +1,497 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008 Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <grub/types.h>
+#include <grub/util/misc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <freetype/ftsynth.h>
+
+#define GRUB_FONT_DEFAULT_SIZE         16
+#define GRUB_FONT_DEFAULT_DESC         2
+
+#define GRUB_FONT_RANGE_BLOCK          1024
+
+struct grub_glyph_info
+{
+  struct grub_glyph_info *next;
+  grub_uint32_t char_code;
+  int width;
+  int height;
+  int x_ofs;
+  int y_ofs;
+  int device_width;
+  int bitmap_size;
+  grub_uint8_t bitmap[0];
+};
+
+#define GRUB_FONT_FLAG_BOLD            1
+#define GRUB_FONT_FLAG_AUTOHINT                2
+#define GRUB_FONT_FLAG_NOBITMAP                4
+
+struct grub_font_info
+{
+  char* name;
+  int style;
+  int desc;
+  int size;
+  int max_width;
+  int max_height;
+  int flags;
+  int num_range;
+  grub_uint32_t *ranges;
+  struct grub_glyph_info *glyph;
+};
+
+static struct option options[] =
+{
+  {"output", required_argument, 0, 'o'},
+  {"name", required_argument, 0, 'n'},
+  {"index", required_argument, 0, 'i'},
+  {"range", required_argument, 0, 'r'},
+  {"size", required_argument, 0, 's'},
+  {"desc", required_argument, 0, 'd'},
+  {"bold", no_argument, 0, 'b'},
+  {"no-bitmap", no_argument, 0, 0x100},
+  {"auto-hint", no_argument, 0, 'a'},
+  {"help", no_argument, 0, 'h'},
+  {"version", no_argument, 0, 'V'},
+  {"verbose", no_argument, 0, 'v'},
+  {0, 0, 0, 0}
+};
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-mkfont --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-mkfont [OPTIONS] FONT_FILES\n\
+\nOptions:\n\
+  -o, --output=FILE_NAME    set output file name\n\
+  -i, --index=N             set font index\n\
+  -r, --range=A-B           set font range\n\
+  -n, --name=S              set font name\n\
+  -s, --size=N              set font size\n\
+  -d, --desc=N              set font descent\n\
+  -b, --bold                convert to bold font\n\
+  -a, --auto-hint           enable autohint\n\
+  --no-bitmap               don't use bitmap glyth\n\
+  -h, --help                display this message and exit\n\
+  -V, --version             print version information and exit\n\
+  -v, --verbose             print verbose messages\n\
+\n\
+Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+void
+add_pixel (grub_uint8_t **data, int *mask, int not_blank)
+{
+  if (*mask == 0)
+    {
+      (*data)++;
+      **data = 0;
+      *mask = 128;
+    }
+
+  if (not_blank)
+    **data |= *mask;
+
+  *mask >>= 1;
+}
+
+void
+add_char (struct grub_font_info *font_info, FT_Face face,
+         grub_uint32_t char_code)
+{
+  struct grub_glyph_info *glyph_info, **p_glyph;
+  int width, height;
+  grub_uint8_t *data;
+  int mask, i, j, bitmap_size;
+  FT_GlyphSlot glyph;
+  int flag = FT_LOAD_RENDER | FT_LOAD_MONOCHROME;
+
+  if (font_info->flags & GRUB_FONT_FLAG_NOBITMAP)
+    flag |= FT_LOAD_NO_BITMAP;
+
+  if (font_info->flags & GRUB_FONT_FLAG_AUTOHINT)
+    flag |= FT_LOAD_FORCE_AUTOHINT;
+  else
+    flag |= FT_LOAD_NO_HINTING;
+
+  if (FT_Load_Char (face, char_code, flag))
+    return;
+
+  glyph = face->glyph;
+
+  if (font_info->flags & GRUB_FONT_FLAG_BOLD)
+    FT_GlyphSlot_Embolden (glyph);
+
+  p_glyph = &font_info->glyph;
+  while ((*p_glyph) && ((*p_glyph)->char_code > char_code))
+    {
+      p_glyph = &(*p_glyph)->next;
+    }
+
+  /* Ignore duplicated glyph.  */
+  if ((*p_glyph) && ((*p_glyph)->char_code == char_code))
+    return;
+
+  width = glyph->bitmap.width;
+  height = glyph->bitmap.rows;
+
+  bitmap_size = ((width * height + 7) / 8);
+  glyph_info = xmalloc (sizeof (struct grub_glyph_info) + bitmap_size);
+  glyph_info->bitmap_size = bitmap_size;
+
+  glyph_info->next = *p_glyph;
+  *p_glyph = glyph_info;
+
+  glyph_info->char_code = char_code;
+  glyph_info->width = width;
+  glyph_info->height = height;
+  glyph_info->x_ofs = glyph->bitmap_left;
+  glyph_info->y_ofs = glyph->bitmap_top - height;
+  glyph_info->device_width = (glyph->advance.x + 63) / 64;
+
+  if (width > font_info->max_width)
+    font_info->max_width = width;
+
+  if (height > font_info->max_height)
+    font_info->max_height = height;
+
+  mask = 0;
+  data = &glyph_info->bitmap[0] - 1;
+  for (j = 0; j < height; j++)
+    for (i = 0; i < width; i++)
+      add_pixel (&data, &mask,
+                glyph->bitmap.buffer[i / 8 + j * glyph->bitmap.pitch] &
+                (1 << (7 - (i & 7))));
+}
+
+void
+add_font (struct grub_font_info *font_info, FT_Face face)
+{
+  if (font_info->num_range)
+    {
+      int i;
+      grub_uint32_t j;
+
+      for (i = 0; i < font_info->num_range; i++)
+       for (j = font_info->ranges[i * 2]; j <= font_info->ranges[i * 2 + 1];
+            j++)
+         add_char (font_info, face, j);
+    }
+  else
+    {
+      grub_uint32_t char_code, glyph_index;
+
+      for (char_code = FT_Get_First_Char (face, &glyph_index);
+          glyph_index;
+          char_code = FT_Get_Next_Char (face, char_code, &glyph_index))
+       add_char (font_info, face, char_code);
+    }
+}
+
+void
+write_font (struct grub_font_info *font_info, char *output_file)
+{
+  FILE *file;
+  grub_uint32_t leng, data;
+  char style_name[20], *font_name;
+  struct grub_glyph_info *cur, *pre;
+  int num, offset;
+
+  file = fopen (output_file, "wb");
+  if (! file)
+    grub_util_error ("Can\'t write to file %s.", output_file);
+
+  offset = 0;
+
+  leng = grub_cpu_to_be32 (4);
+  grub_util_write_image ("FILE", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  grub_util_write_image ("PFF2", 4, file);
+  offset += 12;
+
+  if (! font_info->name)
+    font_info->name = "Unknown";
+
+  if (font_info->flags & GRUB_FONT_FLAG_BOLD)
+    font_info->style |= FT_STYLE_FLAG_BOLD;
+
+  style_name[0] = 0;
+  if (font_info->style & FT_STYLE_FLAG_BOLD)
+    strcpy (style_name, " Bold");
+
+  if (font_info->style & FT_STYLE_FLAG_ITALIC)
+    strcat (style_name, " Italic");
+
+  if (! style_name[0])
+    strcpy (style_name, " Regular");
+
+  asprintf (&font_name, "%s %s %d", font_info->name, &style_name[1],
+           font_info->size);
+
+  leng = grub_cpu_to_be32 (strlen (font_name) + 1);
+  grub_util_write_image ("NAME", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  grub_util_write_image (font_name, grub_be_to_cpu32 (leng), file);
+  offset += 8 + grub_be_to_cpu32 (leng);
+
+  leng = grub_cpu_to_be32 (2);
+  data = grub_cpu_to_be16 (font_info->max_width);
+  grub_util_write_image ("MAXW", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  grub_util_write_image ((char *) &data, 2, file);
+  offset += 10;
+
+  data = grub_cpu_to_be16 (font_info->max_height);
+  grub_util_write_image ("MAXH", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  grub_util_write_image ((char *) &data, 2, file);
+  offset += 10;
+
+  if (! font_info->desc)
+    font_info->desc = GRUB_FONT_DEFAULT_DESC;
+
+  data = grub_cpu_to_be16 (font_info->size - font_info->desc);
+  grub_util_write_image ("ASCE", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  grub_util_write_image ((char *) &data, 2, file);
+  offset += 10;
+
+  data = grub_cpu_to_be16 (font_info->desc);
+  grub_util_write_image ("DESC", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  grub_util_write_image ((char *) &data, 2, file);
+  offset += 10;
+
+  num = 0;
+  pre = 0;
+  cur = font_info->glyph;
+  while (cur)
+    {
+      struct grub_glyph_info *nxt;
+
+      nxt = cur->next;
+      cur->next = pre;
+      pre = cur;
+      cur = nxt;
+      num++;
+    }
+
+  font_info->glyph = pre;
+
+  leng = grub_cpu_to_be32 (num * 9);
+  grub_util_write_image ("CHIX", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+  offset += 8 + num * 9 + 8;
+
+  for (cur = font_info->glyph; cur; cur = cur->next)
+    {
+      data = grub_cpu_to_be32 (cur->char_code);
+      grub_util_write_image ((char *) &data, 4, file);
+      data = 0;
+      grub_util_write_image ((char *) &data, 1, file);
+      data = grub_cpu_to_be32 (offset);
+      grub_util_write_image ((char *) &data, 4, file);
+      offset += 10 + cur->bitmap_size;
+    }
+
+  leng = 0xffffffff;
+  grub_util_write_image ("DATA", 4, file);
+  grub_util_write_image ((char *) &leng, 4, file);
+
+  for (cur = font_info->glyph; cur; cur = cur->next)
+    {
+      data = grub_cpu_to_be16 (cur->width);
+      grub_util_write_image ((char *) &data, 2, file);
+      data = grub_cpu_to_be16 (cur->height);
+      grub_util_write_image ((char *) &data, 2, file);
+      data = grub_cpu_to_be16 (cur->x_ofs);
+      grub_util_write_image ((char *) &data, 2, file);
+      data = grub_cpu_to_be16 (cur->y_ofs);
+      grub_util_write_image ((char *) &data, 2, file);
+      data = grub_cpu_to_be16 (cur->device_width);
+      grub_util_write_image ((char *) &data, 2, file);
+      grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size, file);
+    }
+
+  fclose (file);
+}
+
+int
+main (int argc, char *argv[])
+{
+  struct grub_font_info font_info;
+  FT_Library ft_lib;
+  int font_index = 0;
+  int font_size = 0;
+  char *output_file = NULL;
+
+  memset (&font_info, 0, sizeof (font_info));
+
+  progname = "grub-mkfont";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "bao:n:i:s:d:r:hVv", options, 0);
+
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'b':
+           font_info.flags |= GRUB_FONT_FLAG_BOLD;
+           break;
+
+         case 'a':
+           font_info.flags |= GRUB_FONT_FLAG_AUTOHINT;
+           break;
+
+         case 0x100:
+           font_info.flags |= GRUB_FONT_FLAG_NOBITMAP;
+           break;
+
+         case 'o':
+           output_file = optarg;
+           break;
+
+         case 'n':
+           font_info.name = optarg;
+           break;
+
+         case 'i':
+           font_index = strtoul (optarg, NULL, 0);
+           break;
+
+         case 's':
+           font_size = strtoul (optarg, NULL, 0);
+           break;
+
+         case 'r':
+           {
+             char *p = optarg;
+
+             while (1)
+               {
+                 grub_uint32_t a, b;
+
+                 a = strtoul (p, &p, 0);
+                 if (*p != '-')
+                   grub_util_error ("Invalid font range");
+                 b = strtoul (p + 1, &p, 0);
+                 if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0)
+                   font_info.ranges = xrealloc (font_info.ranges,
+                                                (font_info.num_range +
+                                                 GRUB_FONT_RANGE_BLOCK) *
+                                                sizeof (int) * 2);
+
+                 font_info.ranges[font_info.num_range * 2] = a;
+                 font_info.ranges[font_info.num_range * 2 + 1] = b;
+                 font_info.num_range++;
+
+                 if (*p)
+                   {
+                     if (*p != ',')
+                       grub_util_error ("Invalid font range");
+                     else
+                       p++;
+                   }
+                 else
+                   break;
+               }
+             break;
+           }
+
+         case 'd':
+           font_info.desc = strtoul (optarg, NULL, 0);
+           break;
+
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  if (! output_file)
+    grub_util_error ("No output file is specified.");
+
+  if (FT_Init_FreeType (&ft_lib))
+    grub_util_error ("FT_Init_FreeType fails");
+
+  for (; optind < argc; optind++)
+    {
+      FT_Face ft_face;
+      int size;
+
+      if (FT_New_Face (ft_lib, argv[optind], font_index, &ft_face))
+       {
+         grub_util_info ("Can't open file %s, index %d\n", argv[optind],
+                         font_index);
+         continue;
+       }
+
+      if ((! font_info.name) && (ft_face->family_name))
+       font_info.name = xstrdup (ft_face->family_name);
+
+      size = font_size;
+      if (! size)
+       size = ((ft_face->num_fixed_sizes) ?
+               ft_face->available_sizes[0].height :
+               GRUB_FONT_DEFAULT_SIZE);
+
+      font_info.style = ft_face->style_flags;
+      font_info.size = size;
+
+      FT_Set_Pixel_Sizes (ft_face, size, size);
+      add_font (&font_info, ft_face);
+      FT_Done_Face (ft_face);
+    }
+
+  FT_Done_FreeType (ft_lib);
+
+  write_font (&font_info, output_file);
+
+  return 0;
+}
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to