Scalable Screen Font: Difference between revisions

m
updated for SSFN 2.0
[unchecked revision][unchecked revision]
mNo edit summary
m (updated for SSFN 2.0)
Line 1:
Scalable Screen Font is a compressed font format which comes with a small, free, MIT licensed rendering library. It was designed specially for hobby OS developers, therefore it has minimal dependencies. It is also floating-point arithmetic free, so it will work even if your kernel hasn't initialized the FPU or SSE yet.
 
= Supported Font Types =
 
* Bitmap - you can convert [[PC Screen Font]] with UNICODE table into SSFN directly. X11 Bitmap Distribution Format, Portable Compiled Fonts and Windows FNT/FON files are also supported.
* Pixmap - to have colorful emoji icons, you can convert TGA and PNG files into SSFN fonts.
* Vector - vector based fonts can be converted from PostScript Type1, OpenType and [[TrueType_Fonts|TrueType fonts]].
 
Fonts are compressed, and in case of vector fonts, with a data-loss compression. You can set the compression ratio to balance between quality and font size. With the same quality as a typical OpenType file, the SSFN font usually takes only the half the file size (or less).
 
= Library =
Line 15:
== Simple Renderer ==
 
Designed specially for OS consoles, has only one function. It can render unscaled bitmap fonts directly to the framebuffer. Has absolutely no dependencies, and compiles to less than atwo kilobytekilobytes of code.
 
<source lang="c">
#define SSFN_NOIMPLEMENTATION /* don't include the normal renderer implementation */
#define SSFN_CONSOLEBITMAP_HICOLOR /* use the special renderer for hicolor packed pixels */
#include <ssfn.h>
 
/* set up context by global variables */
ssfn_fontssfn_src = &_binary_console_sfn_start; /* the bitmap font to use */
ssfn_dst_ptrssfn_dst.ptr = 0xE0000000; /* framebuffer address and bytes per line */
ssfn_dst_pitchssfn_dst.p = 4096;
ssfn_fgssfn_dst.fg = 0xFFFF; /* colors, white on black */
ssfn_bgssfn_dst.bg = 0;
ssfn_xssfn_dst.x = 100; /* coordinates to draw to */
ssfn_yssfn_dst.y = 200;
 
/* render one glyph directly to the screen and then adjust ssfn_xssfn_dst.x and ssfn_yssfn_dst.y */
ssfn_putc(0x41);
</source>
Line 37 ⟶ 36:
== Normal Renderer ==
 
There's another for user space applications. This one can render all three types of fonts, supports gzip compressed fonts, it can scale, antialias, autohintanti-alias and kern glyphs. Has minimal libc dependencies (memset, memcmp, realloc, free) and compiles to about 2228 kilobytes of code.
 
<source lang="c">
#define SSFN_NOIMPLEMENTATIONSSFN_IMPLEMENTATION /* don't includeuse the normal renderer implementation */
#include <ssfn.h>
 
ssfn_t ctx; /* the renderer context */
ssfn_glyph_tssfn_buf_t *glyphbuf; /* the returneddestination rasterizedpixel bitmapbuffer */
 
/* you don't need to initialize the library, just make sure the context is zerod out */
Line 49:
 
/* add one or more fonts to the context. Fonts must be already in memory */
ssfn_load(&ctx, &_binary_times_sfn_start, 0); /* you can add different styles... */
ssfn_load(&ctx, &_binary_timesbold_sfn_start, 0);
ssfn_load(&ctx, &_binary_timesitalic_sfn_start, 0);
ssfn_load(&ctx, &_binary_emoji_sfn_start, 0); /* ...or different UNICODE ranges */
ssfn_load(&ctx, &_binary_cjk_sfn_start, 0);
 
/* select the typeface to use */
ssfn_select(&ctx,
SSFN_FAMILY_SERIF, NULL, /* family */
SSFN_STYLE_REGULAR | SSFN_STYLE_UNDERLINE, 64, /* style and size */
SSFN_MODE_BITMAP64 /* rendering modesize */
);
 
/* describe the destination buffer. Could be a 32 bit linear framebuffer as well */
/* rasterize a glyph for the 0x41 UNICODE code point into a newly allocated bitmap */
pen_xbuf.ptr += glyphsdlsurface->adv_xpixels; /* adjustaddress of the cursorbuffer */
glyph = ssfn_render(&ctx, 0x41);
buf.w = &glyphsdlsurface->data w; /* bitmap datawidth */
pen_xbuf.h += glyphsdlsurface->adv_xh; /* adjust X for the next glyphheight */
pen_ybuf.p += glyphsdlsurface->adv_ypitch; /* ssfn handles verticalbytes fontsper tooline */
if(rtl) buf.x = buf.y = 100; /* set up cursorpen position for the next glyph */
pen_ybuf.fg += glyph->adv_y0xFF808080; /* adjust the Y coordinate thisforeground timecolor */
 
/* rasterize the first glyph in an UTF-8 string into a 32 bit packed pixel buffer */
/* display the bitmap on your screen */
glyph = ssfn_render(&ctx, 0x41&buf, "A");
my_draw_glyph(
pen_x, pen_y - glyph->baseline, /* coordinates to draw to */
glyph->w, glyph->h, glyph->pitch, /* bitmap dimensions */
&glyph->data /* bitmap data */
);
pen_x += glyph->adv_x; /* adjust the cursor */
pen_y += glyph->adv_y; /* ssfn handles vertical fonts too */
 
/* free resources */
free(glyph); /* no special treatment for freeing glyphs */
ssfn_free(&ctx); /* free the renderer context's internal buffers */
</source>
The renderer takes care of the font direction, it uses horizontal or vertical alignment automatically. It cannot determine right-to-left though, for that you'll need
 
It is not as simple as one would think, because it's not enough to know if the given UNICODE character belongs to a right-to-left scripting system,minimal BiDi requires a minimal state machine too. That has to be implemented in the text renderer (or text shaping library) that's built on top of the low level rasterizer. The [http://www.unicode.org/reports/tr9/ algorithm to properly display bidirectional texts] is specified by UNICODE. But once you have decided that you need to draw a glyph in right-to-left direction, thesejust arepass theSSFN_STYLE_RTL requiredto steps:ssfn_select().
=== Left-to-right text ===
 
This is the default. Left to right requires nothing special, only to subtract baseline and add the advance value to your current pen position.
<source lang="c">
my_draw_glyph(pen_x, pen_y - glyph->baseline, ...); /* position the glyph vertically */
 
pen_x += glyph->adv_x; /* adjust X for the next glyph */
</source>
 
=== Vertical text ===
 
To display vertical fonts properly, you should subtract the baseline from the X coordinate before you draw.
<source lang="c">
my_draw_glyph(pen_x - glyph->baseline, pen_y, ...); /* position the glyph horizontally */
 
pen_y += glyph->adv_y; /* adjust the Y coordinate this time */
</source>
 
=== Right-to-left text ===
 
It is not as simple as one would think, because it's not enough to know if the given UNICODE character belongs to a right-to-left scripting system, BiDi requires a minimal state machine too. That has to be implemented in the text renderer (or text shaping library) that's built on top of the low level rasterizer. The [http://www.unicode.org/reports/tr9/ algorithm to properly display bidirectional texts] is specified by UNICODE. But once you have decided that you need to draw a glyph in right-to-left direction, these are the required steps:
<source lang="c">
my_draw_glyph(pen_x - glyph->w, pen_y, ...); /* subtract the glyph's width first */
 
pen_x -= glyph->adv_x; /* and subtract the advance instead of adding */
</source>
 
Putting every direction variations all together:
<source lang="c">
if(glyph->adv_y) { /* things to temporarily adjust before drawing */
x = pen_x - glyph->baseline;
y = pen_y;
} else {
x = pen_x - (rtl ? glyph->w : 0);
y = pen_y - glyph->baseline;
}
 
my_draw_glyph(x, y, ...);
 
if(rtl) /* set up cursor position for the next glyph */
pen_x -= glyph->adv_x;
else
pen_x += glyph->adv_x;
pen_y += glyph->adv_y;
</source>
 
= Links =
Line 132 ⟶ 86:
== External Links ==
* [https://forum.osdev.org/viewtopic.php?f=2&t=33719 OSDEV forum] on Scalable Screen Fonts
* https://gitlab.com/bztsrc/scalable-fontfont2 source code repository
* [https://gitlab.com/bztsrc/scalable-fontfont2/blob/master/docs/sfn_format.md .sfn file format] description
* [https://gitlab.com/bztsrc/scalable-fontfont2/blob/master/docs/API.md SSFN API] documentation
 
[[Category:Graphical UI]]
Anonymous user