Subversion Repositories Kolibri OS

Rev

Rev 5981 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #ifndef INCLUDE_FONT_H
  2. #define INCLUDE_FONT_H
  3.  
  4. #ifndef INCLUDE_MATH_H
  5. #include "../lib/math.h"
  6. #endif
  7.  
  8. #ifndef INCLUDE_FS_H
  9. #include "../lib/obj/fs.h"
  10. #endif
  11.  
  12. #define DEFAULT_FONT "/sys/fonts/Tahoma.kf"
  13.  
  14. :struct __OFFSET_FONT
  15. {
  16.         signed x,y;
  17. };
  18. :struct __SIZE
  19. {
  20.         dword width,height;
  21.         __OFFSET_FONT offset;
  22.         float offset_i,w_italic;
  23.         byte text;
  24.         byte TMP_WEIGHT;
  25. };
  26. :struct FONT
  27. {
  28.         __SIZE size;
  29.         int left,top,width,height;
  30.         byte bold,italic,smooth;
  31.         dword bg_color;
  32.         dword color;
  33.         dword file_size;
  34.         dword buffer;
  35.         dword buffer_size;
  36.         word block;
  37.         dword data;
  38.         dword begin;
  39.         byte load(...);
  40.         byte changeSIZE();
  41.         byte symbol(signed x,y;byte s;dword c);
  42.         byte symbol_size(byte s);
  43.         dword getsize(dword text1);
  44.         void apply_smooth();
  45.         int write_center(dword x,y,w,h;dword txt);
  46.         int write(int x,y;dword text1);
  47.         void write_buf(int x,y,w,h, text1);
  48.         void show_buf();
  49. };
  50. FONT font = 0;
  51.  
  52. :byte FONT::changeSIZE()
  53. {
  54.         dword TMP_DATA;
  55.         dword ofs;
  56.         IF(size.text<9) size.text = 8;
  57.         TMP_DATA = data = begin;
  58.         TMP_DATA +=size.text-8*4;
  59.         ofs = DSDWORD[TMP_DATA];
  60.         IF(ofs==-1)return false;
  61.         data += ofs + 156;
  62.         TMP_DATA = data;
  63.         file_size = DSDWORD[TMP_DATA];
  64.         TMP_DATA = data + file_size;
  65.         height = DSBYTE[TMP_DATA - 1];
  66.         width =  DSBYTE[TMP_DATA - 2];
  67.         block = math.ceil(height*width/32);
  68.         return true;
  69. }
  70. :dword FONT::getsize(dword text1)
  71. {
  72.         size.height = size.width = 0;
  73.         size.offset.x = size.offset.y = -1;
  74.         IF(size.text)IF(!changeSIZE())return 0;
  75.         WHILE(DSBYTE[text1])
  76.         {
  77.                 symbol_size(DSBYTE[text1]);
  78.                 text1++;
  79.         }
  80.         $neg size.offset.y
  81.         $neg size.offset.x
  82.         size.height += size.offset.y; size.height++;
  83.         size.width += size.offset.x; size.width++;
  84.         IF(italic)
  85.         {
  86.                 size.w_italic = size.height/3;
  87.                 size.offset_i = size.w_italic/size.height;
  88.                 size.width += size.w_italic;
  89.                 size.w_italic = -size.w_italic;
  90.         }
  91.         return size.width;
  92. }
  93. :byte FONT::symbol_size(byte s)
  94. {
  95.                 dword xi,yi;
  96.                 dword tmp,_;
  97.                 dword iii = 0;
  98.                 byte rw=0;
  99.                 byte X;
  100.                 size.TMP_WEIGHT = math.ceil(size.text/17);
  101.                 IF(s==32)
  102.                 {
  103.                         size.width += width/4;
  104.                         IF(bold) size.width+=size.TMP_WEIGHT;
  105.                         return;
  106.                 }
  107.                 IF(s==9)
  108.                 {
  109.                         size.width += width;
  110.                         IF(bold) size.width+=size.TMP_WEIGHT;
  111.                         return;
  112.                 }
  113.                 s = AnsiToCp866(s);
  114.                 tmp = 4*block*s + data;
  115.                 for(yi=0; yi<height; yi++)
  116.                 {
  117.                         for(xi=0; xi<width; xi++)
  118.                         {
  119.                                 IF(iii%32) _ >>= 1;
  120.                                 ELSE
  121.                                 {
  122.                                         tmp += 4;
  123.                                         _ = DSDWORD[tmp];
  124.                                 }
  125.                                 IF(_&1)
  126.                                 {
  127.                                         IF(xi>rw)rw=xi;
  128.                                         IF(size.height<yi)size.height = yi;
  129.                                         IF(size.offset.y<0)size.offset.y = yi;
  130.                                         ELSE IF(yi<size.offset.y)size.offset.y = yi;
  131.                                         IF(!X) X = xi;
  132.                                         ELSE IF(X>xi)X = xi;
  133.                                 }
  134.                                 iii++;
  135.                         }
  136.                 }
  137.                 size.width += rw;
  138.                 IF(bold) size.width+=size.TMP_WEIGHT;
  139.                 IF(s=='_') size.width--;
  140.                 IF(size.offset.x<0)size.offset.x = X;
  141. }
  142. :byte FONT::symbol(signed x,y;byte s)
  143. {
  144.                 dword xi,yi;
  145.                 dword iii = 0;
  146.                 dword offs;
  147.                 float ital = -size.w_italic;
  148.                 dword ___x;
  149.                 byte rw=0;
  150.                 IF(s==32)return width/4;
  151.                 IF(s==9)return width;
  152.                 s = AnsiToCp866(s);
  153.                 EBX = block*s << 2 + data;
  154.                 for(yi=0; yi<height; yi++)
  155.                 {
  156.                         EDI = size.offset.y + yi + y * size.width * 3 + buffer;
  157.                         for(xi=0; xi<width; xi++)
  158.                         {
  159.                                 IF(iii%32) $shr ecx,1
  160.                                 ELSE
  161.                                 {
  162.                                                 EBX += 4;
  163.                                                 ECX = DSDWORD[EBX];
  164.                                 }
  165.                                 IF(ECX&true)
  166.                                 {
  167.                                                 IF(xi>rw)rw=xi;
  168.                                                 ___x = x+xi;
  169.                                                 IF(italic)___x+=math.ceil(ital);
  170.                                                 offs = ___x*3 + EDI;
  171.                                                 DSDWORD[offs] = DSDWORD[offs] & 0xFF000000 | color;
  172.                                                 IF(bold) DSDWORD[offs+3] = DSDWORD[offs+3] & 0xFF000000 | color;
  173.                                 }
  174.                                 iii++;
  175.                         }
  176.                         if (italic) ital-=size.offset_i;
  177.                 }
  178.                 return rw;
  179. }
  180.  
  181. byte AnsiToCp866(byte s) {
  182.         IF(s>=128)&&(s<=175)s+=64;
  183.         ELSE IF(s>=224)&&(s<=239)s+=16;
  184.         ELSE IF(s==241)s=184; //yo
  185.         ELSE IF(s==240)s=168; //YO
  186.         return s;
  187. }
  188.  
  189. inline fastcall dword b24(EBX) { return DSDWORD[EBX] << 8; }
  190. :void FONT::apply_smooth()
  191. {
  192.         dword i,line_w,to;
  193.         line_w = font.size.width * 3;
  194.         to = font.size.height - 1 * line_w + font.buffer - 3;
  195.         for(i=font.buffer; i < to; i+=3)       
  196.         {
  197.                 IF(i-font.buffer%line_w +3 == line_w) continue;
  198.                 IF(b24(i)==0x000000) && (b24(i+3)!=0x000000) && (b24(i+line_w)!=0x000000) && (b24(i+3+line_w)==0x000000)
  199.                 {
  200.                         ShadowPixel(i+3, 2);
  201.                         ShadowPixel(i+line_w, 2);
  202.                 }
  203.                 ELSE IF(b24(i)!=0x000000) && (b24(i+3)==0x000000) && (b24(i+line_w)==0x000000) && (b24(i+3+line_w)!=0x000000)
  204.                 {
  205.                         ShadowPixel(i, 2);
  206.                         ShadowPixel(i+3+line_w, 2);
  207.                 }
  208.         }
  209. }
  210. :byte FONT::load(dword path)
  211. {
  212.         lib_init_fs();
  213.         buffer_size = 0;
  214.         smooth = true;
  215.         IF(data)free(data);
  216.         IF(!fs.read(path)) { debug("Error while loading font: "); debugln(path); return false; }
  217.         begin = data = EAX;
  218.         EBX = begin + ECX;
  219.         height = DSBYTE[EBX-1];
  220.         width = DSBYTE[EBX-2];
  221.         block = math.ceil(height*width/32);
  222.         return true;
  223. }
  224.  
  225. :int FONT::write_center(dword x,y,w,h;dword txt)
  226. {
  227.         getsize(txt);
  228.         return write(w-size.width/2+x,y,txt);
  229. }
  230.  
  231. :int FONT::write(int x,y; dword text1)
  232. {
  233.         signed len=0;
  234.         IF(!text1)return false;
  235.         IF(size.text)IF(!changeSIZE())return false;
  236.         left = x;
  237.         getsize(text1);
  238.         y -= size.offset.y;
  239.         top = y;
  240.         EDX = size.width*size.height*3;
  241.         IF(!buffer_size)
  242.         {
  243.                 buffer_size = EDX;
  244.                 buffer = malloc(buffer_size);
  245.         }
  246.         ELSE IF(buffer_size<EDX)
  247.         {
  248.                 buffer_size = EDX;
  249.                 buffer = realloc(buffer,buffer_size);
  250.         }
  251.         // Fill background color {
  252.         EBX = bg_color;
  253.         EAX = buffer_size+buffer;
  254.         for (EDI=buffer; EDI<EAX; EDI+=3) ESDWORD[EDI] = EBX;
  255.         // }
  256.         len = size.offset.x;
  257.         WHILE(DSBYTE[text1])
  258.         {
  259.                 IF(DSBYTE[text1]=='_') len--;
  260.                 len+=symbol(len,0,DSBYTE[text1]);
  261.                 IF(bold)len+=math.ceil(size.text/17);
  262.                 text1++;
  263.         }
  264.         IF (smooth) apply_smooth();
  265.         show_buf(left,top);
  266.         return len;
  267. }
  268.  
  269. :void FONT::write_buf(int x,y,w,h; dword text1)
  270. {
  271.         dword new_buffer_size;
  272.         IF(!text1)return;
  273.         IF(size.text)IF(!changeSIZE())return;
  274.         getsize(text1);
  275.         y -= size.offset.y;
  276.  
  277.         size.width = w;
  278.         size.height = h;
  279.  
  280.         new_buffer_size = w*h*3;
  281.         IF(buffer_size != w*h*3)
  282.         {
  283.                 buffer_size = new_buffer_size;
  284.                 free(buffer);
  285.                 buffer = malloc(buffer_size);
  286.                 // Fill background color
  287.                 EBX = bg_color;
  288.                 EAX = buffer_size+buffer;
  289.                 for (EDI=buffer; EDI<EAX; EDI+=3) ESDWORD[EDI] = EBX;
  290.         }
  291.         WHILE(DSBYTE[text1])
  292.         {
  293.                 x+=symbol(x,y,DSBYTE[text1]);
  294.                 IF(bold)x+=math.ceil(size.text/17);
  295.                 text1++;
  296.         }
  297.         return;
  298. }
  299.  
  300. :void FONT::show_buf(dword left1, top1){
  301.         _PutImage(left1,top1,size.width,size.height,buffer);
  302. }
  303.  
  304.  
  305.  
  306.  
  307. #endif