nanogui: Fonts offset leads to wrong memory location -- genfont.c bug??


Previous by date: 22 Nov 2006 19:32:49 +0000 Fonts in nano-X, nxlib, FLTK, albrecht ellinger
Next by date: 22 Nov 2006 19:32:49 +0000 What coding and font is best for Chinese application, Pete Klemm
Previous in thread: 22 Nov 2006 19:32:49 +0000 Re: Fonts offset leads to wrong memory location -- genfont.c bug??, Greg Haerr
Next in thread: 22 Nov 2006 19:32:49 +0000 Re: Fonts offset leads to wrong memory location -- genfont.c bug??, Greg Haerr

Subject: RES: [nanogui] Fonts offset leads to wrong memory location -- genfont.c bug??
From: "Ricardo P. Jasinski" ####@####.####
Date: 22 Nov 2006 19:32:49 +0000
Message-Id: <20061122024849.6C1F798E4@thialf.cpdtt.cefetpr.br>

Hi Greg,

thanks a lot for your response! Please see the replies to your comments
below.

> ... Convfnt32.exe works by reading bits from the 
> screen, not exactly a great way.  Of course, it could be enhanced by
getting 
> font information internally and adding the width array from that
information.
> I'll write up the missing member data as a bug.
>
> : My first attempt was replacing 'winArial8x22_offset' with the value 0.
It
> : indeed solved the problem, but it only worked for monospaced (fixed
width)
> : fonts.
>
> Of course: the missing data points to the width table, which isn't
present.

Actually, if you are talking about the static unsigned char 
winFreeSansSerif11x13_width[] = { ... }; table, it is generated perfectly
fine, 
for all fonts I have tried. Also, all width calculations are carried out 
correctly.

> : I was able to get things working by making the following change:
> :
> :     //bits = pf->bits + (pf->offset? pf->offset[ch]: (pf->height * ch));
> :     bits = pf->bits + (pf->offset? ((unsigned short *)pf->offset)[ch] :
> : (pf->height * ch));
> :
> : Now, I believe that the root of all problems was that the 'offset'
> variable
> : was declared as an 'unsigned long *', while 'bits' was an 'unsigned
short
> : *'. Actually, 'bits' is declared as  a pointer to the MWIMAGEBITS type,
> : which in turn is defined as an unsigned short. I'm not sure it is a good
> : thing to have these two types mixed when doing pointer arithmetic.
> 
> No, this has nothing to do with pointer arithmetic, the bits = pf->bits +
... 
> means that we want to increment/index the pf->bits pointer MWIMAGEBITS
amount 
> over.  In other words, this is used to find exactly the start of an
MWIMAGEBITS 
> which happens to be the start of a proportional character.  We can't index
it 
> using a straight multiply because there isn't a standard character width.
> 
> The pf->offset is declared as an 'unsigned long *' because that allows
font 
> bitmap data longer than  64k.  This was earlier declared to be 'unsigned
short 
> *' but was buggy for large fonts.

I'll illustrate the situation with actual values from a debug session.

So, these are the types we're dealing with:

  typedef unsigned short	MWIMAGEBITS;	/* bitmap image unit size*/
  typedef struct {
    MWIMAGEBITS *	bits;			/* 16-bit right-padded
bitmap data*/
    unsigned long *offset;		/* offsets into bitmap data*/
    unsigned char *	width;	/* character widths or 0 if fixed*/
    ...
  } MWCFONT, *PMWCFONT;

And these are the code lines that perform the offset calculation. 'bits' is 
the original calculation as in genfont.c, and 'fixedBits' is my modified
version 
of the calculation:

  bits = pf->bits + (pf->offset? pf->offset[ch]: (pf->height * ch));
  fixedBits = pf->bits + (pf->offset? ((unsigned short *)pf->offset)[ch] :
(pf->height * ch));

Right before these code lines, I added the following test code:

  unsigned long * p_longIndexed_char0_offset = &(pf->offset[0]);
  unsigned long * p_longIndexed_char1_offset = &(pf->offset[1]);
  unsigned long * p_longIndexed_char2_offset = &(pf->offset[2]);

  unsigned long * p_shortIndexed_char0_offset = &((unsigned short
*)pf->offset)[0];
  unsigned long * p_shortIndexed_char1_offset = &((unsigned short
*)pf->offset)[1];
  unsigned long * p_shortIndexed_char2_offset = &((unsigned short
*)pf->offset)[2];
    
  unsigned long longIndexed_char0_offset = pf->offset[0];
  unsigned long longIndexed_char1_offset = pf->offset[1];
  unsigned long longIndexed_char2_offset = pf->offset[2];

  unsigned long shortIndexed_char0_offset = ((unsigned short
*)pf->offset)[0];
  unsigned long shortIndexed_char1_offset = ((unsigned short
*)pf->offset)[1];
  unsigned long shortIndexed_char2_offset = ((unsigned short
*)pf->offset)[2];

And the results were:

  pf = 0x0099e980
    size = 224
      bits = 0x0099d020
        +-> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 40
            00 40 00 40 00 40 00 40 00 40 00 00 00 00 00 40
            00 00 00 00 00 00 00 48 00 48 00 48 00 00 00 00 ...		  
      offset = 0x0099e6e0
        +-> 00 00 0d 00 1a 00 27 00 34 00 41 00 4e 00 5b 00 ...
      width = 0x0099e8a0
        +-> 03 03 05 07 06 08 06 02 03 03 04 06 03 03 03 05 ...
  p_longIndexed_char0_offset = 0x0099e6e0
  p_longIndexed_char1_offset = 0x0099e6e4
  p_longIndexed_char2_offset = 0x0099e6e8
  p_shortIndexed_char0_offset = 0x0099e6e0
  p_shortIndexed_char1_offset = 0x0099e6e2
  p_shortIndexed_char2_offset = 0x0099e6e4
  longIndexed_char0_offset = 	0xd0000 = 	851968
  longIndexed_char1_offset = 	0x27001a = 	2555930
  longIndexed_char2_offset = 	0x410034 = 	4259892
  shortIndexed_char0_offset = 0x0 = 	0
  shortIndexed_char1_offset = 0xd = 	13
  shortIndexed_char2_offset = 0x1a =	26

As can be seen, when pf->offset is treated as an unsigned long, it is
indexed at 4 bytes 
increments, placing the pointer at the wrong location. Also, the value
retrieved is 4 bytes
long, which results in an abnormally huge offset value.

Casting pf->offset to an unsigned short *, the pointer is positioned
corrrectly at 2 bytes
increments, and retrieved offset values are 16-bit, giving back the correct
values from the
font offsets table {0, 13, 26, etc.}.

As a test, I have recompiled the original microwindows code, simply changing
pf->offset type
from 'unsigned long *' to 'MWIMAGEBITS *'. Apparently, everything ran
smoothly. 

> The font still displays incorrectly, doesn't it?

No, it shows up perfectly for all fonts I've tried so far.

Final comments: perhaps this is a consequence of the change you have
mentioned in the 
previous message, since pf->offset used to be declared as 'unsigned short
*'.

If you have new thoughts on this subject I'll be glad to hear them, and also
to perform
any necessary tests.

Thanks for your time and attention,

Ricardo P. Jasinski.


Previous by date: 22 Nov 2006 19:32:49 +0000 Fonts in nano-X, nxlib, FLTK, albrecht ellinger
Next by date: 22 Nov 2006 19:32:49 +0000 What coding and font is best for Chinese application, Pete Klemm
Previous in thread: 22 Nov 2006 19:32:49 +0000 Re: Fonts offset leads to wrong memory location -- genfont.c bug??, Greg Haerr
Next in thread: 22 Nov 2006 19:32:49 +0000 Re: Fonts offset leads to wrong memory location -- genfont.c bug??, Greg Haerr


Powered by ezmlm-browse 0.20.