Freetype problem bei kleiner schriftgröße.
-
Hi, ich bastel gerade mit Freetype rum un hab ein Problem mit der Qualität der Schrift, wenn die schriftgröße relativ klein wird (so 10-16). Im Antialiase modus (default) sehen zwar normale schriften gut aus, aber kleine sachen wie Courier New auf 12 wird zu verwaschen ums ordentlich lesen zu können. Stellt man den Rendermode auf mono um hat man zwar harte kanten (konsolen schrift halt), doch leider läßt das ergebnis zu wünschen übrig. Ich glaub ein Bild sagt mehr als 1000 worte:
In groß:
Courier New im Monomode, Größe 48
http://www.urbsch.at/files/cnmonobig.png
Courier New im Antialiased, Größe 48
http://www.urbsch.at/files/cnaabig.pngIn klein
Courier New im Monomode, Größe 14
http://www.urbsch.at/files/cnmonosmall.png
Courier New im Antialiased, Größe 14
http://www.urbsch.at/files/cnaasmall.pngUnd nochmal ein wenig mehr text
Courier New im Monomode, Größe 14
http://www.urbsch.at/files/bsplang.pngAussehen sollte das gabze aber in etwa so:
http://www.urbsch.at/files/so.pngDa der text ja scheinbar richtig gerendert wird, hab ich das gefühl das es einstellungen bei Freetype sein müßen um die schrift schöner zu rendern, leider bin ich nicht fündig geworden. Hoffe ihr könnt mir Helfen
Fals es doch am Code liegen sollte, hier nochmal die Relevanten Ausschnitte
Glyph Image generieren, für jeden buschstaben im string wird von freetype ein bild generiert das dann mit den unten stehenden funktionen auf das surface gezeichnet wird.
for(std::string::size_type i = 0; i < str.size(); i++) { int glyph_index = FT_Get_Char_Index( face, str[i] ); FT_Render_Mode renderMode = FT_RENDER_MODE_MONO; int error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); if ( error ) continue; /* ignore errors */ /* convert to an anti-aliased bitmap */ error = FT_Render_Glyph( face->glyph, renderMode ); if ( error ) continue; if (renderMode == FT_RENDER_MODE_MONO) { FT_Bitmap tempbitmap; FT_Bitmap_New(&tempbitmap); // Wenn bei freetype per monochrome gerendert wird kriegt man normalerweise eine echt // "bitmap" also 1 bit pro pixel. Zur leichteren verarbeitung kann man mit // FT_Bitmap_Convert1 byte pro pixel draus machen FT_Bitmap_Convert( library, &slot->bitmap, &tempbitmap, 1); DrawGlpyhOnSurfaceMonochrome(surface, tempbitmap, point, Vector2D(slot->bitmap_left, slot->bitmap_top)); FT_Bitmap_Done( library, &tempbitmap ); } else { DrawGlpyhOnSurfaceAntiAlias(surface, slot->bitmap, point, Vector2D(slot->bitmap_left, slot->bitmap_top)); } point.x += slot->advance.x / 64; point.y += slot->advance.y / 64; }
Glyph Image auf meine "textur" (Surface) malen
void DrawGlpyhOnSurfaceAntiAlias(Surface &surface, FT_Bitmap &bmp, Vector2D position, Vector2D offset) { for (int y = 0; y < bmp.rows; y++) { for (int x = 0; x < bmp.width; x++) { byte color = bmp.buffer[x + y * bmp.width]; // freetypedoku zu glyph metrics angucken int realX = x + position.x + offset.x; int realY = y + position.y - offset.y; Color<byte> fontColor(255, 255, 255, 255); Color<byte> pixelColor = surface.GetPixel(realX, realY); float alpha = (float)color / 255.0f; Color<byte> newColor = (fontColor * alpha) + (pixelColor * (1 - alpha)); surface.SetPixel(realX, realY, newColor); } } } void DrawGlpyhOnSurfaceMonochrome(Surface &surface, FT_Bitmap &bmp, Vector2D position, Vector2D offset) { for (int y = 0; y < bmp.rows; y++) { for (int x = 0; x < bmp.width; x++) { byte color = bmp.buffer[x + y * bmp.width]; // freetypedoku zu glyph metrics angucken int realX = x + position.x + offset.x; int realY = y + position.y - offset.y; if (color > 0) { // "bitmap" mit 1 byte pro pixel, aber trozdem ur 0 und 1 color = 255; surface.SetPixel(realX, realY, Color<byte>(color, color, color, color)); } } } }
Ja, beim code kann man bestimmt noch einiges besser machen aber ich bin noch am rumspielen
Gruss
-
*hußt bytecode interpreter hußt*