Subversion Repositories Kolibri OS

Rev

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