Main Page Class Hierarchy Compound List File List Compound Members File Members

FTRenderer.cc

Go to the documentation of this file.
00001 /*
00002 File: FTRenderer.cc
00003 
00004 Function: Render text into images using FreeType
00005 (http://www.freetype.org)
00006 
00007 Author: Andrew Willmott
00008 
00009 Notes: 
00010 */
00011 
00012 #include "gcl/FTRenderer.h"
00013 
00014 #include <stdlib.h>
00015 
00016  FTRenderer::FTRenderer() : glyphs(0)
00017 {
00018 dpi = 96;
00019 pointSize = 24;
00020 hinted = 1;
00021 smooth = 1;
00022 border = 0;
00023 Init();
00024 }
00025 
00026  FTRenderer::~FTRenderer() 
00027 {
00028 Free();
00029 }
00030 
00031  Void FTRenderer::SetPointSize(Int size)
00032 {
00033 pointSize = size;
00034 }
00035 
00036  Void FTRenderer::SetupGlyphTable()
00037 {
00038 TT_UShort i, n;
00039 TT_UShort platform, encoding;
00040 
00041 /* First, look for a Unicode charmap */
00042 
00043 noCharMap = true;
00044 n = TT_Get_CharMap_Count(face);
00045 
00046 for (i = 0; i < n; i++)
00047 {
00048 TT_Get_CharMap_ID(face, i, &platform, &encoding);
00049 if ((platform == 3 && encoding == 1) ||
00050 (platform == 0 && encoding == 0))
00051 {
00052 TT_Get_CharMap(face, i, &charMap);
00053 noCharMap = false;
00054 break;
00055 }
00056 }
00057 
00058 if (i == n)
00059 {
00060 TT_Face_Properties properties;
00061 
00062 TT_Get_Face_Properties(face, &properties);
00063 
00064 numGlyphs = properties.num_Glyphs;
00065 }
00066 
00067 /* Second, allocate the array */
00068 
00069 glyphs = new TT_Glyph[256];
00070 for (i = 0; i < 256; i++)
00071 glyphs[i].z = 0;
00072 }
00073 
00074  Void FTRenderer::FreeGlyphTable()
00075 {
00076 Int i;
00077 
00078 if (!glyphs)
00079 return;
00080 
00081 for (i = 0; i < 256; ++i)
00082 TT_Done_Glyph(glyphs[i]);
00083 
00084 delete[] glyphs;
00085 
00086 glyphs = 0;
00087 }
00088 
00089  Void FTRenderer::LoadGlyphs(StrConst txt, Int txtlen)
00090 // make sure all glyphs in the string are loaded
00091 {
00092 TT_UShort i, n;
00093 Int code, load_flags;
00094 TT_Error error;
00095 
00096 load_flags = TTLOAD_SCALE_GLYPH;
00097 if (hinted)
00098 load_flags |= TTLOAD_HINT_GLYPH;
00099 
00100 for (i = 0; i < txtlen; ++i)
00101 {
00102 unsigned char j = txt[i];
00103 
00104 // already loaded?
00105 if (glyphs[j].z)
00106 continue;
00107 
00108 if (noCharMap)
00109 {
00110 code = j - ' ' + 1;
00111 if (code < 0 || code >= numGlyphs)
00112 code = 0;
00113 }
00114 else
00115 {
00116 code = TT_Char_Index(charMap, j);
00117 if (code < 0)
00118 code = 0; /* FIXME! default code */
00119 }
00120 
00121 (void)
00122 (
00123 (error = TT_New_Glyph(face, &glyphs[j])) ||
00124 (error = TT_Load_Glyph(instance, glyphs[j], code, load_flags))
00125 );
00126 if (error)
00127 _Warning(String().Printf("ERROR: cannot allocate and load glyph: %d\n", error));
00128 }
00129 }
00130 
00131 
00132  Void FTRenderer::SetFace(StrConst filename)
00133 {
00134 TT_Error error;
00135 
00136 if (faceSet)
00137 FreeFace();
00138 
00139 /* load the typeface */
00140 
00141 error = TT_Open_Face(engine, filename, &face);
00142 if (error)
00143 {
00144 if (error == TT_Err_Could_Not_Open_File)
00145 _Error(String().Printf("ERROR: could not find/open %s\n", filename));
00146 else
00147 _Error(String().Printf("ERROR: while opening %s, error code = %x\n", filename, error));
00148 }
00149 
00150 /* create and initialize instance */
00151 
00152 (void)
00153 (
00154 (error = TT_New_Instance(face, &instance)) ||
00155 (error = TT_Set_Instance_Resolutions(instance, dpi, dpi)) ||
00156 (error = TT_Set_Instance_CharSize(instance, pointSize * 64))
00157 );
00158 if (error)
00159 _Error(String().Printf("ERROR: could not create and initialize instance: %d\n",
00160 error));
00161 
00162 faceSet = true;
00163 SetupGlyphTable();
00164 }
00165 
00166  Void FTRenderer::FreeFace()
00167 {
00168 FreeGlyphTable();
00169 TT_Done_Instance(instance);
00170 TT_Close_Face(face);
00171 }
00172 
00173  Void FTRenderer::SetupImage(StrConst txt, Int txtlen)
00174 {
00175 Int i, upm, ascent, descent;
00176 TT_Face_Properties properties;
00177 TT_Instance_Metrics imetrics;
00178 TT_Glyph_Metrics gmetrics;
00179 Int width, height;
00180 TT_F26Dot6 widthx;
00181 
00182 /* allocate the large bitmap */
00183 
00184 TT_Get_Face_Properties( face, &properties );
00185 TT_Get_Instance_Metrics( instance, &imetrics );
00186 
00187 upm = properties.header->Units_Per_EM;
00188 ascent = ( properties.horizontal->Ascender * imetrics.y_ppem ) / upm;
00189 descent = ( properties.horizontal->Descender * imetrics.y_ppem ) / upm;
00190 
00191 width = 2 * border;
00192 height = 2 * border + ascent - descent;
00193 widthx = 64 * width;
00194 
00195 for (i = 0; i < txtlen; i++)
00196 {
00197 unsigned char j = txt[i];
00198 
00199 if (!glyphs[j].z)
00200 continue;
00201 
00202 TT_Get_Glyph_Metrics(glyphs[j], &gmetrics);
00203 widthx += gmetrics.advance;
00204 }
00205 
00206 width = (widthx + 63) / 64;
00207 width = (width + 3) & ~0x3;
00208 image.SetSize(width, height);
00209 image.Clear(cWhite);
00210 
00211 pixmap.rows = height;
00212 pixmap.width = width;
00213 pixmap.flow = TT_Flow_Up;
00214 pixmap.cols = width;
00215 pixmap.size = width * height;
00216 pixmap.bitmap = image.ByteData();
00217 
00218 xShift = border;
00219 yShift = border - descent;
00220 }
00221 
00222 
00223  Void FTRenderer::RenderGlyph(TT_Glyph glyph, TT_F26Dot6 x_off, TT_F26Dot6 y_off,
00224 TT_Glyph_Metrics *gmetrics)
00225 {
00226 if (!smooth)
00227 {
00228 TT_Get_Glyph_Bitmap(glyph, &pixmap, x_off, y_off);
00229 }
00230 else
00231 {
00232 TT_F26Dot6 xmin, ymin, xmax, ymax;
00233 
00234 xmin = gmetrics->bbox.xMin & ~0x3F;
00235 ymin = gmetrics->bbox.yMin & ~0x3F;
00236 xmax = (gmetrics->bbox.xMax + 63) & ~0x3F;
00237 ymax = (gmetrics->bbox.yMax + 63) & ~0x3F;
00238 
00239 TT_Get_Glyph_Pixmap(glyph, &pixmap, x_off, y_off);
00240 }
00241 }
00242 
00243  Void FTRenderer::RenderAllGlyphs(StrConst txt, Int txtlen)
00244 {
00245 Int i;
00246 TT_F26Dot6 x, y;
00247 TT_Glyph_Metrics gmetrics;
00248 
00249 x = xShift * 64;
00250 y = yShift * 64;
00251 
00252 for (i = 0; i < txtlen; i++)
00253 {
00254 unsigned char j = txt[i];
00255 
00256 if (!glyphs[j].z)
00257 continue;
00258 
00259 TT_Get_Glyph_Metrics(glyphs[j], &gmetrics);
00260 
00261 RenderGlyph(glyphs[j], x, y, &gmetrics);
00262 
00263 x += gmetrics.advance;
00264 }
00265 }
00266 
00267  Void FTRenderer::Init()
00268 {
00269 TT_Error error;
00270 TT_Byte palette[5] = 
00271 {
00272 255,
00273 192,
00274 128,
00275 64,
00276 0
00277 };
00278 
00279 error = TT_Init_FreeType(&engine);
00280 if (error)
00281 _Error(String().Printf("ERROR: While initializing engine, code = %d\n", error));
00282 
00283 TT_Set_Raster_Gray_Palette(engine, palette);
00284 
00285 faceSet = false;
00286 }
00287 
00288  Void FTRenderer::Free()
00289 {
00290 if (faceSet)
00291 FreeFace();
00292 
00293 TT_Done_FreeType(engine);
00294 }
00295 
00296  Void FTRenderer::RenderText(StrConst txt)
00297 {
00298 if (!faceSet)
00299 _Error("(FTRenderer) No font set yet");
00300 Int txtlen = txt.Length();
00301 LoadGlyphs(txt, txtlen);
00302 SetupImage(txt, txtlen);
00303 RenderAllGlyphs(txt, txtlen);
00304 }

Generated at Sat Aug 5 00:16:58 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000

AltStyle によって変換されたページ (->オリジナル) /