mirror of https://github.com/buggins/dlangui.git
support font antialiasing and hinting settings
This commit is contained in:
parent
ddc97cd563
commit
269b1736d3
|
|
@ -134,6 +134,12 @@ class Font : RefCountedObject {
|
|||
/// returns true if font object is not yet initialized / loaded
|
||||
abstract @property bool isNull();
|
||||
|
||||
/// return true if antialiasing is enabled, false if not enabled
|
||||
@property bool antialiased() {
|
||||
return size >= FontManager.instance.minAnitialiasedFontSize;
|
||||
}
|
||||
|
||||
|
||||
private int _fixedFontDetection = -1;
|
||||
|
||||
/// returns true if font has fixed pitch (all characters have equal width)
|
||||
|
|
@ -415,10 +421,24 @@ struct FontList {
|
|||
}
|
||||
}
|
||||
|
||||
/// default min font size for antialiased fonts (e.g. if 16 is set, for 16+ sizes antialiasing will be used, for sizes <=15 - antialiasing will be off)
|
||||
const int DEF_MIN_ANTIALIASED_FONT_SIZE = 0; // 0 means always use antialiasing
|
||||
|
||||
/// Hinting mode (currently supported for FreeType only)
|
||||
enum HintingMode : int {
|
||||
/// based on information from font (using bytecode interpreter)
|
||||
Normal,
|
||||
/// force autohinting algorithm even if font contains hint data
|
||||
AutoHint,
|
||||
/// disable hinting completely
|
||||
Disabled
|
||||
}
|
||||
|
||||
/// Access points to fonts.
|
||||
class FontManager {
|
||||
protected static __gshared FontManager _instance;
|
||||
protected static __gshared int _minAnitialiasedFontSize = DEF_MIN_ANTIALIASED_FONT_SIZE;
|
||||
protected static __gshared HintingMode _hintingMode = HintingMode.Normal;
|
||||
|
||||
/// sets new font manager singleton instance
|
||||
static @property void instance(FontManager manager) {
|
||||
|
|
@ -443,6 +463,26 @@ class FontManager {
|
|||
/// removes entries not used after last call of checkpoint() or cleanup()
|
||||
abstract void cleanup();
|
||||
|
||||
/// get min font size for antialiased fonts
|
||||
@property int minAnitialiasedFontSize() {
|
||||
return _minAnitialiasedFontSize;
|
||||
}
|
||||
|
||||
/// set new min font size for antialiased fonts
|
||||
@property void minAnitialiasedFontSize(int size) {
|
||||
_minAnitialiasedFontSize = size;
|
||||
}
|
||||
|
||||
/// get current hinting mode
|
||||
@property HintingMode hintingMode() {
|
||||
return _hintingMode;
|
||||
}
|
||||
|
||||
/// set hinting mode
|
||||
@property void hintingMode(HintingMode mode) {
|
||||
_hintingMode = mode;
|
||||
}
|
||||
|
||||
~this() {
|
||||
Log.d("Destroying font manager");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -246,14 +246,14 @@ private class FreeTypeFontFile {
|
|||
//FONT_GUARD
|
||||
int glyph_index = getCharIndex(code, def_char);
|
||||
int flags = FT_LOAD_DEFAULT;
|
||||
const bool _drawMonochrome = false;
|
||||
const bool _drawMonochrome = _size < FontManager.instance.minAnitialiasedFontSize;
|
||||
flags |= (!_drawMonochrome ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO);
|
||||
if (withImage)
|
||||
flags |= FT_LOAD_RENDER;
|
||||
//if (_hintingMode == HINTING_MODE_AUTOHINT)
|
||||
// flags |= FT_LOAD_FORCE_AUTOHINT;
|
||||
//else if (_hintingMode == HINTING_MODE_DISABLED)
|
||||
// flags |= FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
|
||||
if (FontManager.instance.hintingMode == HintingMode.AutoHint)
|
||||
flags |= FT_LOAD_FORCE_AUTOHINT;
|
||||
else if (FontManager.instance.hintingMode == HintingMode.Disabled)
|
||||
flags |= FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING;
|
||||
int error = FT_Load_Glyph(
|
||||
_face, /* handle to face object */
|
||||
glyph_index, /* glyph index */
|
||||
|
|
@ -276,8 +276,30 @@ private class FreeTypeFontFile {
|
|||
int sz = w * cast(int)h;
|
||||
if (sz > 0) {
|
||||
glyph.glyph = new ubyte[sz];
|
||||
for (int i = 0; i < sz; i++)
|
||||
glyph.glyph[i] = bitmap.buffer[i];
|
||||
if (_drawMonochrome) {
|
||||
// monochrome bitmap
|
||||
ubyte mask = 0x80;
|
||||
ubyte * ptr = bitmap.buffer;
|
||||
ubyte * dst = glyph.glyph.ptr;
|
||||
for ( int y=0; y<h; y++ ) {
|
||||
ubyte * row = ptr;
|
||||
mask = 0x80;
|
||||
for ( int x=0; x<w; x++ ) {
|
||||
*dst++ = (*row & mask) ? 0xFF : 00;
|
||||
mask >>= 1;
|
||||
if ( !mask && x != w-1) {
|
||||
mask = 0x80;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
ptr += bitmap.pitch;
|
||||
}
|
||||
|
||||
} else {
|
||||
// antialiased
|
||||
for (int i = 0; i < sz; i++)
|
||||
glyph.glyph[i] = bitmap.buffer[i];
|
||||
}
|
||||
}
|
||||
version (USE_OPENGL) {
|
||||
glyph.id = nextGlyphId();
|
||||
|
|
|
|||
|
|
@ -142,12 +142,24 @@ class Win32Font : Font {
|
|||
&identity );
|
||||
if (res == GDI_ERROR)
|
||||
return null;
|
||||
int gs = GetGlyphOutlineW( _drawbuf.dc, cast(wchar)ch,
|
||||
GGO_GRAY8_BITMAP, //GGO_METRICS
|
||||
&metrics,
|
||||
0,
|
||||
NULL,
|
||||
&identity );
|
||||
int gs = 0;
|
||||
// calculate bitmap size
|
||||
if (antialiased) {
|
||||
gs = GetGlyphOutlineW( _drawbuf.dc, cast(wchar)ch,
|
||||
GGO_GRAY8_BITMAP,
|
||||
&metrics,
|
||||
0,
|
||||
NULL,
|
||||
&identity );
|
||||
} else {
|
||||
gs = GetGlyphOutlineW( _drawbuf.dc, cast(wchar)ch,
|
||||
GGO_BITMAP,
|
||||
&metrics,
|
||||
0,
|
||||
NULL,
|
||||
&identity );
|
||||
}
|
||||
|
||||
if (gs >= 0x10000 || gs < 0)
|
||||
return null;
|
||||
|
||||
|
|
@ -167,33 +179,65 @@ class Win32Font : Font {
|
|||
g.glyph = new ubyte[g.blackBoxX * g.blackBoxY];
|
||||
if (gs>0)
|
||||
{
|
||||
ubyte[] glyph = new ubyte[gs];
|
||||
res = GetGlyphOutlineW( _drawbuf.dc, cast(wchar)ch,
|
||||
GGO_GRAY8_BITMAP, //GGO_METRICS
|
||||
&metrics,
|
||||
gs,
|
||||
glyph.ptr,
|
||||
&identity );
|
||||
if (res==GDI_ERROR)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int glyph_row_size = (g.blackBoxX + 3) / 4 * 4;
|
||||
ubyte * src = glyph.ptr;
|
||||
ubyte * dst = g.glyph.ptr;
|
||||
for (int y = 0; y < g.blackBoxY; y++)
|
||||
{
|
||||
for (int x = 0; x < g.blackBoxX; x++)
|
||||
{
|
||||
ubyte b = src[x];
|
||||
if (b>=64)
|
||||
b = 63;
|
||||
b = (b<<2) & 0xFC;
|
||||
dst[x] = b;
|
||||
}
|
||||
src += glyph_row_size;
|
||||
dst += g.blackBoxX;
|
||||
}
|
||||
if (antialiased) {
|
||||
// antialiased glyph
|
||||
ubyte[] glyph = new ubyte[gs];
|
||||
res = GetGlyphOutlineW( _drawbuf.dc, cast(wchar)ch,
|
||||
GGO_GRAY8_BITMAP, //GGO_METRICS
|
||||
&metrics,
|
||||
gs,
|
||||
glyph.ptr,
|
||||
&identity );
|
||||
if (res==GDI_ERROR)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int glyph_row_size = (g.blackBoxX + 3) / 4 * 4;
|
||||
ubyte * src = glyph.ptr;
|
||||
ubyte * dst = g.glyph.ptr;
|
||||
for (int y = 0; y < g.blackBoxY; y++)
|
||||
{
|
||||
for (int x = 0; x < g.blackBoxX; x++)
|
||||
{
|
||||
ubyte b = src[x];
|
||||
if (b>=64)
|
||||
b = 63;
|
||||
b = (b<<2) & 0xFC;
|
||||
dst[x] = b;
|
||||
}
|
||||
src += glyph_row_size;
|
||||
dst += g.blackBoxX;
|
||||
}
|
||||
} else {
|
||||
// bitmap glyph
|
||||
ubyte[] glyph = new ubyte[gs];
|
||||
res = GetGlyphOutlineW( _drawbuf.dc, cast(wchar)ch,
|
||||
GGO_BITMAP, //GGO_METRICS
|
||||
&metrics,
|
||||
gs,
|
||||
glyph.ptr,
|
||||
&identity );
|
||||
if (res==GDI_ERROR)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
int glyph_row_bytes = ((g.blackBoxX + 7) / 8);
|
||||
int glyph_row_size = (glyph_row_bytes + 3) / 4 * 4;
|
||||
ubyte * src = glyph.ptr;
|
||||
ubyte * dst = g.glyph.ptr;
|
||||
for (int y = 0; y < g.blackBoxY; y++)
|
||||
{
|
||||
for (int x = 0; x < g.blackBoxX; x++)
|
||||
{
|
||||
int offset = x >> 3;
|
||||
int shift = 7 - (x & 7);
|
||||
ubyte b = ((src[offset] >> shift) & 1) ? 255 : 0;
|
||||
dst[x] = b;
|
||||
}
|
||||
src += glyph_row_size;
|
||||
dst += g.blackBoxX;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -217,6 +261,7 @@ class Win32Font : Font {
|
|||
lf.lfFaceName[def.face.length] = 0;
|
||||
lf.lfHeight = size; //-size;
|
||||
lf.lfItalic = italic;
|
||||
lf.lfWeight = weight;
|
||||
lf.lfOutPrecision = OUT_OUTLINE_PRECIS; //OUT_TT_ONLY_PRECIS;
|
||||
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||||
//lf.lfQuality = NONANTIALIASED_QUALITY; //ANTIALIASED_QUALITY;
|
||||
|
|
|
|||
|
|
@ -859,7 +859,7 @@ int myWinMain(void* hInstance, void* hPrevInstance, char* lpCmdLine, int iCmdSho
|
|||
|
||||
|
||||
/// testing freetype font manager
|
||||
static if (false) {
|
||||
version(USE_FREETYPE) {
|
||||
import dlangui.graphics.ftfonts;
|
||||
import win32.shlobj;
|
||||
FreeTypeFontManager ftfontMan = new FreeTypeFontManager();
|
||||
|
|
@ -889,6 +889,14 @@ int myWinMain(void* hInstance, void* hPrevInstance, char* lpCmdLine, int iCmdSho
|
|||
ftfontMan.registerFont(fontsPath ~ "timesbd.ttf", FontFamily.Serif, "Times New Roman", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "timesbi.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "timesi.ttf", FontFamily.Serif, "Times New Roman", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consola.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolab.ttf", FontFamily.MonoSpace, "Consolas", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolai.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "consolaz.ttf", FontFamily.MonoSpace, "Consolas", true, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdana.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanab.ttf", FontFamily.SansSerif, "Verdana", false, FontWeight.Bold);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanai.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Normal);
|
||||
ftfontMan.registerFont(fontsPath ~ "verdanaz.ttf", FontFamily.SansSerif, "Verdana", true, FontWeight.Bold);
|
||||
FontManager.instance = ftfontMan;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue