/* Copyright 1997 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /***************************************************/ /* File : FontManage.c */ /* */ /* Purpose: A range of font management veneers. */ /* */ /* Author : Merlyn Kline for Customer browser */ /* This source adapted by A.D.Hodgkinson */ /* */ /* History: 05-Dec-96: Created. */ /* 14-Apr-97: Merged in a bug fix to */ /* fm_get_string_width spotted */ /* by T.Cheal (see source for */ /* more info). */ /***************************************************/ #include #include #include #include #include #include "swis.h" #include "HTMLLib.h" /* HTML library API, Which will include html2_ext.h, tags.h and struct.h */ #include "wimp.h" #include "event.h" #include "svcprint.h" #include "Global.h" #include "FromROSLib.h" #include "MiscDefs.h" #include "Utils.h" #include "Redraw.h" #include "FontManage.h" /* Conditional includes */ #ifdef UNIFONT #include "Unicode/iso10646.h" #include "Unicode/utf8.h" #include "Unifont.h" #endif #ifndef Font_WideFormat #define Font_WideFormat 0x400A9 #endif /**************************************************************************************************/ /* */ /* Merlyn's original overview comments (corrected where necessary, due to changes in the source): */ /* ============================================================================================== */ /* */ /* RISC OS Font management */ /* */ /* Merlyn Kline, 1995 */ /* */ /* This module provides a range of veneers for font management. It allows a typeface */ /* to be defined including bold, italic and bold-italic attributes. These typefaces */ /* are given names by which they are referred to in subsequent use. When defining a */ /* typeface an alternative to be used can be specified for cases where the primary */ /* selection is unavailable for some reason. If the alternative does not exist, *its* */ /* alternative is checked. This goes on for several attempts (about 4) before giving */ /* up after which the ordinary system font is used, scaled appropriately. This limit */ /* on the number of attempts improves performance and means you don't have to worry too */ /* much about defining loops (eg pairs of typefaces which specify each other as alternatives). */ /* */ /* The system provides veneers for all font related functions and these use an internal */ /* font handle. This font handle is either the RISC OS font handle when an appropriate */ /* font was available or a negative number made up from the x and y font sizes. */ /* */ /* Note the use of the word 'typeface' to describe the four-font structure used by this */ /* module. This is to avoid confusion with the RISC OS term 'font' underlying it. */ /* */ /* Typefaces are defined by passing strings to the font definition routine, which contain */ /* a description of the desired font, like: */ /* */ /* name=normal:italic:bold:bolditalic;alternative */ /* */ /* where: */ /* */ /* name is the name you want to refer to this typeface by (case *sensitive* for speed) */ /* normal is the RISC OS font name to use in normal rendering */ /* italic is the RISC OS font name to use in italic rendering */ /* bold is the RISC OS font name to use in bold rendering */ /* bolditalic is the RISC OS font name to use in bold plus italic rendering */ /* alternative is the alternative typeface name to use if necessary */ /* */ /* Any of these fields may be missing except . If the font names used for */ /* bold/italic rendering are missing, the normal one will be used instead. If */ /* the normal font name is missing, the alternative typface is used. If the */ /* alternative is missing, system font will be used when the requested fonts are */ /* not available. */ /* */ /* When defining typefaces for optimum performance define the one which will be used */ /* most, last. This is because they are kept in a linked list and new ones are added to */ /* the start of the list and so will be found more quickly. */ /* */ /* If you define a typeface with the same name as an existing one the new definition */ /* overwrites the old one. */ /* */ /* Default font definitions are available as follows: */ /* */ /* system=System.Fixed:Corpus.Medium.Oblique:Corpus.Bold:Corpus.Bold.Oblique;fixed */ /* sans=Homerton.Medium:Homerton.Medium.Oblique:Homerton.Bold:Homerton.Bold.Oblique;serif */ /* serif=Trinity.Medium:Trinity.Medium.Italic:Trinity.Bold:Trinity.Bold.Italic;sans */ /* fixed=Corpus.Medium:Corpus.Medium.Oblique:Corpus.Bold:Corpus.Bold.Oblique */ /* */ /* Font sizes are defined in sixteenths of a point. The system font is treated as a font */ /* with a 2:1 aspect ratio so set both xsize and ysize to the same to get normal looking text. */ /* A size of 205 (=8*2*16*72/90 ie: */ /* */ /* pixels * os_units_per_pixel * sixteenths_of_a _point_per_inch / os_units_per_inch ) */ /* */ /* will get system font at its normal size. This size should therefore be used for any display */ /* of information where size is pretty arbitrary, ensuring a reasonable appearnce should system */ /* font be used. To help, it is #defined as FM_Standard_Size in FontManage.h. */ /* */ /* ------------------------------------------------------ */ /* */ /* (Merlyn then goes on to describe the font menu display and interpretation functions, which are */ /* more or less redundant in this source due to the Toolbox's automation). */ /* */ /* Note that some specialisation of the library for use in the browser has been necessary, so */ /* for example references to browser_data structures would need to be removed were this version */ /* of the library to be used elsewhere. */ /* */ /**************************************************************************************************/ /* Statics */ static fm_typeface * fm_new_typeface (void); static fm_face fm_sub_find_font (fm_typeface * f, int xsize, int ysize, int italic, int bold); static fm_facelist * fm_list = NULL; static int fm_systemfont = 0; static int fm_allowblend = -1; /* Locals */ /* fm_faces allows typeface numbers to be defined internally */ /* which relate to typeface names held by the font managing */ /* routines; these are easier to deal with than strings. */ char * fm_faces[] = { "serif", "sans", "fixed" }; /* fm_handles records usage of font handles. For every font */ /* font claim, an appropriate bit is examined in the */ /* browser_data structure of the claimant (if available). If */ /* the bit is unset, it is set and the entry in fm_handles */ /* incremented by one. For every font discard, the bit is */ /* examined again and if set, it is cleared, and the entry */ /* in fm_handles decremented by one. If that entry is now */ /* zero, Font_LoseFont is called for the handle. */ int fm_handles[Limits_OS_FontHandles]; /* fm_sizes allows quick lookup of a font size number, which */ /* otherwise would needed to be calculated on the fly (this */ /* is slow). Initialisation is done in fm_init, and the size */ /* is looked up through fm_size. */ /* */ /* Whilst fm_find_token_font scales using this, fm_find_font */ /* doesn't. For speed, it's quicker if the caller can do the */ /* scaling, if needed, when falling fm_find_font. */ int fm_sizes[Limits_FontSizes + 1]; /* (Indices 1 to Limits_FontSizes are used, with index 0 */ /* filled with base size in case something goes wrong */ /* and a size of 0 is given) */ /*************************************************/ /* fm_find_typeface() */ /* */ /* Goes through the linked list of fm_facelist */ /* structures looking for one which is named, */ /* returning the address of the fm_typeface */ /* structure containing that name if it is found */ /* (or NULL if not). The name should be in lower */ /* case charaters. */ /* */ /* Parameters: A pointer to a string holding the */ /* name of the typeface to find, in */ /* lower case. */ /* */ /* Returns: Pointer to the fm_typeface struct */ /* if found, else NULL. */ /*************************************************/ fm_typeface * fm_find_typeface(char * name) { fm_facelist * f; /* Set f to point to the start of the list */ /* of fm_facelist structures, and go up */ /* the list looking for the named font. */ /* Return the address of the fm_typeface */ /* structure itself (rather than the */ /* fm_facelist structure that contains it) */ /* if found, NULL if not. */ f = fm_list; while (f) { if (!strcmp(f->face.name, name)) return &f->face; f = f->next; } return NULL; } /*************************************************/ /* fm_new_typeface() */ /* */ /* Adds a new typeface to the list of typefaces. */ /* Returns a pointer to the fm_typeface struct */ /* itself, when added, or NULL if the malloc */ /* claim failed (so error check this externally) */ /* */ /* Returns: Pointer to the new fm_typeface */ /* struct, or NULL if malloc failed. */ /*************************************************/ static fm_typeface * fm_new_typeface(void) { fm_facelist * f; /* Allocate memory for the fm_facelist struct */ #ifdef TRACE if (tl & (1u<<12)) Printf("fm_new_typeface: malloc %d for 'fm_facelist' structure\n",sizeof(fm_facelist)); #endif f = calloc(1, sizeof(fm_facelist)); if (f) { #ifdef TRACE malloccount += sizeof(fm_facelist); if (tl & (1u<<13)) Printf("** malloccount (fm_new_typeface): \0211%d\0217\n",malloccount); #endif /* If the claim succeeded, link the new item into */ /* the list, and return with the address of the */ /* fm_typeface structure. */ f->next = fm_list; fm_list = f; return &f->face; } /* The malloc claim failed, so return NULL */ return NULL; } /*************************************************/ /* fm_define_typeface_explicit() */ /* */ /* Adds a new fm_facelist structure to the list */ /* of fm_facelist structures, but also names */ /* the new typeface and only allocates a new */ /* list item if one of the same name wasn't */ /* already present. */ /* */ /* Parameters: A pointer to an fm_typeface */ /* structure, in which only the */ /* 'name' field is filled in. This */ /* becomes the name for the new */ /* typeface and is used to check if */ /* a typeface of that name is */ /* already present. */ /*************************************************/ _kernel_oserror * fm_define_typeface_explicit(fm_typeface * f) { fm_typeface * fp; /* Try to find a typeface of the same name in the list */ fp = fm_find_typeface(f->name); /* If there isn't one, create a new typeface entry */ if (!fp) fp = fm_new_typeface(); /* Report an error if the new typeface entry couldn't be created */ if (!fp) { erb.errnum = Utils_Error_Custom_Fatal; StrNCpy0(erb.errmess, lookup_token("FontMem:There is not enough free memory for font handling (%0).", 0, "1")); return(&erb); } /* Copy whole structure over to fp */ *fp = *f; return(NULL); } /*************************************************/ /* fm_define_typeface() */ /* */ /* This function defines a whole new typeface in */ /* full, according to a description string the */ /* format of which is described in Merlyn's */ /* comments at the top of this file. */ /* */ /* Parameters: A pointer to a string containing */ /* the typeface description. */ /*************************************************/ _kernel_oserror * fm_define_typeface(char * description) { fm_typeface f; char * p = description; int i = 0; /* Ensure that the fm_typeface struct has been */ /* allocated locally, then zero the contents */ f.name[0] = 0; memset(&f,0,sizeof(f)); /* Travel through the description string looking for */ /* an equals sign - this separates the name of the */ /* typeface from the actual RISC OS fonts it uses. */ /* Copy the text - which is the typeface name - into */ /* the 'name' field of the new typeface structure */ /* that was filled with zeros above. */ while ((*p) && (*p != '=')) { if (i < (sizeof(f.name) - 1)) f.name[i++] = *p++; } /* If we're not now at the end of the string, get the */ /* four RISC OS font names from the string. */ if (*p) { int n; for (n = 0; n < 4; n++) { p++; /* Skip past the =, : or ; that we last ended on */ i=0; /* Copy between the current position and the next separator */ /* (i.e. the font name) into the relevant fontname field of */ /* the fm_typeface structure. */ while ((*p) && (*p != ':') && (*p != ';')) { if (i < sizeof(f.fontnames[n]) - 1) f.fontnames[n][i++] = *p++; } /* If we've reached the end of the string or a ';', exit now */ /* as there are no more font names. */ if ((!*p) || (*p == ';')) break; } /* If there's a semicolon, there is an alternative typeface */ /* name defined */ if (*p == ';') { p++; /* Skip past the ; */ /* Copy the alternative typeface name to the fm_typeface struct */ strncpy(f.alternative, p, sizeof(f.alternative) - 1); } } /* If there's at least one font name present, */ /* actually allocate the memory for the */ /* typeface (or copy over an old one with the */ /* same name). */ if (f.name[0]) return fm_define_typeface_explicit(&f); /* There are no font names - the typeface is badly defined */ erb.errnum = Utils_Error_Custom_Fatal; StrNCpy0(erb.errmess, lookup_token("BadType:Internal error - Bad typeface definition in %0.", 0, "fm_define_typeface")); return &erb; } /*************************************************/ /* fm_define_default_typefaces() */ /* */ /* Sets up the default typeface settings, for */ /* system, fixed space, sans serif and serif */ /* font 'banks'. */ /*************************************************/ _kernel_oserror * fm_define_default_typefaces(void) { /* These will be overridden if typefaces of the same name are read */ /* in by load_choices later. */ RetError(fm_define_typeface("fixed=Corpus.Medium:Corpus.Medium.Oblique:Corpus.Bold:Corpus.Bold.Oblique")); RetError(fm_define_typeface("sans=Homerton.Medium:Homerton.Medium.Oblique:Homerton.Bold:Homerton.Bold.Oblique;serif")); RetError(fm_define_typeface("serif=Trinity.Medium:Trinity.Medium.Italic:Trinity.Bold:Trinity.Bold.Italic;sans")); return NULL; } /*************************************************/ /* fm_claim_basic_typefaces() */ /* */ /* Claim a few basic fonts which will probably */ /* be needed for the duration of the application */ /* run time. */ /* */ /* Parameters: Base font size to claim at. */ /*************************************************/ void fm_claim_basic_typefaces(int base_size) { fm_face h; #define FMCIncHandles(f) { \ if (f >= 0) \ { \ if (!fm_handles[(f)]) fm_handles[(f)] = 1; \ else fm_lose_font(NULL, (f)); \ } \ } if (!choices.system_font) { /* Need to be a bit careful here... Must not claim a font twice, if the */ /* typeface is the same (e.g. System.Fixed for both fixed width normal */ /* and fixed width bold). The fm_handles array is an *internal* usage */ /* count - as far as the RISC OS Font Manager is concerned, for every */ /* font marked as used inside fm_handles, there's only one user in the */ /* browser. So if we claim something two or more times here, it'll only */ /* get released once later on, thereby 'leaking' the font handle. */ h = fm_find_font(NULL, "sans", base_size, base_size, 0, 0); FMCIncHandles(h) h = fm_find_font(NULL, "sans", base_size, base_size, 0, 1); FMCIncHandles(h) h = fm_find_font(NULL, "sans", base_size, base_size, 1, 0); FMCIncHandles(h) h = fm_find_font(NULL, "sans", base_size, base_size, 1, 1); FMCIncHandles(h) h = fm_find_font(NULL, "serif", base_size, base_size, 0, 0); FMCIncHandles(h) h = fm_find_font(NULL, "serif", base_size, base_size, 1, 0); FMCIncHandles(h) h = fm_find_font(NULL, "serif", base_size, base_size, 0, 1); FMCIncHandles(h) h = fm_find_font(NULL, "serif", base_size, base_size, 1, 1); FMCIncHandles(h) h = fm_find_font(NULL, "fixed", base_size, base_size, 0, 0); FMCIncHandles(h) h = fm_find_font(NULL, "fixed", base_size, base_size, 0, 1); FMCIncHandles(h) } } /*************************************************/ /* fm_sub_find_font() */ /* */ /* When asked for a standard, italic, bold or */ /* bold italic variant of a typeface, this will */ /* return the font handle for the requested font */ /* or -1 if it can't be found. The routine */ /* will try for just a standard or bold variant */ /* if an italic or bold italic variant isn't */ /* defined, then drop to just standard, before */ /* giving up. */ /* */ /* Parameters: Pointer to the fm_typeface struct */ /* for the typeface in question; */ /* */ /* The X and Y sizes, in 1/16ths of */ /* a point, of the font to claim; */ /* */ /* 1 to specify italics, else 0; */ /* */ /* 1 to specify bold, else 0. */ /* */ /* Returns: The RISC OS font manager's font */ /* handle for the requested font (as */ /* an fm_face) or -1 if the font */ /* couldn't be found either by this */ /* routine, or by the font manager */ /* itself. */ /*************************************************/ static fm_face fm_sub_find_font(fm_typeface * f, int xsize, int ysize, int italic, int bold) { int n; fm_face h; /* Set bit 0 of n if italic was specified, and bit 1 */ /* if bold was specified. */ n=(italic ? 1 : 0) | (bold ? 2 : 0); /* So n = 0 for standard, 1 for italic, 2 for bold */ /* and 3 for bold italic. */ /* If there is no fontname defined for that combination, */ /* AND n with 2 - i.e., drop the italic specifier and */ /* just try plain / bold. */ if (!f->fontnames[n][0]) n &= 2; /* If there is still no font name, try the standard only */ if (!f->fontnames[n][0]) n = 0; /* If there is *still* no font name, we can't match this */ /* so flag that by returning -1. */ if (!f->fontnames[n][0]) return -1; /* If the font manager can't find the font, again flag the */ /* problem by returning -1. Otherwise, return the font */ /* handle returned by the font manager. */ if (_swix(Font_FindFont, _INR(1,5) | _OUT(0), f->fontnames[n], /* Font name to find */ xsize, /* x size in 16ths pt */ ysize, /* y size in 16ths pt */ 180 / wimpt_dx(), /* Current mode's x dpi */ 180 / wimpt_dy(), /* Current mode's y dpi */ &h)) /* Font handle put in h */ return -1; return h; } /*************************************************/ /* fm_size() */ /* */ /* Given an abstracted font size (from 1 to 7, */ /* with 3 being 'base font' size), returns the */ /* actual size (in 16ths of a point) to use. */ /* */ /* Parameters: The font size, from 1 to 7. */ /* */ /* Returns: The equivalent font size, in */ /* 16ths of a point. */ /* */ /* Assumes: For speed, the parameter is not */ /* limit checked, so if it falls */ /* outside the allowed range the */ /* returned value will be undefined */ /* and probably very inappropriate */ /* for a font size! */ /*************************************************/ int fm_size(int size) { return fm_sizes[size]; } /*************************************************/ /* fm_find_font() */ /* */ /* Returns the font handle of a requested */ /* typeface variant, optionally recording the */ /* usage in a given browser_data structure. */ /* */ /* Parameters: Pointer to the browser_data */ /* struct relevant to the font; */ /* */ /* Pointer to the typeface name; */ /* */ /* X and Y sizes in 16ths of a pt; */ /* */ /* 1 for italics, 0 for not italic; */ /* */ /* 1 for bold, 0 for not bold. */ /* */ /* Returns: A RISC OS font handle for the */ /* requested font or the closest */ /* available match to it; this may */ /* be the system font if no good */ /* match could be found. */ /* */ /* Assumes: The browser_data struct pointer */ /* may be NULL. */ /*************************************************/ fm_face fm_find_font(browser_data * b, char * name, int xsize, int ysize, int italic, int bold) { fm_typeface * f; fm_face s,h; int i; /* Work out the system font 'handle' for the given point size */ s = FM_System_Handle(xsize,ysize); /* (Macro defined in FontManage.h) */ /* If system font has been configured locally through the */ /* fm_set_system_font function, return that handle now */ if (fm_systemfont) return s; /* The slower alternative - try to find the named typeface */ f = fm_find_typeface(name); /* If it can't be found, return the system font */ if (!f) return s; /* Get the RISC OS font handle for that typeface */ h = fm_sub_find_font(f, xsize, ysize, italic, bold); /* If fm_sub_find_font returns -1, keep trying */ /* alternative typefaces as long as there are */ /* some defined, to a maximum of 4 alternatives. */ for ( i = 0; i < 3 && h < 0 && f->alternative[0]; i++ ) { f = fm_find_typeface(f->alternative); if (!f) return s; h = fm_sub_find_font(f, xsize, ysize, italic, bold); } /* If we still haven't got a RISC OS font handle */ /* return the system font handle. */ if (h < 0) return s; /* Success, eventually! */ /* If the font has already been claimed (it has an entry in fm_handles) */ /* don't want to keep the second claim caused by the Font_FindFont that */ /* gave the handle. So, lose the font - we know that the Font Manager */ /* will still have a usage of at least 1 for the font as long as */ /* fm_handles has a non-zero usage count itself. This is somewhat */ /* inefficient, but otherwise, for every claimed font handle, the face */ /* name, style, and size would have to be recorded with it, and for */ /* every font claim these preclaimed fonts would need to checked */ /* through. This would end up being quite slow. */ if (b && fm_handles[h]) _swix(Font_LoseFont, _IN(0), h); /* Record the usage of this font */ if (b && !(Bitfield_Is_Set(&b->handles, h))) { fm_handles[h]++; Bitfield_Set_Bit(&b->handles, h); } return h; } /*************************************************/ /* fm_lose_font() */ /* */ /* Forgets about the usage of a given font by a */ /* given browser, and if there are no users at */ /* this point, tell the RISC OS Font Manager */ /* that the font is no longer in use. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the font; */ /* */ /* The RISC OS font handle for the */ /* font to forget. */ /* */ /* Assumes: The pointer to the browser_data */ /* struct *may* be NULL, in which */ /* case the RISC OS Font Manager is */ /* told the font isn't needed */ /* straight away. */ /*************************************************/ void fm_lose_font(browser_data * b, fm_face h) { if (h >= 0) { if (b) { if (Bitfield_Is_Set(&b->handles, h)) { fm_handles[h]--; Bitfield_Clear_Bit(&b->handles, h); } if (!fm_handles[h]) _swix(Font_LoseFont,_IN(0),h); else if (fm_handles[h] < 0) fm_handles[h] = 0; } else _swix(Font_LoseFont,_IN(0),h); } } /*************************************************/ /* fm_lose_fonts() */ /* */ /* Forgets about the usage of all fonts used by */ /* a given browser, and if there are no longer */ /* any users of any of the fonts, tells the */ /* RISC OS Font Manager that those fonts are no */ /* longer in use. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the fonts. */ /*************************************************/ void fm_lose_fonts(browser_data * b) { int fh; for (fh = 0; fh < Limits_OS_FontHandles; fh++) { if (Bitfield_Is_Set(&b->handles, fh)) fm_lose_font(b, fh); } } /*************************************************/ /* fm_rescale_fonts() */ /* */ /* For all currently claimed fonts, reclaim them */ /* with the current screen DPI. Useful for (say) */ /* mode changes, when the Desktop scaling may */ /* have changed. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the fonts to rescale. */ /*************************************************/ _kernel_oserror * fm_rescale_fonts(browser_data * b) { _kernel_oserror * e; browser_data temp; int fh, size, xsize, ysize; char name[Limits_FontName]; /* Can't lose and reclaim fonts within the same browser, */ /* whilst scanning through its list of claimed fonts... */ /* if ever a font handle higher than the one just lost */ /* was returned, things would go very wrong. So copy */ /* the list of used fonts into a temporary store and use */ /* this for the loses and claims, then copy that back to */ /* the actual browser_data structure when finished. */ temp.handles = b->handles; /* Now loop round all the font handles */ for (fh = 0; fh < Limits_OS_FontHandles; fh++) { /* If this font is claimed... */ if (Bitfield_Is_Set(&b->handles, fh)) { /* How much space does the font name need? */ e = _swix(Font_ReadDefn, _INR(0,1) | _IN(3) | _OUT(2), fh, /* Handle */ 0, /* Return buffer size needed for name */ Magic_Word_FULL, /* See MiscDefs.h */ &size); if (e) return e; /* If the font name will fit, then get the name and size details */ if (size < sizeof(name)) /* Not '<=' as need terminator */ { int h; /* Fill the name buffer with zeros first, to ensure the */ /* name string is correctly terminated. */ memset(name, 0, sizeof(name)); /* Now read the font information */ e = _swix(Font_ReadDefn, _INR(0,1) | _IN(3) | _OUTR(2,3), fh, name, Magic_Word_FULL, /* See MiscDefs.h */ &xsize, &ysize); if (e) return e; /* Lose the old font, and reclaim the same name and size */ /* at a new resolution. */ fm_lose_font(&temp, fh); e = _swix(Font_FindFont, _INR(1,5) | _OUT(0), name, /* Font name to find */ xsize, /* x size in 16ths pt */ ysize, /* y size in 16ths pt */ 180 / wimpt_dx(), /* Current mode's x dpi */ 180 / wimpt_dy(), /* Current mode's y dpi */ &h); /* Font handle put in h */ if (e) return e; /* See fm_find_font for full comments on this bit, no need */ /* to repeat it all here. */ if (fm_handles[h]) _swix(Font_LoseFont, _IN(0), h); /* Record the usage of this font */ fm_handles[h]++; Bitfield_Set_Bit(&temp.handles, h); /* Closure of long 'if' to see if the font name would fit */ /* in the allocated buffer. The code above executes if it */ /* would. */ } /* Closure of long 'if' to see if the current font handle */ /* was claimed; the code above executes if it was. */ } /* Closure of 'for' loop going found all font handles. */ } /* Copy the font usage information back to the actual browser. */ b->handles = temp.handles; return NULL; } /*************************************************/ /* fm_font_box() */ /* */ /* Gets a bounding box large enough to cover any */ /* character in a given font, in OS units. */ /* */ /* Parameters: RISC OS font handle of the font; */ /* */ /* Pointer to a BBox into which the */ /* bounding box is placed (min X and */ /* Y are inclusive, max X and Y are */ /* exclusive). */ /*************************************************/ _kernel_oserror * fm_font_box(fm_face h, BBox * box) { if (h < 0) { /* If we're passed a system font handle, */ /* treat that as a special case. */ int xs,ys; xs = FM_System_Size_X(h); /* (Macros defined in FontManage.h) */ ys = FM_System_Size_Y(h); /* The code is derived from this: */ /* */ /* box->xmin=0; */ /* box->ymin=ys * (10 * -3) / (64 * 16); */ /* */ /* box->xmax=xs * 10 / 128; */ /* box->ymax=ys * (10 * 13) / (64 * 16); */ box->xmin = 0; box->ymin = (ys * -30) / (1024); box->xmax = (xs * 10) / 128; box->ymax = (ys * 130) / (1024); } else { /* Otherwise, ask the Font Manager for the bounding box */ // this probably needs to a char by char scan of the font and cache the result return _swix(Font_ReadInfo, _IN(0) | _OUTR(1,4), h, /* Handle */ &box->xmin, /* Minimum X of bounding box */ &box->ymin, /* Minimum Y of bounding box */ &box->xmax, /* Maximum X of bounding box */ &box->ymax); /* Maximum Y of bounding box */ } return NULL; } /*************************************************/ /* fm_char_box() */ /* */ /* Gets the bounding box of a char, in OS units. */ /* */ /* Parameters: RISC OS font handle of the font; */ /* */ /* Character to measure; */ /* */ /* Pointer to a BBox into which the */ /* bounding box is placed (min X and */ /* Y are inclusive, max X and Y are */ /* exclusive). */ /*************************************************/ _kernel_oserror * fm_char_box(fm_face h, char c, BBox * box) { /* Very similar structure to fm_font_box, so see that for */ /* more comments. */ if (h < 0) { int xs,ys; xs = FM_System_Size_X(h); ys = FM_System_Size_Y(h); box->xmin = 0; box->ymin = (ys * -30) / (1024); box->xmax = (xs * 10) / 128; box->ymax = (ys * 130) / (1024); } else { #ifdef UNIFONT _swix(Font_WideFormat, _INR(0,1), h, 12); #endif return _swix(Font_CharBBox, _INR(0,2) | _OUTR(1,4), h, /* Handle */ c, /* Character */ FM_OSUnits, /* Flags -> OS units, please */ &box->xmin, /* Minimum X of bounding box */ &box->ymin, /* Minimum Y of bounding box */ &box->xmax, /* Maximum X of bounding box */ &box->ymax); /* Maximum Y of bounding box */ } return NULL; } /*************************************************/ /* fm_set_font_colour() */ /* */ /* Sets the font colour for subsequent painting. */ /* */ /* Parameters: The RISC OS font handle of the */ /* font in question; */ /* */ /* The foreground colour; */ /* */ /* The background colour. */ /* */ /* Colours are As palette entries, */ /* i.e. are in the form BBGGRRcc */ /* where cc = GCOL, else use the Red */ /* Green and Blue bytes. */ /*************************************************/ _kernel_oserror * fm_set_font_colour(fm_face h, int fore, int back) { /* First, the system font case */ if (h < 0) { #ifdef UNIFONT /* Need to set the background colour too */ _swix(ColourTrans_SetGCOL, _IN(0) | _INR(3,4), fore, /* Palette entry */ 0x80, /* Flags */ 0); /* GCOL action */ #endif return _swix(ColourTrans_SetGCOL, _IN(0) | _INR(3,4), fore, /* Palette entry */ 0, /* Flags */ 0); /* GCOL action */ } else { /* Alternatively, deal with an outline font */ return _swix(ColourTrans_SetFontColours, _INR(0,3), h, /* Handle */ back, /* Background colour palette entry */ fore, /* Foreground colour palette entry */ 14); /* Maximum foreground colour offset */ } } /*************************************************/ /* fm_puts() */ /* */ /* Outputs a string in a given font at specified */ /* coordinates in a colour determined by calls */ /* to fm_set_font_colour() prior to calling this */ /* function. */ /* */ /* Parameters: A RISC OS font handle; */ /* */ /* X and Y coordinates of the bottom */ /* left of the bounding box of the */ /* plotted string. These may be in */ /* OS units or millipoints (see */ /* below); */ /* */ /* Pointer to the string to output; */ /* */ /* 1 if using OS coords, else 0; */ /* */ /* 1 to use font blending, else 0 - */ /* do NOT use font blending on a */ /* Font Manager earlier than v3.37! */ /*************************************************/ _kernel_oserror * fm_puts(fm_face h, int x, int y, const char * s, int os, int blend) { #ifdef TRACE if (tl & (1u<<10)) Printf("\nfm_puts: Called with handle %p\n String '%s'\n",(void *) h, s); #endif if (h < 0) { /* System font output */ int xs,ys; if (!os) convert_pair_to_os(x, y, &x, &y); /* Work out the pixel size of the font; note that the */ /* Y size is twice the X size for aesthetic reasons */ xs = FM_System_Size_X(h) * 10 / (128 * wimpt_dx()); ys = FM_System_Size_Y(h) * 10 / (64 * wimpt_dy()); /* Set the size and spacing */ bbc_vduq(23, 17, 7, 6, xs & 255, xs >> 8, ys & 255, ys >> 8, 0, 0); /* Move to the requested (converted) coordinates. 10/64 */ /* converts to OS units, 13/16 is height above base */ bbc_move(x, y + (FM_System_Size_Y(h) * (10*13) / (64*16)) - 1); /* Output the string */ #ifdef UNIFONT unifont_write0(s, x, y + (FM_System_Size_Y(h) * (10*13) / (64*16)) - 1, xs, ys); #else _swix(OS_Write0, _IN(0), s); #endif /* Set the text output size back (certainly get interesting */ /* effects from Make if you don't do this...!) */ bbc_vduq(23, 17, 7, 6, 16 / wimpt_dx(), 0, 32 / wimpt_dy(), 0, 0, 0); return NULL; } else { unsigned int flags; /* Outline font output */ if (fm_allowblend < 0) { /* If we haven't already, check the Font Manager */ /* version - for 3.37 or later, allow background */ /* blending (fm_allowblend will set bit 11 of */ /* the flags for Font_Paint), else don't allow */ /* blending (earlier versions of the Font */ /* Manager will object strongly to bit 11 being */ /* set). */ int version; if (_swix(Font_CacheAddr,_OUT(0),&version)) version = 0; fm_allowblend = (version >= 337) ? FM_Blend : 0; } /* Paint the string. The parameters are a pointer to the string, */ /* flags, and x and y coordinates. The flags have the blending */ /* set if asked for, specify absolute coordaintes, and tell the */ /* Font Manager whether x and y are OS units or millipoints. */ #ifdef TRACE if (tl & (1u<<10)) { unsigned char * scan = (unsigned char *) s; while (*scan) { if (*scan < 32 && *scan != 10 && *scan != 13) Printf("fm_puts: Warning, non-CR/LF control char %d in string\n",(unsigned int) *scan); scan ++; } Printf("fm_puts: Calling Font_Paint prior to exiting\n"); } #endif if (printing) flags = 0; else flags = blend ? fm_allowblend : 0; flags |= ( (FM_GivenHandle) | (FM_Kern) | (os ? FM_OSUnits : 0) ); #ifdef UNIFONT _swix(Font_WideFormat, _INR(0,1), h, 12); #endif return _swix(Font_Paint, _INR(0,7), h, s, flags, x, y, NULL,NULL,0); } } /*************************************************/ /* fm_putsl() */ /* */ /* As fm_puts above, but takes an extra */ /* parameter after the string pointer which says */ /* how many characters of the string should be */ /* plotted. */ /* */ /* This will *write a character into the string* */ /* during operation, so the string must be owned */ /* by the caller and not in ROM. */ /* */ /* Parameters: As fm_puts above, but after the */ /* pointer to the string to output, */ /* pass the number of characters in */ /* the string that will be plotted. */ /*************************************************/ _kernel_oserror * fm_putsl(fm_face handle, int x, int y, char * s, int chars, int os, int blend) { char c; _kernel_oserror * e = NULL; /* If chars doesn't point past the end of the */ /* string, then forcibly terminate it and */ /* call fm_puts. Restore the character that */ /* the terminator wrote over whther or not */ /* there is an error. */ if (s[chars] != '\0') { c = s[chars]; s[chars] = '\0'; e = fm_puts(handle,x,y,s,os,blend); s[chars] = c; } /* If the number of chars is longer than the */ /* string, plot as much as there is of it. */ else e = fm_puts(handle,x,y,s,os,blend); return e; } /*************************************************/ /* fm_write_descriptor() */ /* */ /* Writes the descriptor string for a typeface */ /* into a given buffer. */ /* */ /* Parameters: Pointer to the typeface name; */ /* */ /* Pointer to the buffer. */ /* */ /* Assumes: That the buffer is big enough. */ /*************************************************/ _kernel_oserror * fm_write_descriptor(char * name, char * buffer) { fm_typeface * f; /* Try to find the typeface */ f = fm_find_typeface(name); /* If the typeface isn't found, give an error */ if (!f) { erb.errnum = Utils_Error_Custom_Fatal; StrNCpy0(erb.errmess, lookup_token("BadTRef:Internal error - Reference to undefined typeface in %0.", 0, "fm_write_descriptor")); return &erb; } /* Else fill in the buffer */ sprintf(buffer, "%s=%s:%s:%s:%s;%s", f->name, f->fontnames[0], f->fontnames[1], f->fontnames[2], f->fontnames[3], f->alternative); return NULL; } /*************************************************/ /* fm_write_name() */ /* */ /* Writes the RISC OS font name for a given */ /* typeface variant to a given buffer */ /* */ /* Parameters: Typeface number from the fm_faces */ /* array; */ /* */ /* Pointer to the buffer; */ /* */ /* 1 for italics, else 0; */ /* */ /* 1 for bold, else 0. */ /* */ /* Assumes: That the buffer is big enough. */ /*************************************************/ _kernel_oserror * fm_write_name(int number, char * buffer, int italic, int bold) { fm_typeface * f; int n; char * name; if (number < 0 || number >= sizeof(fm_faces)) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Illegal typeface number %d in fm_write_name.", number); return &erb; #endif return NULL; } else name = fm_faces[number]; /* Index the correct font name using the bold and italic flags */ n = (italic ? 1 : 0) | (bold ? 2 : 0); /* Try to find the typeface */ f = fm_find_typeface(name); /* If the typeface isn't found, give an error */ if (!f) { erb.errnum = Utils_Error_Custom_Fatal; StrNCpy0(erb.errmess, lookup_token("BadTRef:Internal error - Reference to undefined typeface in %0.", 0, "fm_write_name")); return &erb; } /* Else fill in the buffer */ sprintf(buffer,"%s",f->fontnames[n]); return NULL; } /*************************************************/ /* fm_read_typeface() */ /* */ /* Given a typeface name inside an fm_typeface */ /* structure, the rest of the typeface details */ /* are filled in. If the typeface name isn't */ /* found an error will be raised. */ /* */ /* Parameters: A pointer to the fm_typeface with */ /* the name to look up inside its */ /* 'name' field. */ /*************************************************/ _kernel_oserror * fm_read_typeface(fm_typeface * face) { fm_typeface * f; /* Try to find the named typeface */ f = fm_find_typeface(face->name); /* Raise an error if it can't be found */ if (!f) { erb.errnum = Utils_Error_Custom_Fatal; StrNCpy0(erb.errmess, lookup_token("BadTRef:Internal error - Reference to undefined typeface in %0.", 0, "fm_read_typeface")); return &erb; } /* Copy the found typeface contents across to the supplied typeface */ *face = *f; return NULL; } /*************************************************/ /* fm_destroy_typefaces() */ /* */ /* Destroys *all* typeface records, therefore */ /* emptying the list of typefaces. */ /*************************************************/ void fm_destroy_typefaces(void) { fm_facelist * f, * c; /* Point f to the head of the list */ f = fm_list; /* As long as f is non-null, there is a typeface. */ /* Remember the typeface address and point f to */ /* the next item in the list; then free the */ /* typeface structure memory. */ while(f) { c = f; f = f->next; #ifdef TRACE if (tl & (1u<<12)) Printf("fm_destroy_typefaces: free block %p, which held 'fm_facelist' structure\n",c); malloccount -= sizeof(fm_facelist); if (tl & (1u<<13)) Printf("** malloccount (fm_destroy_typefaces): \0212%d\0217\n",malloccount); #endif free(c); } /* Ensure that the list is flagged as empty. */ fm_list=NULL; } /*************************************************/ /* fm_set_system_font() */ /* */ /* Sets the static local flag to say that system */ /* fonts only should be used for font handling. */ /* This will only affect any fonts claimed with */ /* e.g. fm_find_font after this function has */ /* been called. */ /* */ /* Parameters: 1 to use system font, 0 to allow */ /* outline fonts. */ /*************************************************/ void fm_set_system_font(int systemfont) { fm_systemfont = systemfont; } /*************************************************/ /* fm_system_font() */ /* */ /* Returns 1 if the font library is currently */ /* using system font for any new font finds, or */ /* 0 if outline fonts are allowed. This is */ /* intended for external callers only (it is */ /* faster to use the fm_systemfont variable */ /* directly in internal routines). */ /*************************************************/ int fm_system_font(void) { return fm_systemfont; } /*************************************************/ /* fm_init() */ /* */ /* Initialises the library for use. */ /* */ /* Parameters: 1 if the library is to only use */ /* the system font from the outset, */ /* or 0 to allow outline fonts; */ /* */ /* The 'base font' size, if going */ /* to use the fm_size function to */ /* allow an abstracted font size */ /* selection method (see fm_size). */ /*************************************************/ void fm_init(int systemfont, int base_size) { fm_destroy_typefaces(); fm_set_system_font(systemfont); fm_init_sizes(base_size); } /*************************************************/ /* fm_init_sizes() */ /* */ /* Sets up the size array for FONT SIZE=xxx and */ /* related attributes, based on the given base */ /* font size. */ /* */ /* Parameters: The 'base font' size. */ /*************************************************/ void fm_init_sizes(int base_size) { int size, scaleby; /* Set up the size array */ fm_sizes[0] = base_size; /* Just in case 0 gets given to fm_size by accident - more likely than a large out of range value */ for (size = 1; size <= 7; size ++) { scaleby = size - 3; fm_sizes[size] = (int) (base_size * pow(1.2, scaleby)); } } /*************************************************/ /* fm_shutdown() */ /* */ /* Tells the RISC OS Font Manager that all fonts */ /* currently marked as used in fm_handles are */ /* not needed regardless of the internal usage */ /* counter therein, and resets those counters to */ /* zero. */ /*************************************************/ void fm_shutdown(void) { int fh; for (fh = 0; fh < Limits_OS_FontHandles; fh++) { if (fm_handles[fh]) { _swix(Font_LoseFont, _IN(0), fh); fm_handles[fh] = 0; } } } /*************************************************/ /* fm_get_string_width() */ /* */ /* Given a string, and the number of chars to */ /* consider in that string, work out the width */ /* of the string. A maximum width can be given, */ /* and if it is possible to split the string */ /* (pass the character to split on), the width */ /* returned will reflect this consideration (but */ /* can still be greater than maxwid, if no split */ /* characters were found for far enough). The */ /* number of bytes used to work out the final */ /* returned width is itself returned, though any */ /* trailing spaces are included in this value */ /* even if they aren't used to get the width. */ /* */ /* Parameters: The RISC OS font handle to use in */ /* width calculations; */ /* */ /* Pointer to the string to use; */ /* */ /* Maximum width to allow if */ /* splitting the line; */ /* */ /* The maximum number of bytes of */ /* string to consider; */ /* */ /* The character to split at (such */ /* as a space), or -1 for 'don't */ /* split'; */ /* */ /* Pointer to an int, into which the */ /* number of characters used to get */ /* the returned width is placed. Any */ /* trailing spaces are skipped past */ /* and included in this returned */ /* value; */ /* */ /* Pointer to an int, into which the */ /* calculated width (in millipoints) */ /* is placed. */ /* */ /* Assumes: The two int pointers may be NULL. */ /*************************************************/ _kernel_oserror * fm_get_string_width(fm_face h, const char * s, int maxwid, int maxbytes, int split, int * bytes, int * width) { int retwidth = 0; int retbytes = 0; /* Now have to do some real work. */ if (h >= 0) { /* The outline font case */ _kernel_oserror * e = NULL; int buffer[9]; int reached; /* For Font_ScanString, negative values of maxwid will */ /* produce a positive return as it copes with RTL text. */ /* We don't want this, so skip the call if maxwid <= 0. */ #ifdef UNIFONT _swix(Font_WideFormat, _INR(0,1), h, 12); #endif if (maxwid > 0) { buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0; buffer[4] = split; e = _swix(Font_ScanString, _INR(0,5) | _IN(7) | _OUT(1) | _OUT(3), h, s, FM_GivenLength | FM_GivenBuffer | FM_Kern | FM_GivenHandle, maxwid, 0x1000000, buffer, maxbytes, &reached, &retwidth); if (!e) retbytes = reached - ((int) s); // #ifdef TRACE // { // int wi, by; // // e = _swix(Font_SetFont,_IN(0),h); // // if (!e) e = _swix(Font_StringWidth, // _INR(1,5) | _OUT(2) | _OUT(5), // // s, /* String to find width of */ // maxwid, /* Maximum width if splitting is allowed */ // 0x1000000, /* Maximum height if splitting is allowed */ // split, /* Character to split on, or -1 for no split */ // maxbytes, /* Maximum string length */ // // &wi, /* Width of scanned string */ // &by); /* Length of scanned string */ // // if (abs(wi - retwidth) > 2000 || by != retbytes) // { // Printf("fm_get_string_width: Width/Bytes mismatch in first call...\n"); // Printf(" Font_ScanString -> %d, %d\n", retwidth, retbytes); // Printf(" Font_StringWidth -> %d, %d\n", wi, by); // } // } // #endif } /* If there was no error, a split character was specified */ /* but the width is zero, the Font Manager did not find a */ /* split char before the maximum width given to it was */ /* exceeded. We want to be able to spill over in this */ /* case, so recall the Font_StringWidth in a non- */ /* splitting mode, but only look as far as the first */ /* split char (if any) to allow the string to still split */ /* up. This keeps the width as small as possible, even */ /* though individual words are wider than the space we */ /* had hoped to fit them into. */ if (!e && !retwidth && split > 0) { const char * p = s; /* Scan only as far as the first split character. */ /* */ /* Thanks to Tony Cheal for spotting this when doing */ /* tables stuff - the original Customer browser sources */ /* recognised 'some problem' with Font_StringWidth but */ /* didn't then allow any sort of splitting in this part */ /* of the code. */ while (*p && *(p++) != split); /* Now call the Font Manager without asking for a split, knowing that */ /* the string length only runs up to the split character. */ _swix(Font_ScanString, _INR(0,4) | _IN(7) | _OUT(3), h, s, FM_GivenLength | FM_Kern | FM_GivenHandle, 0x1000000, 0x1000000, p - s, &retwidth); retbytes = p - s; // #ifdef TRACE // { // int wi, by; // // _swix(Font_StringWidth, // _INR(1,5) | _OUT(2) | _OUT(5), // // s, /* String to find width of */ // 0x1000000, /* Maximum width if splitting is allowed */ // 0x1000000, /* Maximum height if splitting is allowed */ // -1, /* Character to split on, or -1 for no split */ // p - s, /* String length */ // // &wi, /* Width of scanned string */ // &by); /* Length of scanned string */ // // if (abs(wi != retwidth) > 2000 || by != retbytes) // { // Printf("fm_get_string_width: Width/Bytes mismatch in second call...\n"); // Printf(" Font_ScanString -> %d, %d\n", retwidth, retbytes); // Printf(" Font_StringWidth -> %d, %d\n", wi, by); // } // } // #endif } /* Exit if there was some error */ if (e) return e; /* Include any trailing spaces in the byte count */ while (retbytes < maxbytes && s[retbytes] == ' ') retbytes++; } else { /* The system font case. */ int wCurr, wLastSplit, oLastSplit, oCurr; /* (Macro defined in FontManage.h). Important that we take */ /* account of rounding correctly - compare with formula in */ /* fm_puts(). */ int wChar = (FM_System_Size_X(h) * 10 / (128 * wimpt_dx())) * wimpt_dx() * 400; wCurr = wLastSplit = oLastSplit = oCurr = 0; /* Whilst the byte counter is less than maxbytes and the width */ /* calculated so far is less than maxwidth, or we haven't */ /* found a split character yet, go through adding */ /* the width of a character to the width total for each char */ /* of the string. If a split character is met during this, set */ /* oLastSplit and wLastSplit to the byte counter and thus far */ /* calculated width at that point. */ while ( oCurr < maxbytes && ( (wCurr <= (unsigned) maxwid) || (split > 0) && !oLastSplit ) ) { #ifdef UNIFONT UCS4 ucs; #endif if ((split > 0) && (s[oCurr] == split)) { oLastSplit = oCurr; wLastSplit = wCurr; } #ifdef UNIFONT oCurr += UTF8_to_UCS4(s + oCurr, &ucs); wCurr += unifont_widechar(ucs) ? wChar * 2 : wChar; #else wCurr += wChar; oCurr ++; #endif } /* If the current width is greater than the maximum width and there is */ /* a split point, go back to that last split point. */ if ((wCurr > (unsigned) maxwid) && oLastSplit) { oCurr = oLastSplit; wCurr = wLastSplit; } /* Include any trailing spaces in the byte count */ while ((oCurr < maxbytes) && (s[oCurr] == ' ')) oCurr++; retbytes = oCurr; retwidth = wCurr; } if (bytes) *bytes = retbytes; if (width) *width = retwidth; return NULL; } /*************************************************/ /* fm_token_font_info() */ /* */ /* Looks at a token and returns information on */ /* the best font to use with it, e.g. bold, */ /* italic, a typeface number, etc. */ /* */ /* The returned typeface number is based on the */ /* array of typeface names defined at the top of */ /* this file (called redraw_faces). */ /* */ /* Parameters: Pointer to the HStream struct */ /* (token) of interest; */ /* */ /* Address of an int into which the */ /* typeface number is placed; */ /* */ /* Address of an int into which the */ /* font size to use is returned (in */ /* 16ths of a point); */ /* */ /* Address of an int into which 1 is */ /* placed if italics should be used */ /* (else 0 is returned); */ /* */ /* Address of an int into which 1 is */ /* placed if bold should be used */ /* (else 0 is returned). */ /*************************************************/ void fm_token_font_info(HStream * t, int * facenum, int * size, int * italic, int * bold) { int flags; flags = t->style; *facenum = 0; /* 0 = Serif */ *bold = *italic = 0; /* May want to scale the size for certain tag types */ if (ISSUP(t) || ISSUB(t)) *size = (choices.font_size * 3) / 5; else *size = choices.font_size; /* Scale the size according to the font size specifier */ /* in the token */ #ifdef TRACE if (t->fontsize < 1 || t->fontsize > 7) { if (tl & (1u<<10)) Printf("fm_token_font_info: fontsize '%d' out of range\n",t->fontsize); t->fontsize = 3; } #endif *size += fm_size(t->fontsize) - choices.font_size; /* Set font details according to specific tags */ /* (or any header, with H_MASK). The macros */ /* defined in HTMLLib:tags.h. */ if (flags & (ITALIC | BLOCKQUOTE)) *italic = 1; if (flags & (BOLD | DT)) *bold = 1; if (flags & (H_MASK | ADDRESS)) *facenum = 1; /* 1 = Sans serif */ if (flags & (PRE | TT)) *facenum = 2; /* 2 = Monospaced */ /* Set bold, italic and size details according */ /* to the header level (if the token represents */ /* header information, that is). */ switch (redraw_header(flags)) { case 1: *bold = 1, *size *= 2; break; case 2: *bold = 1, *size = (*size * 8) / 5; break; case 3: *bold = 1, *size = (*size * 3) / 2; break; case 4: *bold = 1, *size = (*size * 4) / 3; break; case 5: *bold = 1, *size = (*size * 8) / 7; break; case 6: *bold = 1; break; } } /*************************************************/ /* fm_find_token_font() */ /* */ /* Returns an appropriate RISC OS font handle in */ /* which the contents of a given token should be */ /* rendered, optionally recording the usage in a */ /* given browser_data structure. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the font (may be NULL */ /* for a non-browser specific font */ /* claim); */ /* */ /* Pointer to the HStream struct */ /* (token) to find the font for; */ /* */ /* 1 to ignore bold and italic flags */ /* and just find plain text, else 0. */ /*************************************************/ fm_face fm_find_token_font(browser_data * b, HStream * t, int ignore_styles) { int facenum, size, bold, italic; /* Get the recommended font */ fm_token_font_info(t, &facenum, &size, &italic, &bold); if (ignore_styles) facenum = italic = bold = 0; /* Return the font handle - note that the typeface name is */ /* passed to the font managing routines by looking up the */ /* typeface number in the redraw_faces array defined at */ /* the top of this file, and that 100% aspect ratio is */ /* always used due to 'size' being passed in for both the */ /* x and y sizes of the font. */ if (facenum == 2) return fm_find_font(b, fm_faces[facenum], (size * choices.tt_aspect) / 100, size, italic, bold); else return fm_find_font(b, fm_faces[facenum], size, size, italic, bold); }