1 module unde.font; 2 3 import derelict.sdl2.sdl; 4 import derelict.sdl2.ttf; 5 version(FreeType) 6 { 7 import derelict.freetype.ft; 8 } 9 10 import unde.global_state; 11 import unde.lib; 12 13 import core.exception; 14 import core.memory; 15 16 import std.math; 17 import std.stdio; 18 import std.conv; 19 import std..string; 20 21 version(Windows) 22 { 23 import berkeleydb.all: ssize_t; 24 } 25 26 27 struct CharSize 28 { 29 string chr; 30 int size; 31 SDL_Color color; 32 size_t font; 33 } 34 35 struct LineSize 36 { 37 string line; 38 int size; 39 int line_width; 40 int line_height; 41 SDL_Color color; 42 ushort[] attrs; 43 ssize_t start_pos; 44 ssize_t end_pos; 45 } 46 47 enum Attr 48 { 49 Black, 50 Red, 51 Green, 52 Brown, 53 Blue, 54 Magenta, 55 Cyan, 56 White, 57 Bold = 0x100, 58 Underscore = 0x200, 59 HalfBright = 0x400, 60 Blink = 0x800, 61 Color = 0x1000, 62 } 63 64 class Font 65 { 66 SDL_Renderer *renderer; 67 version(FreeType) 68 { 69 FT_Library library; 70 FT_Face[5] face; 71 } 72 TTF_Font *[16][5]font; 73 SDL_Texture*[16] attr_textures; 74 75 long last_chars_cache_use; 76 Texture_Tick[CharSize] chars_cache; 77 long last_lines_cache_use; 78 Texture_Tick[LineSize] lines_cache; 79 80 auto 81 get_char_from_cache(in string chr, in int size, in SDL_Color color, size_t f = 0) 82 { 83 auto charsize = CharSize(chr.idup(), size, color, f); 84 auto st = charsize in chars_cache; 85 if (st) 86 { 87 st.tick = SDL_GetTicks(); 88 last_chars_cache_use = SDL_GetTicks(); 89 } 90 else 91 { 92 version(FreeType) 93 { 94 auto glyph_index = FT_Get_Char_Index(face[f], to!dchar(chr), FT_LOAD_RENDER);//FT_Get_Char_Index( face[0], to!dchar(chr) ); 95 } 96 else 97 { 98 int glyph_index; 99 dchar dchr; wchar wchr; 100 try 101 { 102 dchr = to!dchar(chr); 103 wchr = to!wchar(dchr); 104 glyph_index = TTF_GlyphIsProvided(font[f][size], wchr); 105 } 106 catch (Exception e) 107 { 108 } 109 } 110 SDL_Surface *surface; 111 if (glyph_index > 0) 112 { 113 if (size < 9) 114 { 115 surface = TTF_RenderUTF8_Solid( 116 font[f][size], chr.toStringz(), 117 color ); 118 } 119 else 120 { 121 surface = TTF_RenderUTF8_Blended( 122 font[f][size], chr.toStringz(), 123 color ); 124 } 125 } 126 else 127 { 128 if (size < 9) 129 { 130 surface = TTF_RenderUTF8_Solid( 131 font[4][size], chr.toStringz(), 132 color ); 133 } 134 else 135 { 136 surface = TTF_RenderUTF8_Blended( 137 font[4][size], chr.toStringz(), 138 color ); 139 } 140 } 141 142 auto texture = 143 SDL_CreateTextureFromSurface(renderer, surface); 144 145 if (surface) 146 { 147 chars_cache[charsize] = Texture_Tick(surface.w, surface.h, [], texture, SDL_GetTicks()); 148 SDL_FreeSurface(surface); 149 last_chars_cache_use = SDL_GetTicks(); 150 st = charsize in chars_cache; 151 } 152 } 153 154 return st; 155 } 156 157 /* EN: clear cache from old entries 158 RU: очистить кеш от старых элементов */ 159 void 160 clear_chars_cache() 161 { 162 int cleared = 0; 163 foreach(k, v; chars_cache) 164 { 165 if (v.tick < last_chars_cache_use - 30_000) 166 { 167 cleared++; 168 if (v.texture) SDL_DestroyTexture(v.texture); 169 if ( !chars_cache.remove(k) ) 170 { 171 writefln("Can't remove chars cache key %s", k); 172 } 173 //writefln("v.tick = %s < %s. Remove key %s", 174 // v.tick, gs.last_pict_cache_use - 300_000, k); 175 } 176 } 177 if (cleared) 178 { 179 //writefln("Cleared %d objects from lines cache", cleared); 180 GC.collect(); 181 } 182 } 183 184 public SDL_Rect 185 get_size_of_line(inout (char)[] text, 186 int size, long line_width, int line_height, 187 SDL_Color color) 188 { 189 text ~= " "; 190 if (text.length > 0 && text[$-1] == '\r') text = text[0..$-1]; 191 int lines = 1; 192 193 int line_ax = 0; 194 int line_ay = 0; 195 196 SDL_Rect rect = SDL_Rect(0, 0, 1, 1); 197 for (size_t i = 0; i < text.length; i += text.mystride(i)) 198 { 199 auto chrlen = text.mystride(i); 200 if (i+chrlen >= text.length) chrlen = 1; 201 string chr = text[i..i+chrlen].idup(); 202 //writefln("chr = %s", chr); 203 auto st = get_char_from_cache(chr, size, color); 204 if (!st) continue; 205 206 if (line_width > 0) 207 { 208 if (line_ax + st.w > line_width || chr == "\n") 209 { 210 if (line_ax > rect.w) rect.w = line_ax; 211 line_ax = 0; 212 line_ay += line_height; 213 lines++; 214 if (chr == "\n") continue; 215 } 216 } 217 218 line_ax += st.w; 219 } 220 221 if (line_ax > rect.w) rect.w = line_ax; 222 rect.h = lines*line_height; 223 return rect; 224 } 225 226 public SDL_Rect 227 get_size_of_line(int cols, int rows, 228 int size, SDL_Color color) 229 { 230 SDL_Rect rect = SDL_Rect(0, 0, 1, 1); 231 auto st = get_char_from_cache(" ", size, color); 232 if (!st) return rect; 233 234 rect.w = cols*st.w; 235 rect.h = rows*st.h; 236 237 return rect; 238 } 239 240 auto 241 get_line_from_cache(string text, 242 int size, int line_width, int line_height, SDL_Color color, 243 ushort[] attrs = null, ssize_t start_pos=-1, ssize_t end_pos=-1) 244 { 245 auto linesize = LineSize(text.idup(), size, line_width, line_height, 246 color, attrs.dup(), start_pos, end_pos); 247 auto tt = linesize in lines_cache; 248 if (tt) 249 { 250 tt.tick = SDL_GetTicks(); 251 last_lines_cache_use = SDL_GetTicks(); 252 } 253 else 254 { 255 auto rect = get_size_of_line(text, size, line_width, line_height, color); 256 257 if (rect.w > 8192) rect.w = 8192; 258 if (rect.h > 8192) rect.h = 8192; 259 auto texture = SDL_CreateTexture(renderer, 260 SDL_PIXELFORMAT_ARGB8888, 261 SDL_TEXTUREACCESS_TARGET, 262 rect.w, 263 rect.h); 264 if( !texture ) 265 { 266 throw new Exception(format("get_line_from_cache: Error while creating texture: %s", 267 SDL_GetError().to!string() )); 268 } 269 270 auto old_texture = SDL_GetRenderTarget(renderer); 271 int r = SDL_SetRenderTarget(renderer, texture); 272 if (r < 0) 273 { 274 throw new Exception(format("get_line_from_cache: Error while set render target texture: %s", 275 SDL_GetError().to!string() )); 276 } 277 278 SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); 279 r = SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); 280 if (r < 0) 281 { 282 writefln("Can't SDL_SetRenderDrawColor: %s", 283 to!string(SDL_GetError())); 284 } 285 r = SDL_RenderClear(renderer); 286 if (r < 0) 287 { 288 throw new Exception(format("Error while clear renderer: %s", 289 SDL_GetError().to!string() )); 290 } 291 292 text ~= " "; 293 if (text.length > 0 && text[$-1] == '\r') text = text[0..$-1]; 294 295 long line_ax = 0; 296 long line_ay = 0; 297 298 SDL_Rect[] chars = []; 299 300 ssize_t index; 301 ssize_t attrs_i; 302 //writefln("text=%s", text); 303 //writefln("attrs=%s", attrs); 304 for (size_t i=0; i < text.length; i+=text.mystride(i), attrs_i++) 305 { 306 auto chrlen = text.mystride(i); 307 if (i+chrlen >= text.length) chrlen = 1; 308 string chr = text[i..i+chrlen].idup(); 309 SDL_Color real_color = color; 310 ushort attr = (Attr.Black<<4 | Attr.White); 311 if ( attrs && attrs_i < attrs.length ) 312 attr = attrs[attrs_i]; 313 else 314 attr = Attr.Black<<4 | Attr.White; 315 if (i >= start_pos && i <= end_pos) 316 attr = attr & 0x0F | (Attr.Blue << 4); 317 if ( attr != (Attr.Black<<4 | Attr.White) && !(attr & Attr.Color) ) 318 { 319 switch (attr & 0x0F) 320 { 321 case Attr.Black: 322 real_color = SDL_Color(0x00, 0x00, 0x00, 0xFF); 323 break; 324 case Attr.Red: 325 real_color = SDL_Color(0xFF, 0x00, 0x00, 0xFF); 326 break; 327 case Attr.Green: 328 real_color = SDL_Color(0x00, 0xFF, 0x00, 0xFF); 329 break; 330 case Attr.Brown: 331 real_color = SDL_Color(0xFF, 0xFF, 0x30, 0xFF); 332 break; 333 case Attr.Blue: 334 real_color = SDL_Color(0x00, 0x00, 0xFF, 0xFF); 335 break; 336 case Attr.Magenta: 337 real_color = SDL_Color(0xFF, 0x00, 0xFF, 0xFF); 338 break; 339 case Attr.Cyan: 340 real_color = SDL_Color(0x00, 0xFF, 0xFF, 0xFF); 341 break; 342 case Attr.White: 343 real_color = SDL_Color(0xFF, 0xFF, 0xFF, 0xFF); 344 break; 345 default: 346 break; 347 } 348 } 349 auto st = get_char_from_cache(chr, size, real_color, (attr&Attr.Bold?1:0)); 350 if (!st) continue; 351 352 SDL_Rect dst; 353 dst.x = cast(int)line_ax; 354 dst.y = cast(int)line_ay; 355 dst.w = st.w; 356 dst.h = st.h; 357 358 chars.length = i+1; 359 chars[i] = dst; 360 361 if (line_width > 0) 362 { 363 if (line_ax + st.w > line_width || chr == "\n") 364 { 365 line_ax = 0; 366 line_ay += line_height; 367 if (chr == "\n") continue; 368 } 369 } 370 /*writefln("%s - %s, %s, %s, %s", 371 line, dst.x, dst.y, dst.w, dst.h);*/ 372 373 dst.x = cast(int)line_ax; 374 dst.y = cast(int)line_ay; 375 dst.w = st.w; 376 dst.h = st.h; 377 378 if ( ((attr & 0xF0)>>4) != Attr.Black ) 379 { 380 r = SDL_RenderCopyEx(renderer, attr_textures[(attr & 0xF0)>>4], null, &dst, 0, 381 null, SDL_FLIP_NONE); 382 if (r < 0) 383 { 384 writefln( "draw_line(): Error while render copy: %s", SDL_GetError().to!string() ); 385 } 386 } 387 388 r = SDL_RenderCopyEx(renderer, st.texture, null, &dst, 0, 389 null, SDL_FLIP_NONE); 390 if (r < 0) 391 { 392 writefln( "draw_line(): Error while render copy: %s", SDL_GetError().to!string() ); 393 } 394 395 if (attr & Attr.Underscore) 396 { 397 dst.y += dst.h - 2; 398 dst.h = 1; 399 400 r = SDL_RenderCopyEx(renderer, attr_textures[attr & 0xF], null, &dst, 0, 401 null, SDL_FLIP_NONE); 402 if (r < 0) 403 { 404 writefln( "draw_line(): Error while render copy: %s", SDL_GetError().to!string() ); 405 } 406 } 407 408 line_ax += st.w; 409 } 410 411 r = SDL_SetRenderTarget(renderer, old_texture); 412 if (r < 0) 413 { 414 throw new Exception(format("get_line_from_cache: Error while restore render target old_texture: %s", 415 SDL_GetError().to!string() )); 416 } 417 418 lines_cache[linesize] = Texture_Tick(rect.w, rect.h, chars, texture, SDL_GetTicks()); 419 last_lines_cache_use = SDL_GetTicks(); 420 tt = linesize in lines_cache; 421 } 422 423 return tt; 424 } 425 426 auto 427 get_line_from_cache(dchar[] text, int cols, int rows, 428 int size, int line_height, SDL_Color color, ushort[] attrs = null, 429 ssize_t start_pos=-1, ssize_t end_pos=-1) 430 { 431 auto linesize = LineSize(to!(string)(text.idup()), size, cols*rows, 432 line_height, color, attrs.dup(), start_pos, end_pos); 433 auto tt = linesize in lines_cache; 434 if (tt) 435 { 436 tt.tick = SDL_GetTicks(); 437 last_lines_cache_use = SDL_GetTicks(); 438 } 439 else 440 { 441 auto rect = get_size_of_line(cols, rows, size, color); 442 443 if (rect.w > 8192) rect.w = 8192; 444 if (rect.h > 8192) rect.h = 8192; 445 auto texture = SDL_CreateTexture(renderer, 446 SDL_PIXELFORMAT_ARGB8888, 447 SDL_TEXTUREACCESS_TARGET, 448 rect.w, 449 rect.h); 450 if( !texture ) 451 { 452 throw new Exception(format("get_line_from_cache: Error while creating texture: %s", 453 SDL_GetError().to!string() )); 454 } 455 456 auto old_texture = SDL_GetRenderTarget(renderer); 457 int r = SDL_SetRenderTarget(renderer, texture); 458 if (r < 0) 459 { 460 throw new Exception(format("get_line_from_cache: Error while set render target texture: %s", 461 SDL_GetError().to!string() )); 462 } 463 464 SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); 465 r = SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); 466 if (r < 0) 467 { 468 writefln("Can't SDL_SetRenderDrawColor: %s", 469 to!string(SDL_GetError())); 470 } 471 r = SDL_RenderClear(renderer); 472 if (r < 0) 473 { 474 throw new Exception(format("Error while clear renderer: %s", 475 SDL_GetError().to!string() )); 476 } 477 478 long line_ax = 0; 479 long line_ay = 0; 480 481 SDL_Rect[] chars = []; 482 chars.length = text.length; 483 484 ssize_t index; 485 //writefln("text=%s", text); 486 //writefln("attrs=%s", attrs); 487 for (size_t i=0; i < text.length; i++) 488 { 489 string chr = to!string(text[i]); 490 SDL_Color real_color = color; 491 ushort attr = (Attr.Black<<4 | Attr.White); 492 if ( attrs ) 493 attr = attrs[i]; 494 else attr = Attr.Black<<4 | Attr.White; 495 if (i >= start_pos && i <= end_pos) 496 attr = attr & 0x0F | (Attr.Blue << 4); 497 if ( attr != (Attr.Black<<4 | Attr.White) && !(attr & Attr.Color) ) 498 { 499 switch (attr & 0x0F) 500 { 501 case Attr.Black: 502 real_color = SDL_Color(0x00, 0x00, 0x00, 0xFF); 503 break; 504 case Attr.Red: 505 real_color = SDL_Color(0xFF, 0x00, 0x00, 0xFF); 506 break; 507 case Attr.Green: 508 real_color = SDL_Color(0x00, 0xFF, 0x00, 0xFF); 509 break; 510 case Attr.Brown: 511 real_color = SDL_Color(0xFF, 0xFF, 0x30, 0xFF); 512 break; 513 case Attr.Blue: 514 real_color = SDL_Color(0x80, 0x80, 0xFF, 0xFF); 515 break; 516 case Attr.Magenta: 517 real_color = SDL_Color(0xFF, 0x00, 0xFF, 0xFF); 518 break; 519 case Attr.Cyan: 520 real_color = SDL_Color(0x00, 0xFF, 0xFF, 0xFF); 521 break; 522 case Attr.White: 523 real_color = SDL_Color(0xFF, 0xFF, 0xFF, 0xFF); 524 break; 525 default: 526 break; 527 } 528 } 529 auto st = get_char_from_cache(chr, size, real_color, (attr&Attr.Bold?1:0)); 530 if (!st) continue; 531 532 if (i > 0 && i%cols == 0) 533 { 534 line_ax = 0; 535 line_ay += line_height; 536 } 537 538 SDL_Rect dst; 539 dst.x = cast(int)line_ax; 540 dst.y = cast(int)line_ay; 541 dst.w = st.w; 542 dst.h = st.h; 543 544 chars[i] = dst; 545 546 if ( ((attr & 0xF0)>>4) != Attr.Black ) 547 { 548 r = SDL_RenderCopyEx(renderer, attr_textures[(attr & 0xF0)>>4], null, &dst, 0, 549 null, SDL_FLIP_NONE); 550 if (r < 0) 551 { 552 writefln( "draw_line(): Error while render copy: %s", SDL_GetError().to!string() ); 553 } 554 } 555 556 r = SDL_RenderCopyEx(renderer, st.texture, null, &dst, 0, 557 null, SDL_FLIP_NONE); 558 if (r < 0) 559 { 560 writefln( "draw_line(): Error while render copy: %s", SDL_GetError().to!string() ); 561 } 562 563 if ( attr & Attr.Underscore ) 564 { 565 dst.y += dst.h - 4; 566 dst.h = 1; 567 568 r = SDL_RenderCopyEx(renderer, attr_textures[attr & 0xF], null, &dst, 0, 569 null, SDL_FLIP_NONE); 570 if (r < 0) 571 { 572 writefln( "draw_line(): Error while render copy: %s", SDL_GetError().to!string() ); 573 } 574 } 575 576 line_ax += st.w; 577 } 578 579 r = SDL_SetRenderTarget(renderer, old_texture); 580 if (r < 0) 581 { 582 throw new Exception(format("get_line_from_cache: Error while restore render target old_texture: %s", 583 SDL_GetError().to!string() )); 584 } 585 586 lines_cache[linesize] = Texture_Tick(rect.w, rect.h, chars, texture, SDL_GetTicks()); 587 last_lines_cache_use = SDL_GetTicks(); 588 tt = linesize in lines_cache; 589 } 590 591 return tt; 592 } 593 594 /* EN: clear cache from old entries 595 RU: очистить кеш от старых элементов */ 596 void 597 clear_lines_cache() 598 { 599 int cleared; 600 foreach(k, v; lines_cache) 601 { 602 if (v.tick < last_lines_cache_use - 30_000) 603 { 604 cleared++; 605 if (v.texture) SDL_DestroyTexture(v.texture); 606 if (!lines_cache.remove(k)) 607 { 608 writefln("NOT DELETED key %s", k.line); 609 writefln("k in lines_cache %s", k in lines_cache); 610 } 611 //writefln("v.tick = %s < %s. Remove key %s", 612 // v.tick, last_lines_cache_use - 30_000, k); 613 } 614 } 615 if (cleared) 616 { 617 //writefln("Cleared %d objects from lines cache", cleared); 618 GC.collect(); 619 } 620 } 621 622 this(SDL_Renderer *renderer) 623 { 624 this.renderer = renderer; 625 626 version(FreeType) 627 { 628 DerelictFT.load(); 629 auto err = FT_Init_FreeType(&library); 630 if (err != 0) 631 { 632 throw new Exception(format("FT_Init_FreeType: %s\n", 633 err)); 634 } 635 } 636 637 DerelictSDL2ttf.load(); 638 639 if(TTF_Init()==-1) { 640 throw new Exception(format("TTF_Init: %s\n", 641 TTF_GetError().to!string())); 642 } 643 644 version (linux) 645 { 646 version(Mageia) 647 { 648 string[] font_list = ["/usr/share/fonts/TTF/liberation/LiberationMono-Regular.ttf", 649 "/usr/share/fonts/TTF/liberation/LiberationMono-Bold.ttf", 650 "/usr/share/fonts/TTF/liberation/LiberationMono-Italic.ttf", 651 "/usr/share/fonts/TTF/liberation/LiberationMono-BoldItalic.ttf", 652 "/usr/share/fonts/gdouros-symbola/Symbola.ttf"]; 653 } 654 else version(Manjaro) 655 { 656 string[] font_list = ["/usr/share/fonts/TTF/LiberationMono-Regular.ttf", 657 "/usr/share/fonts/TTF/LiberationMono-Bold.ttf", 658 "/usr/share/fonts/TTF/LiberationMono-Italic.ttf", 659 "/usr/share/fonts/TTF/LiberationMono-BoldItalic.ttf", 660 "/usr/share/fonts/TTF/Symbola.ttf"]; 661 } 662 else version(OpenSUSE) 663 { 664 string[] font_list = ["/usr/share/fonts/truetype/LiberationMono-Regular.ttf", 665 "/usr/share/fonts/truetype/LiberationMono-Bold.ttf", 666 "/usr/share/fonts/truetype/LiberationMono-Italic.ttf", 667 "/usr/share/fonts/truetype/LiberationMono-BoldItalic.ttf", 668 "/usr/share/fonts/truetype/Symbola.ttf"]; 669 } 670 else version(Fedora) 671 { 672 string[] font_list = ["/usr/share/fonts/liberation/LiberationMono-Regular.ttf", 673 "/usr/share/fonts/liberation/LiberationMono-Bold.ttf", 674 "/usr/share/fonts/liberation/LiberationMono-Italic.ttf", 675 "/usr/share/fonts/liberation/LiberationMono-BoldItalic.ttf", 676 "/usr/share/fonts/dejavu/DejaVuSans.ttf"]; 677 } 678 else version (Ubuntu_14_04) 679 { 680 string[] font_list = ["/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf", 681 "/usr/share/fonts/truetype/liberation/LiberationMono-Bold.ttf", 682 "/usr/share/fonts/truetype/liberation/LiberationMono-Italic.ttf", 683 "/usr/share/fonts/truetype/liberation/LiberationMono-BoldItalic.ttf", 684 "/usr/share/fonts/truetype/ttf-ancient-scripts/Symbola605.ttf"]; 685 } 686 else 687 { 688 string[] font_list = ["/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf", 689 "/usr/share/fonts/truetype/liberation/LiberationMono-Bold.ttf", 690 "/usr/share/fonts/truetype/liberation/LiberationMono-Italic.ttf", 691 "/usr/share/fonts/truetype/liberation/LiberationMono-BoldItalic.ttf", 692 "/usr/share/fonts/truetype/ancient-scripts/Symbola_hint.ttf"]; 693 } 694 } 695 else version (Windows) 696 { 697 string[] font_list = ["C:\\Windows\\Fonts\\cour.ttf", 698 "C:\\Windows\\Fonts\\cour.ttf", 699 "C:\\Windows\\Fonts\\cour.ttf", 700 "C:\\Windows\\Fonts\\cour.ttf", 701 // Good fonts: MS GOTHIC, Segoe UI Emoji, Segoe UI Symbol 702 "C:\\Windows\\Fonts\\seguisym.ttf"]; 703 } 704 705 // fonts with sizes 6, 8, 11, 16, 23, 32, 45, 64, 91, 128, 181 706 foreach(f, fontname; font_list) 707 { 708 foreach(i; 5..16) 709 { 710 font[f][i]=TTF_OpenFont( 711 fontname.toStringz(), 712 cast(int)round(SQRT2^^i)); 713 if(!font[f][i]) { 714 throw new Exception(format("TTF_OpenFont: %s\n", 715 TTF_GetError().to!string())); 716 } 717 } 718 719 version(FreeType) 720 { 721 err = FT_New_Face( library, toStringz(fontname.dup), 0, &face[f] ); 722 if (err) 723 { 724 throw new Exception(format("FT_Open_Face 1: %s\n", 725 err)); 726 } 727 } 728 } 729 730 SDL_Surface* surface = SDL_CreateRGBSurface(0, 731 1, 732 1, 733 32, 0x00FF0000, 0X0000FF00, 0X000000FF, 0XFF000000); 734 735 for (auto c = 0; c < 16; c++) 736 { 737 SDL_Color back_color; 738 switch (c) 739 { 740 case Attr.Black: 741 back_color = SDL_Color(0x00, 0x00, 0x00, 0xFF); 742 break; 743 case Attr.Red: 744 back_color = SDL_Color(0xFF, 0x00, 0x00, 0xFF); 745 break; 746 case Attr.Green: 747 back_color = SDL_Color(0x00, 0xFF, 0x00, 0xFF); 748 break; 749 case Attr.Brown: 750 back_color = SDL_Color(0x80, 0x80, 0x00, 0xFF); 751 break; 752 case Attr.Blue: 753 back_color = SDL_Color(0x00, 0x00, 0xFF, 0xFF); 754 break; 755 case Attr.Magenta: 756 back_color = SDL_Color(0xFF, 0x00, 0xFF, 0xFF); 757 break; 758 case Attr.Cyan: 759 back_color = SDL_Color(0x00, 0x80, 0x80, 0xFF); 760 break; 761 case Attr.White: 762 back_color = SDL_Color(0x80, 0x80, 0x80, 0xFF); 763 break; 764 case 8+Attr.Black: 765 back_color = SDL_Color(0x00, 0x00, 0x00, 0xFF); 766 break; 767 case 8+Attr.Red: 768 back_color = SDL_Color(0xFF, 0x00, 0x00, 0xFF); 769 break; 770 case 8+Attr.Green: 771 back_color = SDL_Color(0x00, 0xFF, 0x00, 0xFF); 772 break; 773 case 8+Attr.Brown: 774 back_color = SDL_Color(0x80, 0x80, 0x00, 0xFF); 775 break; 776 case 8+Attr.Blue: 777 back_color = SDL_Color(0x00, 0x00, 0xFF, 0xFF); 778 break; 779 case 8+Attr.Magenta: 780 back_color = SDL_Color(0xFF, 0x00, 0xFF, 0xFF); 781 break; 782 case 8+Attr.Cyan: 783 back_color = SDL_Color(0x00, 0xFF, 0xFF, 0xFF); 784 break; 785 case 8+Attr.White: 786 back_color = SDL_Color(0xFF, 0xFF, 0xFF, 0xFF); 787 break; 788 default: 789 break; 790 } 791 792 (cast(uint*) surface.pixels)[0] = (back_color.a<<24) | 793 (back_color.r << 16) | (back_color.g << 8) | back_color.b; 794 795 attr_textures[c] = 796 SDL_CreateTextureFromSurface(renderer, surface); 797 } 798 799 SDL_FreeSurface(surface); 800 } 801 802 ~this() 803 { 804 version(FreeType) 805 { 806 foreach(f; 0..5) 807 { 808 FT_Done_Face( face[f] ); 809 } 810 } 811 812 foreach(f; 0..5) 813 { 814 foreach(i; 5..16) 815 { 816 TTF_CloseFont(font[f][i]); 817 } 818 } 819 820 for (auto c = Attr.Black; c <= Attr.White; c++) 821 { 822 SDL_DestroyTexture(attr_textures[c]); 823 } 824 825 TTF_Quit(); 826 } 827 }