| 1 | /* |
|---|
| 2 | * Copyright (c) 2004 Kazunori "jagarl" Ueno |
|---|
| 3 | * Copyright (c) 2000, 2001 Yuki Sawada |
|---|
| 4 | * All rights reserved. |
|---|
| 5 | * |
|---|
| 6 | * Redistribution and use in source and binary forms, with or without |
|---|
| 7 | * modification, are permitted provided that the following conditions |
|---|
| 8 | * are met: |
|---|
| 9 | * 1. Redistributions of source code must retain the above copyright |
|---|
| 10 | * notice, this list of conditions and the following disclaimer. |
|---|
| 11 | * 2. Redistributions in binary form must reproduce the above copyright |
|---|
| 12 | * notice, this list of conditions and the following disclaimer in the |
|---|
| 13 | * documentation and/or other materials provided with the distribution. |
|---|
| 14 | * 3. The name of the author may not be used to endorse or promote products |
|---|
| 15 | * derived from this software without specific prior written permission. |
|---|
| 16 | * |
|---|
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|---|
| 18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|---|
| 19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|---|
| 20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
|---|
| 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|---|
| 22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|---|
| 23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|---|
| 24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|---|
| 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|---|
| 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|---|
| 27 | */ |
|---|
| 28 | |
|---|
| 29 | #include <stdlib.h> |
|---|
| 30 | |
|---|
| 31 | #include "font.h" |
|---|
| 32 | #include "font_peer.h" |
|---|
| 33 | |
|---|
| 34 | #if USE_X11 |
|---|
| 35 | |
|---|
| 36 | #include <sys/ipc.h> |
|---|
| 37 | #include <sys/shm.h> |
|---|
| 38 | |
|---|
| 39 | #include <X11/Xlib.h> |
|---|
| 40 | #include <X11/Xutil.h> |
|---|
| 41 | #include <X11/extensions/XShm.h> |
|---|
| 42 | #include <stdio.h> |
|---|
| 43 | #include <iostream> |
|---|
| 44 | |
|---|
| 45 | #include <vector> |
|---|
| 46 | #include <map> |
|---|
| 47 | |
|---|
| 48 | #include <sstream> |
|---|
| 49 | #include <string> |
|---|
| 50 | #include <stdexcept> |
|---|
| 51 | |
|---|
| 52 | using namespace std; |
|---|
| 53 | |
|---|
| 54 | namespace XKFont { |
|---|
| 55 | inline int read_little_endian_int(const char* buf) { |
|---|
| 56 | const unsigned char *p = (const unsigned char *) buf; |
|---|
| 57 | return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]; |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| 60 | /*********************************** |
|---|
| 61 | ** |
|---|
| 62 | ** Fontinfo / FontSetInfo |
|---|
| 63 | ** |
|---|
| 64 | ** fontset ããç¹å® pixel size ãæã€ |
|---|
| 65 | ** å¥ã®fontsetãäœæããããã®ã¯ã©ã¹ |
|---|
| 66 | */ |
|---|
| 67 | struct FontInfo { |
|---|
| 68 | std::map<int, string> fontlist; |
|---|
| 69 | FontInfo(Display* display, const char* fontname_orig); |
|---|
| 70 | string Search(int pixsize); |
|---|
| 71 | }; |
|---|
| 72 | struct FontSetInfo { |
|---|
| 73 | std::vector<FontInfo*> fontlist; |
|---|
| 74 | FontSetInfo(Display* display, const char* fontset_orig); |
|---|
| 75 | string Search(int pixsize); |
|---|
| 76 | ~FontSetInfo(); |
|---|
| 77 | }; |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | /*********************************** |
|---|
| 81 | ** |
|---|
| 82 | ** Methods of Fontinfo / FontSetInfo |
|---|
| 83 | ** |
|---|
| 84 | */ |
|---|
| 85 | FontInfo::FontInfo(Display* display, const char* fontname_orig) { |
|---|
| 86 | /* ãã©ã³ãã®å€§ããé¢ä¿ã®æ
å ±ãæ¶å» */ |
|---|
| 87 | int i; |
|---|
| 88 | char* fontname = new char[strlen(fontname_orig)+50]; |
|---|
| 89 | int minus_count = 0; |
|---|
| 90 | bool is_skip = false; |
|---|
| 91 | int fc = 0; |
|---|
| 92 | for (i=0; fontname_orig[i]!=0; i++) { |
|---|
| 93 | if (fontname_orig[i] == '-') { |
|---|
| 94 | minus_count++; |
|---|
| 95 | if (minus_count >= 7 && minus_count <= 12) { |
|---|
| 96 | fontname[fc++] = '-'; |
|---|
| 97 | fontname[fc++] = '*'; |
|---|
| 98 | is_skip = true; |
|---|
| 99 | } else { |
|---|
| 100 | is_skip = false; |
|---|
| 101 | } |
|---|
| 102 | } |
|---|
| 103 | if (! is_skip) fontname[fc++] = fontname_orig[i]; |
|---|
| 104 | } |
|---|
| 105 | /* ãã©ã³ãæ
å ±ãåŸã */ |
|---|
| 106 | fontname[fc] = 0; |
|---|
| 107 | int count; |
|---|
| 108 | char** fontnamelist = XListFonts(display, fontname, 100, &count); |
|---|
| 109 | for (i=0; i<count; i++) { |
|---|
| 110 | char* curfont = fontnamelist[i]; |
|---|
| 111 | /* fontname ãã pixel size æ
å ±ãåŸã */ |
|---|
| 112 | int j; |
|---|
| 113 | int minus_count = 0; |
|---|
| 114 | for (j=0; curfont[j] != 0; j++) { |
|---|
| 115 | if (curfont[j] == '-') minus_count++; |
|---|
| 116 | if (minus_count == 7) { |
|---|
| 117 | int pixsize = atoi(curfont+j+1); |
|---|
| 118 | if (fontlist.find(pixsize) == fontlist.end()) { |
|---|
| 119 | fontlist[pixsize] = string(curfont); |
|---|
| 120 | } |
|---|
| 121 | break; |
|---|
| 122 | } |
|---|
| 123 | } |
|---|
| 124 | } |
|---|
| 125 | /* æ€çŽ¢ã«å€±æããå Žåããšãããã fontname ãå
¥ããŠãã */ |
|---|
| 126 | if (fontlist.find(0) == fontlist.end()) { |
|---|
| 127 | fontlist[0] = string(fontname); |
|---|
| 128 | } |
|---|
| 129 | XFreeFontNames(fontnamelist); |
|---|
| 130 | delete[] fontname; |
|---|
| 131 | return; |
|---|
| 132 | } |
|---|
| 133 | string FontInfo::Search(int pixsize) { |
|---|
| 134 | int i; |
|---|
| 135 | /* pixsize ã«è¿ããã©ã³ãã(ããã°)åž°ã */ |
|---|
| 136 | if (fontlist.find(pixsize) != fontlist.end()) return fontlist[pixsize]; |
|---|
| 137 | for (i=1; i<4; i++) { |
|---|
| 138 | if (fontlist.find(pixsize-i) != fontlist.end()) return fontlist[pixsize-i]; |
|---|
| 139 | if (fontlist.find(pixsize+i) != fontlist.end()) return fontlist[pixsize+i]; |
|---|
| 140 | } |
|---|
| 141 | /* èŠã€ãããªãïŒfontlist[0] ãå å·¥ããŠåž°ã */ |
|---|
| 142 | /* pt/xres/yres ãªã©ã®ãã£ãŒã«ãã« '-0-' ãšããã®ãããã° '-*-'ã«å€æ |
|---|
| 143 | ** pixsize ã¯äžãããã pixsize ã«ãã |
|---|
| 144 | */ |
|---|
| 145 | string basefont_s = fontlist[0]; |
|---|
| 146 | const char* basefont = basefont_s.c_str(); |
|---|
| 147 | char* retfont = new char[strlen(basefont)+50]; |
|---|
| 148 | int minus_count = 0; |
|---|
| 149 | int rc = 0; |
|---|
| 150 | bool is_skip = false; |
|---|
| 151 | for (i=0; basefont[i] != 0; i++) { |
|---|
| 152 | if (basefont[i] == '-') { |
|---|
| 153 | minus_count++; |
|---|
| 154 | is_skip = false; |
|---|
| 155 | if (minus_count == 7) { |
|---|
| 156 | sprintf(retfont+rc, "-%d", pixsize); |
|---|
| 157 | rc = strlen(retfont); |
|---|
| 158 | is_skip = true; |
|---|
| 159 | } else if (minus_count > 7 && minus_count <= 12) { |
|---|
| 160 | if (basefont[i+1] == '0' && basefont[i+2] == '-') { |
|---|
| 161 | retfont[rc++]='-'; |
|---|
| 162 | retfont[rc++]='*'; |
|---|
| 163 | is_skip = true; |
|---|
| 164 | } |
|---|
| 165 | } |
|---|
| 166 | } |
|---|
| 167 | if (! is_skip) retfont[rc++] = basefont[i]; |
|---|
| 168 | } |
|---|
| 169 | retfont[rc] = 0; |
|---|
| 170 | string retfont_str = string(retfont); |
|---|
| 171 | delete[] retfont; |
|---|
| 172 | return retfont_str; |
|---|
| 173 | } |
|---|
| 174 | |
|---|
| 175 | FontSetInfo::FontSetInfo(Display* display, const char* fontset_orig) { |
|---|
| 176 | char* fontset = new char[strlen(fontset_orig)+1]; |
|---|
| 177 | strcpy(fontset, fontset_orig); |
|---|
| 178 | char* cur = fontset; |
|---|
| 179 | while(strchr(cur, ',')) { |
|---|
| 180 | char* font = cur; |
|---|
| 181 | cur = strchr(cur, ','); |
|---|
| 182 | *cur++ = '\0'; |
|---|
| 183 | fontlist.push_back(new FontInfo(display, font)); |
|---|
| 184 | } |
|---|
| 185 | fontlist.push_back(new FontInfo(display, cur)); |
|---|
| 186 | delete[] fontset; |
|---|
| 187 | return; |
|---|
| 188 | } |
|---|
| 189 | FontSetInfo::~FontSetInfo() { |
|---|
| 190 | std::vector<FontInfo*>::iterator it; |
|---|
| 191 | for (it=fontlist.begin(); it != fontlist.end(); it++) { |
|---|
| 192 | delete (*it); |
|---|
| 193 | } |
|---|
| 194 | return; |
|---|
| 195 | } |
|---|
| 196 | string FontSetInfo::Search(int pixsize) { |
|---|
| 197 | stringstream s; |
|---|
| 198 | std::vector<FontInfo*>::iterator it; |
|---|
| 199 | for (it=fontlist.begin(); it != fontlist.end(); it++) { |
|---|
| 200 | if (it != fontlist.begin()) s << ","; |
|---|
| 201 | s << (*it)->Search(pixsize); |
|---|
| 202 | } |
|---|
| 203 | s << ends; |
|---|
| 204 | return string(s.str()); |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | /**************************************** |
|---|
| 208 | ** |
|---|
| 209 | ** FontPeerX11 |
|---|
| 210 | */ |
|---|
| 211 | Display* PeerX11::display = NULL; |
|---|
| 212 | void PeerX11::InitDisplay(Display* _d) { |
|---|
| 213 | /* d = ((GdkWindowPrivate*)(top_window.gdkobj()))->xdisplay; */ |
|---|
| 214 | display = _d; |
|---|
| 215 | } |
|---|
| 216 | |
|---|
| 217 | void PeerX11::OpenDisplay(void) { |
|---|
| 218 | if (display != NULL) return; |
|---|
| 219 | |
|---|
| 220 | const char* display_name = getenv("DISPLAY"); |
|---|
| 221 | if (display_name == NULL) display_name = ":0"; |
|---|
| 222 | |
|---|
| 223 | display = XOpenDisplay(display_name); |
|---|
| 224 | |
|---|
| 225 | if (display == NULL) { |
|---|
| 226 | string err = string("XKFont::PeerX11:OpenDisplay() : Cannot open X display ") + display_name; |
|---|
| 227 | throw std::invalid_argument(err); |
|---|
| 228 | } |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | inline int MAX(int a, int b) { |
|---|
| 232 | if (a > b) return a; |
|---|
| 233 | else return b; |
|---|
| 234 | } |
|---|
| 235 | |
|---|
| 236 | PeerX11::PeerX11(const char* fontname, int index, int fontsize, int _vsize) : |
|---|
| 237 | fontset(0), gc(0), canvas(0), image(0), colortable(0) { |
|---|
| 238 | OpenDisplay(); |
|---|
| 239 | |
|---|
| 240 | int scr = DefaultScreen(display); |
|---|
| 241 | Window w = RootWindow(display, scr); |
|---|
| 242 | Colormap cmap = DefaultColormap(display, scr); |
|---|
| 243 | visual = DefaultVisual(display, scr); |
|---|
| 244 | |
|---|
| 245 | if (visual->c_class != TrueColor && visual->c_class != DirectColor) { |
|---|
| 246 | string err = "XKFont::PeerX11:PeerX11() : No supported Color mode of X : neither TrueColor nor DirectColor"; |
|---|
| 247 | throw std::runtime_error(err); |
|---|
| 248 | } |
|---|
| 249 | /* è²ã®åæå */ |
|---|
| 250 | white = visual->red_mask | visual->green_mask | visual->blue_mask; |
|---|
| 251 | black = 0; |
|---|
| 252 | if (visual->green_mask == 0) { |
|---|
| 253 | string err = "XKFont::PeerX11:PeerX11() : Invalid Visual on X"; |
|---|
| 254 | throw std::runtime_error(err); |
|---|
| 255 | } |
|---|
| 256 | shift = 0; |
|---|
| 257 | mask = visual->green_mask; |
|---|
| 258 | while(mask & 0x01) { shift++; mask >>= 1; } |
|---|
| 259 | |
|---|
| 260 | int tablesize = mask+1; |
|---|
| 261 | colortable = new int[tablesize]; |
|---|
| 262 | int i; |
|---|
| 263 | for (i=0; i< tablesize; i++) { |
|---|
| 264 | colortable[i] = i*255/tablesize; |
|---|
| 265 | } |
|---|
| 266 | |
|---|
| 267 | XSupportsLocale(); //FIXME: er... yes? |
|---|
| 268 | |
|---|
| 269 | /* font èªã¿èŸŒã¿ */ |
|---|
| 270 | FontSetInfo fsinfo(display,fontname); |
|---|
| 271 | string fontset_name = fsinfo.Search(fontsize); |
|---|
| 272 | char** missing_cl; |
|---|
| 273 | int missing_cc; |
|---|
| 274 | char* def_s; |
|---|
| 275 | printf("fontset %s\n",fontset_name.c_str()); |
|---|
| 276 | fontset = XCreateFontSet(display, fontset_name.c_str(), &missing_cl, &missing_cc, &def_s); |
|---|
| 277 | |
|---|
| 278 | if (fontset == 0) { |
|---|
| 279 | delete[] colortable; |
|---|
| 280 | string err = string("XKFont::PeerX11:PeerX11() : Cannot create fontset "); |
|---|
| 281 | err += fontset_name; err += " (font name "; err += fontname; err += ")"; |
|---|
| 282 | throw std::invalid_argument(err); |
|---|
| 283 | } |
|---|
| 284 | |
|---|
| 285 | if (missing_cc != 0) { |
|---|
| 286 | cerr << "XKFont::PeerX11:PeerX11() : Cannot found some fonts in the fontset"<<endl; |
|---|
| 287 | cerr << " fontset: "<<fontset_name<<endl; |
|---|
| 288 | cerr << " not found fonts:"<<endl; |
|---|
| 289 | int i; for (i=0; i<missing_cc; i++) { |
|---|
| 290 | cerr << " " << missing_cl[i] << endl; |
|---|
| 291 | } |
|---|
| 292 | } |
|---|
| 293 | |
|---|
| 294 | XFontSetExtents* extents = XExtentsOfFontSet(fontset); |
|---|
| 295 | |
|---|
| 296 | width = extents->max_ink_extent.width; |
|---|
| 297 | height = extents->max_ink_extent.height; |
|---|
| 298 | |
|---|
| 299 | /* calculate ascent / descent */ |
|---|
| 300 | XFontStruct** font_structs; char** font_names; |
|---|
| 301 | int num_fonts = XFontsOfFontSet(fontset, &font_structs, &font_names); |
|---|
| 302 | printf("locale %s\n",XLocaleOfOM(XOMOfOC(fontset))); |
|---|
| 303 | |
|---|
| 304 | ascent = 0; |
|---|
| 305 | for (i=0; i<num_fonts; i++) { |
|---|
| 306 | ascent = MAX(ascent, font_structs[i]->ascent); |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | /* æç»çšã® pixmap ãäœæ */ |
|---|
| 310 | XGCValues gc_values; |
|---|
| 311 | unsigned int gc_values_mask; |
|---|
| 312 | gc_values.function = GXcopy; |
|---|
| 313 | gc_values.fill_style = FillSolid; |
|---|
| 314 | gc_values.arc_mode = ArcPieSlice; |
|---|
| 315 | gc_values.subwindow_mode = ClipByChildren; |
|---|
| 316 | gc_values.graphics_exposures = False; |
|---|
| 317 | gc_values.foreground = white; |
|---|
| 318 | gc_values.background = black; |
|---|
| 319 | gc_values_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures | GCForeground | GCBackground; |
|---|
| 320 | gc = XCreateGC(display, w, gc_values_mask, &gc_values); |
|---|
| 321 | |
|---|
| 322 | canvas = XCreatePixmap(display, w, width, height, DefaultDepth(display, scr)); |
|---|
| 323 | |
|---|
| 324 | /* ã€ã¡ãŒãžè»¢éçšã® image ã®äœæ */ |
|---|
| 325 | int ignore; |
|---|
| 326 | use_shm = false; |
|---|
| 327 | if (XShmQueryExtension(display) == True) { |
|---|
| 328 | x_shm_info.shmid = -1; |
|---|
| 329 | x_shm_info.shmaddr = (char*)-1; |
|---|
| 330 | image = XShmCreateImage(display, visual, DefaultDepth(display, scr), ZPixmap, NULL, &x_shm_info, width, height); |
|---|
| 331 | if (image != NULL) { |
|---|
| 332 | x_shm_info.shmid = shmget(IPC_PRIVATE, image->bytes_per_line*image->height, IPC_CREAT | 0600); |
|---|
| 333 | if (x_shm_info.shmid == -1) { |
|---|
| 334 | XDestroyImage(image); |
|---|
| 335 | image = NULL; |
|---|
| 336 | goto no_shm; |
|---|
| 337 | } |
|---|
| 338 | x_shm_info.readOnly = False; |
|---|
| 339 | x_shm_info.shmaddr = (char*) shmat(x_shm_info.shmid, 0, 0); |
|---|
| 340 | image->data = x_shm_info.shmaddr; |
|---|
| 341 | if (x_shm_info.shmaddr == (char*) -1) { |
|---|
| 342 | XDestroyImage(image); |
|---|
| 343 | shmctl(x_shm_info.shmid, IPC_RMID, 0); |
|---|
| 344 | image = 0; |
|---|
| 345 | goto no_shm; |
|---|
| 346 | } |
|---|
| 347 | XShmAttach(display, &x_shm_info); |
|---|
| 348 | XSync(display, False); |
|---|
| 349 | shmctl(x_shm_info.shmid, IPC_RMID, 0); |
|---|
| 350 | use_shm = true; |
|---|
| 351 | } |
|---|
| 352 | } |
|---|
| 353 | no_shm: //TODO: Understand why he did it, and supress it if needed |
|---|
| 354 | if (image == 0) { |
|---|
| 355 | use_shm = false; |
|---|
| 356 | image = XCreateImage(display, visual, DefaultDepth(display, scr), ZPixmap, 0, 0, width, height, 32, 0); |
|---|
| 357 | image->data = (char*)malloc(image->bytes_per_line * image->height); |
|---|
| 358 | if (image->data == NULL) { |
|---|
| 359 | XDestroyImage(image); |
|---|
| 360 | image = NULL; |
|---|
| 361 | throw bad_alloc(); |
|---|
| 362 | } |
|---|
| 363 | } |
|---|
| 364 | |
|---|
| 365 | Glyph g; |
|---|
| 366 | GlyphCreate(0xa1a2, &g); //FIXME: Two calls? Huh? |
|---|
| 367 | GlyphCreate(0xa4a3, &g); |
|---|
| 368 | } |
|---|
| 369 | |
|---|
| 370 | PeerX11::~PeerX11() { |
|---|
| 371 | if (display) { |
|---|
| 372 | if (fontset) XFreeFontSet(display, fontset); |
|---|
| 373 | if (gc) XFlushGC(display, gc); |
|---|
| 374 | if (canvas) XFreePixmap(display, canvas); |
|---|
| 375 | if (image) { |
|---|
| 376 | if (use_shm) XShmDetach(display, &x_shm_info); |
|---|
| 377 | XDestroyImage(image); |
|---|
| 378 | if (use_shm) shmdt(x_shm_info.shmaddr); |
|---|
| 379 | } |
|---|
| 380 | if (colortable) delete[] colortable; |
|---|
| 381 | } |
|---|
| 382 | } |
|---|
| 383 | |
|---|
| 384 | bool PeerX11::GlyphCreate(unsigned int code, Glyph* glyph) { |
|---|
| 385 | XRectangle ink, logic; |
|---|
| 386 | |
|---|
| 387 | char str[3]={0,0,0}; |
|---|
| 388 | |
|---|
| 389 | if ( (code>>8)&0xff){ |
|---|
| 390 | str[0]=code>>8; |
|---|
| 391 | str[1]=code & 0xff; |
|---|
| 392 | } else { |
|---|
| 393 | str[0]=code; |
|---|
| 394 | } |
|---|
| 395 | |
|---|
| 396 | XmbTextExtents(fontset, str, strlen(str),&ink,&logic); |
|---|
| 397 | int cwidth = logic.width; |
|---|
| 398 | XmbDrawImageString(display, canvas, fontset, gc, 0, -logic.y, str, strlen(str)); |
|---|
| 399 | if (use_shm) { |
|---|
| 400 | XShmGetImage(display, canvas, image, 0, 0, AllPlanes); |
|---|
| 401 | } else { |
|---|
| 402 | XGetSubImage(display, canvas, 0, 0, width, height, AllPlanes, ZPixmap, image, 0, 0); |
|---|
| 403 | } |
|---|
| 404 | XSync(display, False); |
|---|
| 405 | glyph->bitmap.buffer = new unsigned char[logic.width*logic.height]; |
|---|
| 406 | int i; |
|---|
| 407 | unsigned char* mem = (unsigned char*) image->data; |
|---|
| 408 | unsigned char* dest = glyph->bitmap.buffer; |
|---|
| 409 | int bpp = image->bytes_per_line/width; |
|---|
| 410 | int bpl = image->bytes_per_line; |
|---|
| 411 | for (i=0; i < logic.height; i++) { |
|---|
| 412 | unsigned char* m = mem; |
|---|
| 413 | int j; for (j=0; j<cwidth; j++) { |
|---|
| 414 | *dest = colortable[((read_little_endian_int((char*)m))>>shift) & mask]; |
|---|
| 415 | dest++; |
|---|
| 416 | m += bpp; |
|---|
| 417 | } |
|---|
| 418 | mem += bpl; |
|---|
| 419 | } |
|---|
| 420 | glyph->bitmap_left = logic.x; |
|---|
| 421 | glyph->bitmap_top = -logic.y; |
|---|
| 422 | glyph->bitmap.width = logic.width; |
|---|
| 423 | glyph->bitmap.rows = logic.height; |
|---|
| 424 | glyph->advance.x = logic.width + 1; |
|---|
| 425 | glyph->advance.y = logic.height+ 1; |
|---|
| 426 | |
|---|
| 427 | return true; |
|---|
| 428 | } |
|---|
| 429 | }; |
|---|
| 430 | |
|---|
| 431 | #endif /* USE_X11 */ |
|---|