Torque3D Documentation / _generateds / x86UNIXFont.client.cpp

x86UNIXFont.client.cpp

Engine/source/platformX86UNIX/x86UNIXFont.client.cpp

More...

Public Functions

createPlatformFont(const char * name, dsize_t size, U32 charset)
XftFont *
loadFont(const char * name, S32 size, Display * display)

Detailed Description

Public Functions

createPlatformFont(const char * name, dsize_t size, U32 charset)

loadFont(const char * name, S32 size, Display * display)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "gfx/gFont.h"
 25#include "gfx/bitmap/gBitmap.h"
 26#include "math/mRect.h"
 27#include "console/console.h"
 28#include "core/strings/unicode.h"
 29#include "core/stringTable.h"
 30#include "platformX86UNIX/platformX86UNIX.h"
 31#include "platformX86UNIX/x86UNIXFont.h"
 32
 33// Needed by createFont
 34#include <X11/Xlib.h>
 35#include <X11/Xutil.h>
 36#include <X11/Xos.h>
 37#include <X11/Xatom.h>
 38#include <X11/Xft/Xft.h>
 39//#include <X11/extensions/Xrender.h>      // For XRenderColor
 40
 41// Needed for getenv in createFont
 42#include <stdlib.h>
 43XftFont *loadFont(const char *name, S32 size, Display *display)
 44{
 45  XftFont *fontInfo = NULL;
 46  const char* fontname = name;
 47  if (dStrlen(fontname)==0)
 48    fontname = "arial";
 49  else if (stristr(name, "arial") != NULL)
 50    fontname = "arial";
 51  else if (stristr(name, "lucida console") != NULL)
 52    fontname = "lucida console";
 53
 54  const char* weight = "medium";
 55  const char* slant = "roman"; // no slant
 56
 57  if (stristr(name, "bold") != NULL)
 58    weight = "bold";
 59  if (stristr(name, "italic") != NULL)
 60    slant = "italic";
 61
 62  int mSize = size - 2 - (int)((float)size * 0.1);
 63  char xfontName[512];
 64  // We specify a lower DPI to get 'correct' looking fonts, if we go with the
 65  // native DPI the fonts are to big and don't fit the widgets.
 66  dSprintf(xfontName, 512, "%s-%d:%s:slant=%s:dpi=76", fontname, mSize, weight, slant);
 67
 68  // Lets see if Xft can get a font for us.
 69  char xftname[1024];
 70  fontInfo = XftFontOpenName(display, DefaultScreen(display), xfontName);
 71  // Cant find a suitabke font, default to a known font (6x10)
 72  if ( !fontInfo )
 73    {
 74   dSprintf(xfontName, 512, "6x10-%d:%s:slant=%s:dpi=76", mSize, weight, slant);
 75      fontInfo = XftFontOpenName(display, DefaultScreen(display), xfontName);
 76    }
 77      XftNameUnparse(fontInfo->pattern, xftname, 1024);
 78
 79#ifdef DEBUG
 80    Con::printf("Font '%s %d' mapped to '%s'\n", name, size, xftname);
 81#endif
 82
 83  return fontInfo;
 84}
 85
 86
 87//GOldFont* createFont(const char *name, dsize_t size, U32 charset)
 88//{
 89//  Display *display = XOpenDisplay(getenv("DISPLAY"));
 90//  int screen;
 91//
 92//  if (!display)
 93//    AssertFatal(false, "createFont: cannot connect to X server");
 94//  screen = DefaultScreen(display);
 95//
 96//  XftFont *font = loadFont (name, size, display);
 97//  if (!font) // This should almost never trigger anymore.
 98//    AssertFatal(false, "createFont: cannot load font");
 99//
100//  // Create the pixmap to draw on.
101//  Pixmap pixmap = XCreatePixmap(display,
102//                                DefaultRootWindow(display),
103//                                font->max_advance_width,
104//                                font->height,
105//                                DefaultDepth(display, screen));
106//  // And the Xft wrapper around it.
107//  XftDraw *draw = XftDrawCreate(display,
108//                                pixmap,
109//                                DefaultVisual(display, screen),
110//                                DefaultColormap(display, screen));
111//  // Allocate some colors, we don't use XftColorAllocValue here as that
112//  // Don't appear to function correctly (or I'm using it wrong) As we only do
113//  // this twice per new un cached font it isn't that big of a penalty. (Each
114//  // call to XftColorAllocName involves a round trip to the X Server)
115//  XftColor black, white;
116//  XftColorAllocName(display,
117//                    DefaultVisual(display, screen),
118//                    DefaultColormap(display, screen),
119//                    "black",
120//                    &black);
121//  // White
122//  XftColorAllocName(display,
123//                    DefaultVisual(display, screen),
124//                    DefaultColormap(display, screen),
125//                    "white",
126//                    &white);
127//  
128//  // The font.
129//  GOldFont *retFont = new GOldFont;
130//  static U8 scratchPad[65536];
131//  int x, y;
132//  // insert bitmaps into the font for each character
133//  for(U16 i = 32; i < 256; i++)
134//  {
135//    XGlyphInfo extent;
136//    FT_UInt glyph;
137//    if (!XftCharExists(display, font, i))
138//      {
139// retFont->insertBitmap(i, scratchPad, 0, 0, 0, 0, 0, font->max_advance_width);
140// continue;
141//      }
142//    // Get the glyph and its extents.
143//    glyph = XftCharIndex(display, font, i);
144//    XftGlyphExtents (display, font, &glyph, 1, &extent);
145//    // Clear the bounding box and draw the glyph
146//    XftDrawRect (draw, &black, 0, 0, font->max_advance_width, font->height);
147//    XftDrawGlyphs (draw, &white, font, 0, font->ascent, &glyph, 1);
148//    // Grab the rendered image ...
149//    XImage *ximage = XGetImage(display, pixmap, 0, 0,
150//              extent.xOff, font->height,
151//              AllPlanes, XYPixmap);
152//    if (ximage == NULL)
153//      AssertFatal(false, "cannot get x image");
154//    // And store each pixel in the scratchPad for insertion into the bitmap.
155//    // We grab the full height of the pixmap.
156//    for(y = 0; y < font->height; y++)
157//      {
158// // and the width of the glyph and its padding.
159// for(x = 0; x < extent.xOff; x++)
160//     scratchPad[y * extent.xOff + x] = static_cast<U8>(XGetPixel(ximage, x, y));
161//      }
162//    // Done with the image.
163//    XDestroyImage(ximage);
164//    // Add it to the bitmap.
165//    retFont->insertBitmap(i,                   // index
166//         scratchPad,          // src
167//         extent.xOff,         // stride
168//         extent.xOff,         // width
169//         font->height,        // height
170//         0,                   // xOrigin
171//         font->ascent,        // yOrigin
172//         extent.xOff);        // xIncrement
173//    
174//  }
175//  retFont->pack(font->height, font->ascent);
176//  XftFontClose(display, font);
177//
178//  XftColorFree(display, DefaultVisual(display, screen),
179//               DefaultColormap(display, screen), &black);
180//  XftColorFree(display, DefaultVisual(display, screen),
181//               DefaultColormap(display, screen), &white);
182//  XftDrawDestroy(draw);
183//  XFreePixmap(display, pixmap);
184//  XCloseDisplay(display);
185//  return retFont;
186//}
187
188
189// XA: New class for the unix unicode font
190PlatformFont *createPlatformFont(const char *name, dsize_t size, U32 charset /* = TGE_ANSI_CHARSET */)
191{
192  PlatformFont *retFont = new x86UNIXFont;
193
194  if(retFont->create(name, size, charset))
195    return retFont;
196
197  delete retFont;
198  return NULL;
199}
200
201x86UNIXFont::x86UNIXFont()
202{}
203
204x86UNIXFont::~x86UNIXFont()
205{}
206
207
208bool x86UNIXFont::create(const char *name, dsize_t size, U32 charset)
209{
210  Display *display = XOpenDisplay(getenv("DISPLAY"));
211  if (display == NULL)
212    AssertFatal(false, "createFont: cannot connect to X server");
213
214  XftFont *font = loadFont(name, size, display);
215  
216  if (!font)
217  {
218    Con::errorf("Error: Could not load font -%s-", name);
219    return false;
220  }
221  char xfontname[1024];
222  XftNameUnparse(font->pattern, xfontname, 1024);
223#ifdef DEBUG
224  Con::printf("CreateFont: request for %s %d, using %s", name, size, xfontname);
225#endif
226  // store some info about the font
227  baseline = font->ascent;
228  height = font->height;
229  mFontName = StringTable->insert(xfontname);
230  XftFontClose (display, font);
231  // DISPLAY
232  XCloseDisplay(display);
233
234  return true;
235}
236
237bool x86UNIXFont::isValidChar(const UTF16 str) const
238{
239  // 0x20  == 32
240  // 0x100 == 256
241  if( str < 0x20 || str > 0x100 )
242    return false;
243
244  return true;
245}
246
247bool x86UNIXFont::isValidChar(const UTF8 *str) const
248{
249
250  return isValidChar(oneUTF32toUTF16(oneUTF8toUTF32(str,NULL)));
251}
252
253PlatformFont::CharInfo &x86UNIXFont::getCharInfo(const UTF16 ch) const
254{
255  Display *display = XOpenDisplay(getenv("DISPLAY"));
256  if (!display )
257    AssertFatal(false, "createFont: cannot connect to X server");
258
259  static PlatformFont::CharInfo c;
260  dMemset(&c, 0, sizeof(c));
261  c.bitmapIndex = 0;
262  c.xOffset     = 0;
263  c.yOffset     = 0;
264
265  XftFont *fontInfo  = XftFontOpenName(display, DefaultScreen(display), mFontName);
266  if (!fontInfo)
267    AssertFatal(false, "createFont: cannot load font");
268
269  int screen = DefaultScreen(display);
270  // Create the pixmap to draw on.
271  Drawable pixmap = XCreatePixmap(display,
272              DefaultRootWindow(display),
273              fontInfo->max_advance_width,
274              fontInfo->height,
275              DefaultDepth(display, screen));
276  // And the Xft wrapper around it.
277  XftDraw *draw = XftDrawCreate(display,
278                                pixmap,
279                                DefaultVisual(display, screen),
280                                DefaultColormap(display, screen));
281  // Allocate some colors, we don't use XftColorAllocValue here as that
282  // Don't appear to function correctly (or I'm using it wrong) As we only do
283  // this twice per new un cached font it isn't that big of a penalty. (Each
284  // call to XftColorAllocName involves a round trip to the X Server)
285  XftColor black, white;
286  XftColorAllocName(display,
287                    DefaultVisual(display, screen),
288                    DefaultColormap(display, screen),
289                    "black",
290                    &black);
291  // White
292  XftColorAllocName(display,
293                    DefaultVisual(display, screen),
294                    DefaultColormap(display, screen),
295                    "white",
296                    &white);
297  
298  XGlyphInfo charinfo;
299  XftTextExtents16(display, fontInfo, &ch, 1, &charinfo);
300  c.height     = fontInfo->height;
301  c.xOrigin    = 0; 
302  c.yOrigin    = fontInfo->ascent;
303  c.xIncrement = charinfo.xOff;
304  c.width      = charinfo.xOff;
305  // kick out early if the character is undrawable
306  if( c.width == 0 || c.height == 0)
307    return c;
308
309  // allocate a greyscale bitmap and clear it.
310  int bitmapDataSize = c.width * c.height;
311  c.bitmapData = new U8[bitmapDataSize];
312  dMemset(c.bitmapData, 0, bitmapDataSize);
313
314  XftDrawRect (draw, &black, 0, 0, fontInfo->max_advance_width, fontInfo->height);
315  XftDrawString16 (draw, &white, fontInfo, 0, fontInfo->ascent, &ch, 1);
316  // grab the pixmap image
317
318  XImage *ximage = XGetImage(display, pixmap, 0, 0, 
319              charinfo.xOff, fontInfo->height, 
320              AllPlanes, XYPixmap);
321  if (!ximage)
322    AssertFatal(false, "cannot get x image");
323  int x, y;
324
325  // grab each pixel and store it in the scratchPad
326  for(y = 0; y < fontInfo->height; y++)
327  {
328    for(x = 0; x < charinfo.xOff; x++)
329      c.bitmapData[y * charinfo.xOff + x] = static_cast<U8>(XGetPixel(ximage, x, y));
330  }
331  XDestroyImage(ximage);
332
333  XftColorFree(display, DefaultVisual(display, screen),
334               DefaultColormap(display, screen), &black);
335  XftColorFree(display, DefaultVisual(display, screen),
336               DefaultColormap(display, screen), &white);
337  XftDrawDestroy(draw);
338  XFreePixmap(display, pixmap);
339  XCloseDisplay(display);
340
341  return c;
342}
343
344
345PlatformFont::CharInfo &x86UNIXFont::getCharInfo(const UTF8 *str) const
346{
347  return getCharInfo(oneUTF32toUTF16(oneUTF8toUTF32(str,NULL)));
348}
349