[GRASS-dev] [bug #5390] (grass) make GRASS fonts not endian-specific

this bug's URL: http://intevation.de/rt/webrt?serial_num=5390
-------------------------------------------------------------------------

Subject: make GRASS fonts not endian-specific

&ncharsPlatform: Mac OSX
grass obtained from: CVS
grass binary for platform: Compiled from Sources
GRASS Version: 6.3.CVS.20061202

This is mainly concerned with Mac OS X, but can be applied to all platforms. The problem is a OS X
universal binary, that has combined binaries for both PPC and Intel Macs. The font files are built at
compile time for the architecture they are built on, and thus can't be used on the other arch.

I suggest picking one arch, or endian, for the font files on all platforms. These patches are little-
endian, since that's the arch I build on.

First, during compilation, the lib/fonts target must build the fonts for one arch, and byte swap the
output if on the opposite platform (I took the byte-swapping from the nad loading code in PROJ).
This patch is for lib/fonts/for_grass/splitfont.c:

--- /Users/Shared/src/GRASS/grass-6.3.cvs_src_snapshot_2006_12_02-xcode/lib/fonts/for_grass/
splitfont.c 2006-11-10 23:20:06.000000000 -0600
+++ splitfont.c 2006-12-08 12:58:23.000000000 -0600
@@ -5,6 +5,10 @@
#include <stdlib.h>
#include "local_proto.h"

+static int byte_order_test = 1;
+#define IS_LSB (((unsigned char *) (&byte_order_test))[0] == 1)
+static void swap_words( unsigned char *data, int word_size, int word_count );
+
int main (int argc, char **argv)
{
   int achar ;
@@ -16,6 +20,8 @@
   long newchars ;
   long offset;
   long newoffset;
+ long newchars_lsb = newchars;
+ long newoffset_lsb = newoffset;
   long *index;
   int size;
   int i;
@@ -68,7 +74,13 @@
     }
     /* save space for font index */
     newoffset = 0 ;
- write(newfont, &newoffset, sizeof newoffset) ;
+ if(!IS_LSB)
+ {
+ long templong = newoffset;
+ swap_words((unsigned char *) templong, sizeof(long), 1);
+ write(newfont, &templong, sizeof templong) ;
+ } else
+ write(newfont, &newoffset, sizeof newoffset) ;

     newchars = 0 ;
     
@@ -108,10 +120,21 @@
       }
     }
     newoffset = lseek (newfont, 0L, 1);
- write (newfont, &newchars, sizeof(newchars));
+ if(!IS_LSB)
+ {
+ swap_words((unsigned char *) newchars_lsb, sizeof(newchars_lsb), 1);
+ swap_words((unsigned char *) newoffset_lsb, sizeof(newoffset_lsb), 1);
+ write (newfont, &newchars_lsb, sizeof(newchars_lsb));
+ swap_words((unsigned char *) newmap, sizeof(long), newchars);
+ }
+ else
+ write (newfont, &newchars, sizeof(newchars));
     write (newfont, newmap, newchars * sizeof (*newmap));
     lseek (newfont, 0L, 0);
- write (newfont, &newoffset, sizeof(newoffset));
+ if(!IS_LSB)
+ write (newfont, &newoffset_lsb, sizeof newoffset_lsb);
+ else
+ write (newfont, &newoffset, sizeof(newoffset));
     close (newfont);
   }

@@ -127,11 +150,40 @@

     read ( font, &n, sizeof n);
- write (newfont, &n, sizeof n);
     read ( font, X, n);
- write (newfont, X, n);
     read ( font, Y, n);
+ if(!IS_LSB)
+ {
+ int tempint = n;
+ swap_words((unsigned char *) tempint, sizeof(int), 1);
+ write (newfont, &tempint, sizeof(tempint));
+ } else
+ write (newfont, &n, sizeof n);
+ write (newfont, X, n);
     write (newfont, Y, n);

     return 0;
}
+
+/* assume fonts written LSB, byte-swap on big-end */
+
+static void swap_words( unsigned char *data, int word_size, int word_count )
+{
+ int word;
+
+ for( word = 0; word < word_count; word++ )
+ {
+ int i;
+
+ for( i = 0; i < word_size/2; i++ )
+ {
+ int t;
+
+ t = data[i];
+ data[i] = data[word_size-i-1];
+ data[word_size-i-1] = t;
+ }
+ data += word_size;
+ }
+}
+

Then, lib/driver/font2.c needs to always read this arch:

--- font2.c 2006-06-01 12:40:22.000000000 -0500
+++ font2.c.new 2006-08-26 10:54:28.000000000 -0500
@@ -11,6 +11,31 @@
static unsigned char *font;
static int first = 1;

+/* assume fonts written LSB, byte-swap on big-end */
+
+static int byte_order_test = 1;
+#define IS_LSB (((unsigned char *) (&byte_order_test))[0] == 1)
+
+static void swap_words( unsigned char *data, int word_size, int word_count )
+{
+ int word;
+
+ for( word = 0; word < word_count; word++ )
+ {
+ int i;
+
+ for( i = 0; i < word_size/2; i++ )
+ {
+ int t;
+
+ t = data[i];
+ data[i] = data[word_size-i-1];
+ data[word_size-i-1] = t;
+ }
+ data += word_size;
+ }
+}
+
int font_init(const char *filename)
{
   int file, size;
@@ -29,6 +54,8 @@

   /* First record: an offset to the number of character in the font. */
   read(file, &offset, sizeof(offset));
+ if( ! IS_LSB )
+ swap_words(&offset, sizeof(offset), 1);

   /* Read entire font into memory */
   lseek(file, 0L, 0);
@@ -43,6 +70,8 @@
   /* Read font index into memory */
   lseek(file, offset, 0);
   read(file, &nchars, sizeof nchars);
+ if( ! IS_LSB )
+ swap_words(, sizeof(nchars), 1);
   size = nchars * sizeof(*findex);

   if(findex)
@@ -51,6 +80,20 @@
   if (read(file, findex, size) != size)
     G_fatal_error("can't read findex!");

+ /* now byte-swap index and sizes, if needed */
+ if( ! IS_LSB )
+ {
+ int i;
+ unsigned char *work_point;
+
+ swap_words((unsigned char *) findex, sizeof(long), nchars);
+ for( i = 0; i < nchars; i++ )
+ {
+ work_point = font + findex[i];
+ swap_words(work_point, sizeof(int), 1);
+ }
+ }
+
   close(file);

   return 0;

No other changes in the make system are needed.

The font files are small enough that the extra processing time to byte-swap on loading them
shouldn't adversly impact GRASS' speed.

If this is something that could also be backported to 6.2, that would be great.

-------------------------------------------- Managed by Request Tracker