BitmapFont.cpp
Go to the documentation of this file.
1 // ****************************************************************************
2 // This file is part of the Integrating Vision Toolkit (IVT).
3 //
4 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
5 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
6 //
7 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
8 // All rights reserved.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // 2. Redistributions in binary form must reproduce the above copyright
17 // notice, this list of conditions and the following disclaimer in the
18 // documentation and/or other materials provided with the distribution.
19 //
20 // 3. Neither the name of the KIT nor the names of its contributors may be
21 // used to endorse or promote products derived from this software
22 // without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
25 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
28 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 // ****************************************************************************
35 // ****************************************************************************
36 // Filename: BitmapFont.cpp
37 // Copyright: Keyetech UG (haftungsbeschraenkt)
38 // Author: Pedram Azad
39 // Date: 17.12.2012
40 // ****************************************************************************
41 
42 
43 // ****************************************************************************
44 // Includes
45 // ****************************************************************************
46 
47 #include "BitmapFont.h"
48 
49 #include "Image/ByteImage.h"
50 #include "Image/PrimitivesDrawer.h"
51 
52 #include <stdio.h>
53 #include <string.h>
54 
55 
56 // ****************************************************************************
57 // Defines
58 // ****************************************************************************
59 
60 #define PCF_PROPERTIES (1<<0)
61 #define PCF_ACCELERATORS (1<<1)
62 #define PCF_METRICS (1<<2)
63 #define PCF_BITMAPS (1<<3)
64 #define PCF_INK_METRICS (1<<4)
65 #define PCF_BDF_ENCODINGS (1<<5)
66 #define PCF_SWIDTHS (1<<6)
67 #define PCF_GLYPH_NAMES (1<<7)
68 #define PCF_BDF_ACCELERATORS (1<<8)
69 
70 #define PCF_DEFAULT_FORMAT 0x00000000
71 #define PCF_INKBOUNDS 0x00000200
72 #define PCF_ACCEL_W_INKBOUNDS 0x00000100
73 #define PCF_COMPRESSED_METRICS 0x00000100
74 
75 #define PCF_GLYPH_PAD_MASK (3<<0) /* See the bitmap table for explanation */
76 #define PCF_BYTE_MASK (1<<2) /* If set then Most Sig Byte First */
77 #define PCF_BIT_MASK (1<<3) /* If set then Most Sig Bit First */
78 #define PCF_SCAN_UNIT_MASK (3<<4) /* See the bitmap table for explanation */
79 
80 
81 // ****************************************************************************
82 // Struct definitions
83 // ****************************************************************************
84 
85 struct TOCEntry
86 {
87  int type; // indicates which table
88  int format; // indicates how the data are formatted in the table
89  int size; // in bytes
90  int offset; // from start of file
91 };
92 
94 {
95  int format;
97 };
98 
100 {
101  int format; // always stored with least significant byte first
104  short min_byte1;
105  short max_byte1;
107 };
108 
110 {
111  int format; // always stored with least significant byte first
112  unsigned char noOverlap;
113  unsigned char constantMetrics;
114  unsigned char terminalFont;
115  unsigned char constantWidth; // monospace font like courier
116  unsigned char inkInside;
117  unsigned char inkMetrics;
118  unsigned char drawDirection; // 0 =>left to right, 1 => right to left
119  unsigned char padding;
123 };
124 
126 {
133 };
134 
135 
137 {
141  int nWidth;
142  int nAscent;
143  int nDescent;
144 };
145 
146 
147 
148 // ****************************************************************************
149 // CBitmapFont
150 // ****************************************************************************
151 
153 {
154  m_pCharacters = 0;
155  m_pEncodingTable = 0;
156 
157  Reset();
158 }
159 
161 {
162  Reset();
163 }
164 
166 {
167  if (m_pCharacters)
168  {
169  for (int i = 0; i < m_nCharacters; i++)
170  {
171  if (m_pCharacters[i].pCoordinatesX)
172  {
173  delete [] m_pCharacters[i].pCoordinatesX;
174  delete [] m_pCharacters[i].pCoordinatesY;
175  }
176  }
177 
178  delete [] m_pCharacters;
179  m_pCharacters = 0;
180  }
181 
182  delete [] m_pEncodingTable;
183  m_pEncodingTable = 0;
184 
185  m_nCharacters = 0;
186  m_nMaxEncoding = 0;
187  m_nFontHeight = 0;
188 }
189 
190 void CBitmapFont::Init(int nCharacters)
191 {
192  Reset();
193 
194  m_nCharacters = nCharacters;
195 
196  m_pCharacters = new BitmapCharacter[m_nCharacters];
197 
198  int i;
199 
200  for (int i = 0; i < m_nCharacters; i++)
201  {
202  m_pCharacters[i].pCoordinatesX = 0;
203  m_pCharacters[i].pCoordinatesY = 0;
204  m_pCharacters[i].nCoordinates = 0;
205  m_pCharacters[i].nWidth = 0;
206  }
207 
208  m_nMaxEncoding = 256;
209  m_pEncodingTable = new int[m_nMaxEncoding];
210 
211  for (i = 0; i < m_nMaxEncoding; i++)
212  m_pEncodingTable[i] = -1;
213 }
214 
215 bool CBitmapFont::GetCharacterInformation(unsigned char encoding, int *&pCoordinatesX, int *&pCoordinatesY, int &nCoordinates, int &nWidth) const
216 {
217  const int nIndex = m_pEncodingTable[encoding];
218 
219  if (nIndex == -1)
220  return false;
221 
222  pCoordinatesX = m_pCharacters[nIndex].pCoordinatesX;
223  pCoordinatesY = m_pCharacters[nIndex].pCoordinatesY;
224  nCoordinates = m_pCharacters[nIndex].nCoordinates;
225  nWidth = m_pCharacters[nIndex].nWidth;
226 
227  return true;
228 }
229 
230 void CBitmapFont::SetGlyph(int nIndex, int *pCoordinatesX, int *pCoordinatesY, int nCoordinates, int nWidth, int nAscent, int nDescent)
231 {
232  if (m_pCharacters[nIndex].pCoordinatesY)
233  {
234  delete [] m_pCharacters[nIndex].pCoordinatesY;
235  delete [] m_pCharacters[nIndex].pCoordinatesY;
236  }
237 
238  m_pCharacters[nIndex].pCoordinatesX = new int[nCoordinates];
239  m_pCharacters[nIndex].pCoordinatesY = new int[nCoordinates];
240  m_pCharacters[nIndex].nCoordinates = nCoordinates;
241  m_pCharacters[nIndex].nWidth = nWidth;
242 
243  // copy coordinates
244  for (int i = 0; i < nCoordinates; i++)
245  {
246  m_pCharacters[nIndex].pCoordinatesX[i] = pCoordinatesX[i];
247  m_pCharacters[nIndex].pCoordinatesY[i] = pCoordinatesY[i];
248  }
249 }
250 
251 void CBitmapFont::AddEncoding(int nEncoding, int nIndex)
252 {
253  if (nIndex >= m_nCharacters)
254  {
255  printf("error: encoding %i indexed invalid glyph index %i (%i glyphs)\n", nEncoding, nIndex, m_nCharacters);
256  return;
257  }
258 
259  if (nEncoding < 0 || nEncoding >= m_nMaxEncoding)
260  {
261  printf("error: encoding %i is not valid\n", nEncoding);
262  return;
263  }
264 
265  m_pEncodingTable[nEncoding] = nIndex;
266 }
267 
268 
269 
270 static short my_invert_byte_order_short(short x, int bInvert = false)
271 {
272  if (!bInvert)
273  return x;
274 
275  unsigned short result = 0;
276 
277  result |= (x & 0x00ff) << 8;
278  result |= (x & 0xff00) >> 8;
279 
280  return result;
281 }
282 
283 static unsigned int my_invert_byte_order_int(unsigned int x, int bInvert = false)
284 {
285  if (!bInvert)
286  return x;
287 
288  unsigned int result = 0;
289 
290  result |= (x & 0x000000ff) << 24;
291  result |= (x & 0x0000ff00) << 8;
292  result |= (x & 0x00ff0000) >> 8;
293  result |= (x & 0xff000000) >> 24;
294 
295  return result;
296 }
297 
298 
299 bool CBitmapFont::LoadPCFFont(const char *pFilePath)
300 {
301  FILE *f = fopen(pFilePath, "rb");
302  if (!f)
303  {
304  printf("error: could not open file for reading\n");
305  return false;
306  }
307 
308  fseek(f, 0, SEEK_END);
309  const int nFileSize = ftell(f);
310  fseek(f, 0, SEEK_SET);
311 
312  // allocate memory for file contents
313  unsigned char *pBuffer = new unsigned char[nFileSize];
314 
315  // read file into buffer
316  if (fread(pBuffer, nFileSize, 1, f) != 1)
317  {
318  printf("error: could not read file\n");
319  delete [] pBuffer;
320  return false;
321  }
322 
323  // compare
324  if (strncmp((char *) pBuffer, "\1fcp", 4) != 0)
325  {
326  printf("error: file header is not a valid PCF header\n");
327  delete [] pBuffer;
328  return false;
329  }
330 
331  const int nTableCount = my_invert_byte_order_int(*((int *) (pBuffer + 4)));
332 
333  TOCEntry *pTOCEntries = (TOCEntry *) (pBuffer + 8);
334  TOCEntry *pBitmapTOCEntry = 0;
335  TOCEntry *pAcceleratorTOCEntry = 0;
336  TOCEntry *pMetricsTOCEntry = 0;
337  TOCEntry *pEncodingTOCEntry = 0;
338 
339  int i;
340 
341  for (i = 0; i < nTableCount; i++)
342  {
343  if ((pTOCEntries[i].format & PCF_BIT_MASK) == 0)
344  {
345  printf("error: inverse bit order not implmeented\n");
346  delete [] pBuffer;
347  return false;
348  }
349 
350  switch (pTOCEntries[i].type)
351  {
352  case PCF_BITMAPS: pBitmapTOCEntry = pTOCEntries + i; break;
353  case PCF_ACCELERATORS: pAcceleratorTOCEntry = pTOCEntries + i; break;
354  case PCF_METRICS: pMetricsTOCEntry = pTOCEntries + i; break;
355  case PCF_BDF_ENCODINGS: pEncodingTOCEntry = pTOCEntries + i; break;
356  default: break;
357  }
358  }
359 
360  if (!pBitmapTOCEntry || !pAcceleratorTOCEntry || !pMetricsTOCEntry || !pEncodingTOCEntry)
361  {
362  printf("error: PCF does not contain all tables\n");
363  delete [] pBuffer;
364  return false;
365  }
366 
367  // read accelerator table
368  PCFAcceleratorTable *pAcceleratorTable = (PCFAcceleratorTable *) (pBuffer + pAcceleratorTOCEntry->offset);
369 
370  pAcceleratorTable->format = my_invert_byte_order_int(pAcceleratorTable->format);
371  pAcceleratorTable->fontAscent = my_invert_byte_order_int(pAcceleratorTable->fontAscent, pAcceleratorTable->format & PCF_BYTE_MASK);
372  pAcceleratorTable->fontDescent = my_invert_byte_order_int(pAcceleratorTable->fontDescent, pAcceleratorTable->format & PCF_BYTE_MASK);
373 
374  // read metrics table
375  PCFMetricsTable *pMetricsTable = (PCFMetricsTable *) (pBuffer + pMetricsTOCEntry->offset);
376 
377  pMetricsTable->format = my_invert_byte_order_int(pMetricsTable->format);
378  pMetricsTable->metrics_count = my_invert_byte_order_short(pMetricsTable->metrics_count, pMetricsTable->format & PCF_BYTE_MASK);
379 
380  // read encoding table
381  PCFEncodingTable *pEncodingTable = (PCFEncodingTable *) (pBuffer + pEncodingTOCEntry->offset);
382 
383  pEncodingTable->format = my_invert_byte_order_int(pEncodingTable->format);
384  pEncodingTable->min_char_or_byte2 = my_invert_byte_order_short(pEncodingTable->min_char_or_byte2, pEncodingTable->format & PCF_BYTE_MASK);
385  pEncodingTable->max_char_or_byte2 = my_invert_byte_order_short(pEncodingTable->max_char_or_byte2, pEncodingTable->format & PCF_BYTE_MASK);
386  pEncodingTable->min_byte1 = my_invert_byte_order_short(pEncodingTable->min_byte1, pEncodingTable->format & PCF_BYTE_MASK);
387  pEncodingTable->max_byte1 = my_invert_byte_order_short(pEncodingTable->max_byte1, pEncodingTable->format & PCF_BYTE_MASK);
388 
389  if (pEncodingTable->min_byte1 != 0 || pEncodingTable->max_byte1 != 0)
390  {
391  printf("error: 2 byte encoding not implemented\n");
392  delete [] pBuffer;
393  return false;
394  }
395 
396  const short *pEncodingData = (const short *) (pBuffer + pEncodingTOCEntry->offset + 14);
397 
398  // read bitmap table
399  int *pBitmapTable = (int *) (pBuffer + pBitmapTOCEntry->offset);
400 
401  const int nBitmapFormat = my_invert_byte_order_int(pBitmapTable[0]);
402  const int nGlyphs = my_invert_byte_order_int(pBitmapTable[1], nBitmapFormat & PCF_BYTE_MASK);
403  const int nBitmapSize = my_invert_byte_order_int(pBitmapTable[2 + nGlyphs + (nBitmapFormat & 3)], nBitmapFormat & PCF_BYTE_MASK);
404  const int *pGlyphOffsets = pBitmapTable + 2;
405 
406  int nBytesPerLine = 0;
407  switch (nBitmapFormat & 3)
408  {
409  case 0: nBytesPerLine = 1;
410  case 1: nBytesPerLine = 2;
411  case 2: nBytesPerLine = 4;
412  }
413 
414  if (nBytesPerLine == 0)
415  {
416  printf("error: bitmap format invalid\n");
417  delete [] pBuffer;
418  return false;
419  }
420 
421  // invert byte order if needed
422  //for (int i = 0; i < nGlyphs; i++)
423  // pGlyphOffsets[i] = my_invert_byte_order_int(pGlyphOffsets[i], nBitmapFormat & PCF_BYTE_MASK);
424 
425  if (nBitmapSize % nGlyphs != 0)
426  {
427  printf("error: irregular glyph size\n");
428  delete [] pBuffer;
429  return false;
430  }
431 
432  const int nBytesPerGlyph = nBitmapSize / nGlyphs;
433 
434  if (nBytesPerGlyph % nBytesPerLine != 0)
435  {
436  printf("error: irregular line size\n");
437  delete [] pBuffer;
438  return false;
439  }
440 
441  const int nLinesPerGlyph = nBytesPerGlyph / nBytesPerLine;
442 
443  if (pMetricsTable->metrics_count != nGlyphs)
444  {
445  printf("error: glyph count does not match metrics count\n");
446  delete [] pBuffer;
447  return false;
448  }
449 
450  // initialize
451  Init(nGlyphs);
452 
453  // allocate memory for maximum number of coordinates
454  int *pCoordinatesX = new int[nLinesPerGlyph * nBytesPerLine * 8];
455  int *pCoordinatesY = new int[nLinesPerGlyph * nBytesPerLine * 8];
456 
457  for (int n = 0; n < nGlyphs; n++)
458  {
459  const unsigned char *pGlyphBitmapData = ((const unsigned char *) (pBitmapTable + 6 + nGlyphs)) + my_invert_byte_order_int(pGlyphOffsets[n], nBitmapFormat & PCF_BYTE_MASK);
460 
461  // collect coordinates
462  int nCoordinates = 0;
463 
464  for (int i = 0; i < nLinesPerGlyph; i++)
465  {
466  for (int j = 0; j < nBytesPerLine; j++)
467  {
468  const unsigned char value = pGlyphBitmapData[i * nBytesPerLine + j];
469 
470  for (int k = 0; k < 8; k++)
471  if ((value << k) & 128)
472  {
473  pCoordinatesX[nCoordinates] = j * 8 + k;
474  pCoordinatesY[nCoordinates] = i;
475  nCoordinates++;
476  }
477  }
478  }
479 
480  // read metric data
481  int nWidth, nAscent, nDescent;
482 
483  if (pMetricsTable->format & PCF_COMPRESSED_METRICS)
484  {
485  const unsigned char *pMetricsData = (unsigned char *) (pBuffer + pMetricsTOCEntry->offset + 6);
486  nWidth = pMetricsData[n * 5 + 2] - 0x80;
487  nAscent = pMetricsData[n * 5 + 3] - 0x80;
488  nDescent = pMetricsData[n * 5 + 4] - 0x80;
489  }
490  else
491  {
492  const short *pMetricsData = (short *) (pBuffer + pMetricsTOCEntry->offset + 6);
493  nWidth = my_invert_byte_order_short(pMetricsData[n * 5 + 2], pMetricsTable->format & PCF_BYTE_MASK);
494  nAscent = my_invert_byte_order_short(pMetricsData[n * 5 + 3], pMetricsTable->format & PCF_BYTE_MASK);
495  nDescent = my_invert_byte_order_short(pMetricsData[n * 5 + 4], pMetricsTable->format & PCF_BYTE_MASK);
496  }
497 
498  // store coordinates and other information
499  SetGlyph(n, pCoordinatesX, pCoordinatesY, nCoordinates, nWidth, nAscent, nDescent);
500  }
501 
502  // set encoding table
503  for (i = pEncodingTable->min_char_or_byte2; i <= pEncodingTable->max_char_or_byte2; i++)
504  {
505  const int nIndex = my_invert_byte_order_short(pEncodingData[i], pEncodingTable->format & PCF_BYTE_MASK);
506  AddEncoding(i, nIndex);
507  }
508 
509  //printf("\n%i glyphs with %i lines each with %i bytes each (%i = %i)\n", nGlyphs, nLinesPerGlyph, nBytesPerLine, nGlyphs * nLinesPerGlyph * nBytesPerLine, nBitmapSize);
510 
511  // set some attributes
512  m_nFontHeight = pAcceleratorTable->fontAscent + pAcceleratorTable->fontDescent;
513 
514  // free memory
515  delete [] pCoordinatesX;
516  delete [] pCoordinatesY;
517  delete [] pBuffer;
518 
519  return true;
520 }
521 
522 void CBitmapFont::DrawText(CByteImage *pImage, const char *pText, int x0, int y0, unsigned char r, unsigned char g, unsigned char b) const
523 {
524  const int nLength = (int) strlen(pText);
525 
526  int x = x0, y = y0;
527 
528  for (int i = 0; i < nLength; i++)
529  {
530  int *pCoordinatesX, *pCoordinatesY;
531  int nCoordinates, nWidth;
532 
533  if (pText[i] == '\n')
534  {
535  x = x0;
536  y += m_nFontHeight;
537  }
538  else
539  if (GetCharacterInformation(pText[i], pCoordinatesX, pCoordinatesY, nCoordinates, nWidth))
540  {
541  for (int j = 0; j < nCoordinates; j++)
542  {
543  // DrawPoint is fail safe
544  PrimitivesDrawer::DrawPoint(pImage, x + pCoordinatesX[j], y + pCoordinatesY[j], r, g, b);
545  }
546 
547  x += nWidth;
548  }
549  }
550 }
551 
552 void CBitmapFont::DrawText(CByteImage *pImage, const char *pText, int x, int y, Color::Color color) const
553 {
554  unsigned char r, g, b;
555 
556  Color::GetRGBValues(color, r, g, b);
557 
558  DrawText(pImage, pText, x, y, r, g, b);
559 }
GLubyte g
Definition: glext.h:5166
bool GetCharacterInformation(unsigned char encoding, int *&pCoordinatesX, int *&pCoordinatesY, int &nCoordinates, int &nWidth) const
Definition: BitmapFont.cpp:215
unsigned char constantMetrics
Definition: BitmapFont.cpp:113
#define PCF_COMPRESSED_METRICS
Definition: BitmapFont.cpp:73
void DrawText(CByteImage *pImage, const char *pText, int x, int y, unsigned char r=0, unsigned char g=0, unsigned char b=0) const
Definition: BitmapFont.cpp:522
void SetGlyph(int nIndex, int *pCoordinatesX, int *pCoordinatesY, int nCoordinates, int nWidth, int nAscent, int nDescent)
Definition: BitmapFont.cpp:230
#define PCF_BITMAPS
Definition: BitmapFont.cpp:63
#define PCF_BDF_ENCODINGS
Definition: BitmapFont.cpp:65
GLenum GLsizei n
Definition: glext.h:4209
void Reset()
Definition: BitmapFont.cpp:165
Data structure for the representation of 8-bit grayscale images and 24-bit RGB (or HSV) color images ...
Definition: ByteImage.h:80
#define PCF_METRICS
Definition: BitmapFont.cpp:62
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3121
int offset
Definition: BitmapFont.cpp:90
unsigned char padding
Definition: BitmapFont.cpp:119
unsigned char inkMetrics
Definition: BitmapFont.cpp:117
void GetRGBValues(Color color, unsigned char &r, unsigned char &g, unsigned char &b)
Definition: Color.cpp:55
GLenum GLint x
Definition: glext.h:3125
GLsizei const GLfloat * value
Definition: glext.h:3538
void DrawPoint(CByteImage *pImage, const Vec2d &point, int r=255, int g=255, int b=255)
Draws a point into a CByteImage.
unsigned char terminalFont
Definition: BitmapFont.cpp:114
bool LoadPCFFont(const char *pFilePath)
Definition: BitmapFont.cpp:299
unsigned char drawDirection
Definition: BitmapFont.cpp:118
Color
Definition: Color.h:53
#define PCF_BIT_MASK
Definition: BitmapFont.cpp:77
GLubyte GLubyte b
Definition: glext.h:5166
unsigned char inkInside
Definition: BitmapFont.cpp:116
void Init(int nCharacters)
Definition: BitmapFont.cpp:190
int format
Definition: BitmapFont.cpp:88
unsigned char noOverlap
Definition: BitmapFont.cpp:112
GLdouble GLdouble GLdouble r
Definition: glext.h:3227
#define PCF_BYTE_MASK
Definition: BitmapFont.cpp:76
GLenum GLint GLint y
Definition: glext.h:3125
GLenum GLsizei GLenum format
Definition: glext.h:3122
unsigned char constantWidth
Definition: BitmapFont.cpp:115
void AddEncoding(int nEncoding, int nIndex)
Definition: BitmapFont.cpp:251
static short my_invert_byte_order_short(short x, int bInvert=false)
Definition: BitmapFont.cpp:270
#define PCF_ACCELERATORS
Definition: BitmapFont.cpp:61
static unsigned int my_invert_byte_order_int(unsigned int x, int bInvert=false)
Definition: BitmapFont.cpp:283


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Mon Dec 2 2019 03:47:27