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.png

    In 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.png

    Und nochmal ein wenig mehr text

    Courier New im Monomode, Größe 14
    http://www.urbsch.at/files/bsplang.png

    Aussehen sollte das gabze aber in etwa so:
    http://www.urbsch.at/files/so.png

    Da 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*


Anmelden zum Antworten