x86UNIXFont.client.cpp
Engine/source/platformX86UNIX/x86UNIXFont.client.cpp
Public Functions
createPlatformFont(const char * name, dsize_t size, U32 charset)
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