On Sun, 6 May 2007, Glynn Clements wrote:
Paul Kelly wrote:
FWIW, the robust way to check whether two paths are equivalent is to
stat() (or lstat()) both of them, and check whether the device and
inode numbers match.
Interesting; here we are comparing the directory the fonts are stored in
rather than the font files themselves but perhaps still of use?
Yes; in the case of COM_Font_get(), you would need to remove the last
part of the path and check whether the directory part refers to the
same device/inode as $GISBASE/fonts.
OK well it doesn't work on Windows anyway. The device number corresponds to the drive letter but it appears the inode number is always 0. So I suppose we can just keep the string comparison of the directory names. Or remove the option of specifying the full path to a GRASS stroke font - I generally feel unhappy with the idea of removing functionality but maybe it is the best option here?
Also, I'd guess that using a colon as the field separator is likely to
be problematic on Windows.
Yes, that was it. If I use a semi-colon instead all works great - maybe we
could change mkftcap to generate a file with semi-colon separators? And
change parse_freetypecap() to handle both for backwards compatibility? Is
the last character on a line in freetypecap always a separator character?
If so that would be a quick way to check. Or could scan the first line and
whichever appeared first between : and ; use that as the separator?
If it's going to be changed, one option is to use a vertical bar
(which isn't a legal filename character on Windows), and make the face
index a separate column.
I can't see an easy way though of keeping old freetypecap files compatible with the current reading code that way though - just recognising an alternative separator character doesn't seem to be too disruptive (apart from adding extra code and requiring it to be kept there for ever.)
That would eliminate the possibility of using a non-zero index when
specifying a font by a pathname, but that's problematic for other
Yes but that's quite neat and an easy and simple way of specifying a non-zero index if you need to, I thought.
reasons (e.g. gisprompt = "old_file,..." should probably check for
file existence, which would rule out the option of using something
which is "almost" a filename).
Yes if the font was being specified through a module like d.font - I suppose an extra parameter could be added to specify the index. But when the font is just being read from an environment variable then it's more complicated and anyway the parser isn't going to be involved here so as far as I can see the check for file existence needs to be done manually anyway as it currently is.
AFAIK, the trailing separator is an artifact of the time that style
information (colour, size) was included in the freetypecap file.
BTW, the encoding field isn't used either (d.font.freetype and
d.text.freetype used it, but the driver doesn't).
Note that d.font has code which parses the freetypecap file in order
to generate the option list for font=, and to implement the -l switch,
so that will need to be updated if the format changes.
d.font.freetype and d.text.freetype have similar code, but they no
longer need to be maintained; they have been replaced by scripts which
call d.font and d.text (which is actually d.text.new) respectively.
OK. Well here is my current proposal, which can be easily added to both d.font and libdriver: dynamically generate the format conversion string (containing either a : or ; as separator) based on the relative position of : and ; characters in the first line of the file that contains either of them.
The code looks like below; it is complicated but I can't see how to make it simpler without losing backwards compatibility. I'm not quite happy enough with it to commit it yet. It can be easily included in both d.font and libdriver as-is, though.
char format[16] = "";
while(fgets(buf, sizeof(buf), fp) && !feof(fp))
{
char *p;
p = strchr(buf, '#');
if(p)
*p = 0;
if (!*format)
{
char *first_colon = strchr(buf, ':');
char *first_semi = strchr(buf, ';');
if (first_colon || first_semi)
{
char sep_char;
if (first_colon == NULL)
sep_char = ';';
else if (first_semi == NULL)
sep_char = ':';
else
sep_char = (first_colon < first_semi)? ':' : ';';
sprintf(format, "%%[^%c]%c%%[^%c]", sep_char, sep_char, sep_char);
}
else
continue;
}
if(sscanf(buf, format, iname, ipath) != 2)
continue;