xoreos  0.0.5
ttf.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include <boost/scope_exit.hpp>
26 
27 #include "src/common/util.h"
28 #include "src/common/error.h"
29 
30 #include "src/graphics/ttf.h"
31 
33 
34 namespace Graphics {
35 
36 namespace {
37 
38 inline int ftFloor26_6(FT_Pos x) {
39  return x / 64;
40 }
41 
42 inline int ftCeil26_6(FT_Pos x) {
43  return (x + 63) / 64;
44 }
45 
46 } // End of anonymous namespace
47 
49  _library(0), _face(0), _width(0), _height(0), _ascent(0), _descent(0) {
50 
51  // Initialize a library object of FreeType2
52  if (FT_Init_FreeType(&_library))
53  throw Common::Exception("TTFRenderer: Could not init freetype2");
54 
55  bool success = false;
56  BOOST_SCOPE_EXIT( (&success) (&_library)) {
57  if (!success)
58  FT_Done_FreeType(_library);
59  } BOOST_SCOPE_EXIT_END
60 
61  const size_t size = ttfFile.size();
62  _fileBuffer.reset(new uint8[size]);
63 
64  if (ttfFile.read(_fileBuffer.get(), size) != size)
66 
67  if (FT_New_Memory_Face(_library, _fileBuffer.get(), size, 0, &_face))
68  throw Common::Exception("TTFRenderer: Could not load font file");
69 
70  BOOST_SCOPE_EXIT( (&success) (&_face)) {
71  if (!success)
72  FT_Done_Face(_face);
73  } BOOST_SCOPE_EXIT_END
74 
75  // We only support scalable fonts.
76  if (!FT_IS_SCALABLE(_face))
77  throw Common::Exception("TTFRenderer: Font is not scalable");
78 
79  // Set the font height
80  if (FT_Set_Char_Size(_face, 0, height * 64, 0, 0))
81  throw Common::Exception("TTFRenderer: Setting height to %d failed", height);
82 
83  FT_Fixed yScale = _face->size->metrics.y_scale;
84 
85  _ascent = ftCeil26_6(FT_MulFix(_face->ascender, yScale));
86  _descent = ftCeil26_6(FT_MulFix(_face->descender, yScale));
87 
88  _width = ftCeil26_6(FT_MulFix(_face->max_advance_width, _face->size->metrics.x_scale));
89  _height = _ascent - _descent + 1;
90 
91  success = true;
92 }
93 
95  FT_Done_Face(_face);
96  FT_Done_FreeType(_library);
97 }
98 
100  return _height;
101 }
102 
104  return _width;
105 }
106 
107 void TTFRenderer::getFaceMetrics(int &advance, int &yOffset, int &xMin) const {
108  FT_Glyph_Metrics &metrics = _face->glyph->metrics;
109 
110  xMin = ftFloor26_6(metrics.horiBearingX);
111  yOffset = _ascent - ftFloor26_6(metrics.horiBearingY);
112  advance = ftCeil26_6(metrics.horiAdvance);
113 }
114 
115 bool TTFRenderer::hasChar(uint32 ch) const {
116  return FT_Get_Char_Index(_face, ch) != 0;
117 }
118 
120  FT_UInt slot = FT_Get_Char_Index(_face, ch);
121  if (!slot)
122  throw Common::Exception("TTFRenderer: Font does not contain glyph 0x%X", ch);
123 
124  int error;
125  if ((error = FT_Load_Glyph(_face, slot, FT_LOAD_DEFAULT)))
126  throw Common::Exception("TTFRenderer: Could not load glyph 0x%X: 0x%X", ch, error);
127 
128  int advance, yOffset, xMin;
129  getFaceMetrics(advance, yOffset, xMin);
130 
131  return advance;
132 }
133 
134 void TTFRenderer::drawCharacter(uint32 ch, Surface &surface, int x, int y) {
135  FT_UInt slot = FT_Get_Char_Index(_face, ch);
136  if (!slot)
137  throw Common::Exception("TTFRenderer: Font does not contain glyph 0x%X", ch);
138 
139  int error;
140  if ((error = FT_Load_Glyph(_face, slot, FT_LOAD_DEFAULT)))
141  throw Common::Exception("TTFRenderer: Could not load glyph 0x%X: 0x%X", ch, error);
142 
143  if ((error = FT_Render_Glyph(_face->glyph, FT_RENDER_MODE_NORMAL)))
144  throw Common::Exception("TTFRenderer: Could not render glyph 0x%X: 0x%X", ch, error);
145 
146  if (_face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
147  throw Common::Exception("TTFRenderer: Glyph 0x%X is no bitmap", ch);
148 
149  int advance, yOffset, xMin;
150  getFaceMetrics(advance, yOffset, xMin);
151 
152  const FT_Bitmap &bitmap = _face->glyph->bitmap;
153  const uint8 *src = bitmap.buffer;
154  int srcPitch = bitmap.pitch;
155  if (srcPitch < 0) {
156  src += (bitmap.rows - 1) * srcPitch;
157  srcPitch = -srcPitch;
158  }
159 
160  uint bitmapWidth = (uint) bitmap.width;
161  if (xMin < 0) {
162  bitmapWidth += xMin;
163  src -= xMin;
164 
165  xMin = 0;
166  }
167 
168  x += xMin;
169  y += yOffset;
170 
171  if ((x >= surface.getWidth()) || (y >= surface.getHeight()))
172  return;
173 
174  const uint width = MIN<uint>(surface.getWidth () - x, bitmapWidth);
175  const uint height = MIN<uint>(surface.getHeight() - y, bitmap.rows);
176 
177  byte *dst = surface.getData() + (y * surface.getWidth() + x) * 4;
178 
179  switch (bitmap.pixel_mode) {
180  case FT_PIXEL_MODE_GRAY:
181  for (uint i = 0; i < height; ++i) {
182  for (uint j = 0; j < width; ++j, dst += 4) {
183  // Output BGRA
184  dst[0] = dst[1] = dst[2] = 0xFF;
185  dst[3] = src[j];
186  }
187 
188  dst += (surface.getWidth() - width) * 4;
189  src += srcPitch;
190  }
191  break;
192 
193  default:
194  throw Common::Exception("TTFRenderer: Unsupported pixel mode %d", bitmap.pixel_mode);
195  }
196 }
197 
198 } // End of namespace Graphics
byte * getData()
Definition: surface.cpp:61
void reset(PointerType o=0)
Resets the pointer with the new value.
Definition: scopedptr.h:87
uint8_t uint8
Definition: types.h:200
bool hasChar(uint32 ch) const
Does the font have the specified character?
Definition: ttf.cpp:115
A simple TTF renderer outputting BGRA.
Basic exceptions to throw.
int getWidth() const
Definition: surface.cpp:53
Utility templates and functions.
FT_Library _library
Definition: ttf.h:61
int getMaxWidth() const
Return the max width of a character in pixels.
Definition: ttf.cpp:103
virtual size_t read(void *dataPtr, size_t dataSize)=0
Read data from the stream.
int getCharWidth(uint32 ch) const
Return the width of a specific character in pixels.
Definition: ttf.cpp:119
StackException Exception
Definition: error.h:59
const Exception kReadError("Read error")
Exception when reading from a stream failed.
Definition: error.h:62
virtual size_t size() const =0
Obtains the total size of the stream, measured in bytes.
void getFaceMetrics(int &advance, int &yOffset, int &xMin) const
Definition: ttf.cpp:107
PointerType get() const
Returns the plain pointer value.
Definition: scopedptr.h:96
An image surface, in BGRA format.
uint32 _height
Definition: h263.cpp:54
uint32_t uint32
Definition: types.h:204
Common::ScopedArray< byte > _fileBuffer
Definition: ttf.h:64
int getHeight() const
Definition: surface.cpp:57
TTFRenderer(Common::SeekableReadStream &ttfFile, int height)
Create a TTF renderer with this TTF in the specified line height in pixels.
Definition: ttf.cpp:48
uint32 _width
Definition: h263.cpp:53
void NORETURN_PRE error(const char *s,...)
Definition: util.cpp:86
int getHeight() const
Return the height of a character in pixels.
Definition: ttf.cpp:99
Interface for a seekable & readable data stream.
Definition: readstream.h:265
uint8 byte
Definition: types.h:209
unsigned int uint
Definition: types.h:211
void drawCharacter(uint32 ch, Surface &surface, int x, int y)
Draw a specific character onto a BGRA surface.
Definition: ttf.cpp:134
FT_Face _face
Definition: ttf.h:62