Mercurial > projects > mde
changeset 51:387a80724c35
Enabled LCD font rendering mode (only tested with freetype's sub-pixel rendering disabled).
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Mon, 02 Jun 2008 14:34:24 +0100 |
parents | f68ae1d667f9 |
children | 94a4ddb549e5 f000d6cd0f74 |
files | data/L10n/OptionsFont.mtt data/conf/options.mtt mde/resource/FontTexture.d mde/resource/font.d mde/sdl.d |
diffstat | 5 files changed, 58 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/data/L10n/OptionsFont.mtt Sun Jun 01 18:22:54 2008 +0100 +++ b/data/L10n/OptionsFont.mtt Mon Jun 02 14:34:24 2008 +0100 @@ -1,4 +1,4 @@ {MT01} {en-GB} -<entry|lcdFilter=["LCD filtering","Enable or disable LCD filtering. Note that the FreeType library may be compiled with this support disabled due to patents."]> -<entry|renderMode=["Font rendering mode","Controls how fonts are rendered: in gray-scale, or for LCDs (with a horizontal (normal) or vertical layout, with an RGB (normal) or BGR sub-pixel mode."]> +<entry|lcdFilter=["LCD filtering","Enable or disable sub-pixel rendering. Note that the FreeType library may be compiled without support due to patent issues."]> +<entry|renderMode=["Font rendering mode","Controls how fonts are rendered: in gray-scale, or for LCDs (with a horizontal (usual) or vertical layout, with an RGB (usual) or BGR sub-pixel mode."]>
--- a/data/conf/options.mtt Sun Jun 01 18:22:54 2008 +0100 +++ b/data/conf/options.mtt Mon Jun 02 14:34:24 2008 +0100 @@ -8,7 +8,7 @@ {font} <int|lcdFilter=0> -<int|hinting=0> +<int|renderMode=0> {video} <bool|noFrame=false>
--- a/mde/resource/FontTexture.d Sun Jun 01 18:22:54 2008 +0100 +++ b/mde/resource/FontTexture.d Mon Jun 02 14:34:24 2008 +0100 @@ -32,6 +32,7 @@ import Utf = tango.text.convert.Utf; import tango.util.log.Log : Log, Logger; +import tango.io.Stdout; private Logger logger; static this () { @@ -213,7 +214,7 @@ //throw new fontGlyphException ("Unsupported freetype bitmap: b.pitch != b.width"); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei (GL_UNPACK_ROW_LENGTH, b.pitch); + //glPixelStorei (GL_UNPACK_ROW_LENGTH, b.pitch); GlyphAttribs ga; ga.w = b.width; @@ -222,6 +223,10 @@ ga.top = g.bitmap_top; ga.advanceX = g.advance.x >> 6; ga.index = gi; + if (b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_LCD) + ga.w /= 3; + if (b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_LCD_V) + ga.h /= 3; foreach (ref t; tex) { if (t.addGlyph (ga)) @@ -236,14 +241,37 @@ gotTexSpace: glBindTexture(GL_TEXTURE_2D, ga.texID); GLenum format; - if (b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_GRAY && b.num_grays == 256) + ubyte[] buffer; // use our own pointer, since for LCD modes we need to perform a conversion + if (b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_GRAY && b.num_grays == 256) { + buffer = b.buffer[0..b.pitch*b.rows]; format = GL_LUMINANCE; - else if (b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_LCD || - b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_LCD_V) { - if (fontOpts.renderMode & RENDER_LCD_BGR) - format = GL_BGR; - else - format = GL_RGB; + } else if (b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_LCD) { + // NOTE: Can't seem to get OpenGL to read freetype's RGB buffers properly, so convent. + /* NOTE: Sub-pixel rendering probably also needs filtering. I haven't tried, since it's + * disabled in my build of the library. For a tutorial on the filtering, see: + * http://dmedia.dprogramming.com/?n=Tutorials.TextRendering1 */ + buffer = new ubyte[b.width*b.rows]; + for (uint i = 0; i < b.rows; ++i) + for (uint j = 0; j < b.width; j+= 3) + { + buffer[i*b.width + j + 0] = b.buffer[i*b.pitch + j + 0]; + buffer[i*b.width + j + 1] = b.buffer[i*b.pitch + j + 1]; + buffer[i*b.width + j + 2] = b.buffer[i*b.pitch + j + 2]; + } + + format = (fontOpts.renderMode & RENDER_LCD_BGR) ? GL_BGR : GL_RGB; + } else if (b.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_LCD_V) { + // NOTE: Notes above apply. Only in this case converting the buffers seems essential. + buffer = new ubyte[b.width*b.rows]; + for (uint i = 0; i < b.rows; ++i) + for (uint j = 0; j < b.width; ++j) + { + // i/3 is the "real" row, b.width*3 is our width (with subpixels), j is column, + // i%3 is sub-pixel (R/G/B). i/3*3 necessary to round to multiple of 3 + buffer[i/3*b.width*3 + 3*j + i%3] = b.buffer[i*b.pitch + j]; + } + + format = (fontOpts.renderMode & RENDER_LCD_BGR) ? GL_BGR : GL_RGB; } else throw new fontGlyphException ("Unsupported freetype bitmap format"); @@ -251,7 +279,7 @@ ga.x, ga.y, ga.w, ga.h, format, GL_UNSIGNED_BYTE, - cast(void*) b.buffer); + cast(void*) buffer.ptr); cachedGlyphs[chr] = ga; } @@ -352,6 +380,7 @@ Line line; line.yPos = nextYPos; line.height = attr.h * EXTRA_H; + Stdout.format ("Creating new line of height {}", line.height).newline; line.length = attr.w; size_t i = 0; while (i < lines.length && lines[i].height < line.height) ++i; @@ -388,7 +417,7 @@ * FT_LOAD_TARGET_MONO is unsupported. * * lcdFilter should come from enum FT_LcdFilter: - * FT_LCD_FILTER_NONE, FT_LCD_FILTER_DEFAULT, FT_LCD_FILTER_LIGHT */ + * FT_LCD_FILTER_NONE = 0, FT_LCD_FILTER_DEFAULT = 1, FT_LCD_FILTER_LIGHT = 2 */ mixin (impl!("int renderMode, lcdFilter;")); static this() {
--- a/mde/resource/font.d Sun Jun 01 18:22:54 2008 +0100 +++ b/mde/resource/font.d Mon Jun 02 14:34:24 2008 +0100 @@ -71,13 +71,20 @@ logger.warn (logger.format (tmp, "Using an untested FreeType version: {}.{}.{}", maj, min, patch)); } - // Set LCD filtering method - if (FT_Library_SetLcdFilter(library, cast(FT_LcdFilter)fontOpts.lcdFilter)) { + // Set LCD filtering method (note: FT_Library_SetLcdFilter can still complain with + // FT_LcdFilter.FT_LCD_FILTER_NONE). + if (fontOpts.lcdFilter && FT_Library_SetLcdFilter(library, cast(FT_LcdFilter)fontOpts.lcdFilter)) { // If setting failed, leave at default (disabled status). Note: it is disabled by // default because the code isn't compiled in by default, to avoid patents. - logger.warn ("Bad/unsupported LCD filter option; disabling."); + logger.warn ("Bad/unsupported LCD filter option; disabling LCD filtering."); + logger.warn ("Your FreeType 2 library may compiled without support for LCD/sub-pixel rendering."); Options.setInt ("font", "lcdFilter", FT_LcdFilter.FT_LCD_FILTER_NONE); } + const RMF = FT_LOAD_TARGET_MONO | FT_LOAD_TARGET_LCD | FT_LOAD_TARGET_LCD_V; + if (fontOpts.renderMode & RMF && fontOpts.lcdFilter == 0) { + logger.warn ("Using LCD rendering when LCD filtering is disabled has no effect; disabling."); + Options.setInt ("font", "renderMode", FT_LOAD_TARGET_NORMAL); + } /* Load font settings * @@ -208,7 +215,11 @@ * This function will only actually update the cache if it is invalid, caused either by the * font being changed or if cache.cacheVer < 0. */ void updateBlock (char[] str, ref TextBlock cache) { - fontTex.updateCache (face, str, cache); + try { + fontTex.updateCache (face, str, cache); + } catch (Exception e) { + logger.warn ("Exception while drawing text: "~e.msg); + } } /** Draw a block of text (may inlcude new-lines).
--- a/mde/sdl.d Sun Jun 01 18:22:54 2008 +0100 +++ b/mde/sdl.d Mon Jun 02 14:34:24 2008 +0100 @@ -128,7 +128,7 @@ * the highest supported version but this way we know what we're getting. */ try { - DerelictGL.loadVersions(GLVersion.Version13); + DerelictGL.loadVersions(GLVersion.Version21); } catch (SharedLibProcLoadException e) { logger.warn ("Loading OpenGL version 1.3 failed:"); logger.warn (e.msg);