]> git.vomp.tv Git - vompclient.git/blob - surface.cc
Interface changes, introducing DrawStyle, preparation for Vector based OSD
[vompclient.git] / surface.cc
1 /*\r
2     Copyright 2004-2005 Chris Tallon\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
19 */\r
20 \r
21 #include "surface.h"\r
22 \r
23 #include <math.h>\r
24 #include "osd.h"\r
25 #include "log.h"\r
26 #include "video.h"\r
27 \r
28 #include "teletxt/txtfont.h"\r
29 \r
30 unsigned int interpol_table_fac1[16][22];\r
31 unsigned int interpol_table_fac2[16][22];\r
32 unsigned int interpol_table_fac3[16][22];\r
33 unsigned int interpol_table_fac4[16][22];\r
34 int interpol_lowbit[16];\r
35 int interpol_upbit[16];\r
36 int interpol_lowline[22];\r
37 int interpol_upline[22];\r
38 bool pol_table_inited=false;\r
39 \r
40 void initpol_tables(){\r
41     int charsizex;\r
42     int charsizey;\r
43     charsizex=16;\r
44     if (Video::getInstance()->getFormat() == Video::PAL)\r
45     {\r
46         charsizey=22;\r
47     } else {\r
48         charsizey=18;\r
49     }\r
50     int ttcharsizex=12;\r
51     int ttcharsizey=10;\r
52     for (int py=0;py<charsizey;py++) {\r
53         float fposy=((float)(ttcharsizey))/((float)(charsizey))*((float)py);\r
54         float yweight=fposy-floor(fposy);\r
55         float yinvweight=1.-yweight;\r
56         interpol_upline[py]=min((unsigned int)ceil(fposy),9);\r
57         interpol_lowline[py]=max((unsigned int)floor(fposy),0);\r
58         for (int px=0;px<charsizex;px++) {\r
59             float fposx=((float)(ttcharsizex))/((float)(charsizex))*((float)px);\r
60             float xweight=fposx-floor(fposx);\r
61             float xinvweight=1.-xweight;\r
62             interpol_upbit[px]= (min((unsigned int)ceil(fposx),11));\r
63             interpol_lowbit[px]= (max((unsigned int)floor(fposx),0));\r
64 \r
65             interpol_table_fac1[px][py]=xweight*yweight*256.;\r
66             interpol_table_fac2[px][py]=xinvweight*yweight*256.;\r
67             interpol_table_fac3[px][py]=xweight*yinvweight*256.;\r
68             interpol_table_fac4[px][py]=xinvweight*yinvweight*256.;\r
69 \r
70         }\r
71     }\r
72 }\r
73 \r
74 \r
75 Surface* Surface::screen = NULL;\r
76 osd_font_t* Surface::font = &font_helvB18;\r
77 \r
78 Surface::Surface(int id)\r
79 {\r
80   if (id == SCREEN) screen = this;\r
81 }\r
82 \r
83 Surface::~Surface()\r
84 {\r
85 }\r
86 \r
87 Surface* Surface::getScreen()\r
88 {\r
89   return screen;\r
90 }\r
91 \r
92 int Surface::drawText(const char* text, int x, int y, const DrawStyle& c)\r
93 {\r
94   return drawText(text, x, y, 2000, c);\r
95 }\r
96 \r
97 int Surface::drawText(const char* text, int x, int y, int width, const DrawStyle& c)\r
98 {\r
99   int h, n, i;\r
100   int Y, X, cx;\r
101 \r
102   n = strlen(text);\r
103   h = font->height;\r
104 \r
105   X = 0;\r
106   cx = 0;\r
107   ULONG rgba=c.rgba();\r
108   startFastDraw();\r
109   for (i=0; i<n; i++)\r
110   {\r
111     unsigned char c = text[i];\r
112     unsigned long *character = &font->content[font->offset[c]];\r
113     int w = font->width[c];\r
114     int pixels = 0;\r
115 \r
116     for (X=0; (X<w) && (X + cx < width); X++)\r
117     {\r
118       for (Y=0; Y<h; Y++)\r
119       {\r
120         if ((character[Y] >> (32 - X)) & 0x1)\r
121         {\r
122           drawPixel(x+X+cx, y+Y, rgba,true);\r
123           pixels++;\r
124         }\r
125       }\r
126     }\r
127     cx += w;\r
128   }\r
129   endFastDraw();\r
130   return 1;\r
131 }\r
132 \r
133 int Surface::drawTextRJ(const char* text, int x, int y, const DrawStyle& c)\r
134 {\r
135   int i, n, w;\r
136   w = 0;\r
137 \r
138   n = strlen(text);\r
139 \r
140   for (i = 0; i < n; i++)\r
141   {\r
142     w += font->width[(unsigned char)text[i]];\r
143   }\r
144 \r
145   x -= w;\r
146 \r
147   if (x < 0) return 0;\r
148   else return drawText(text, x, y, c);\r
149 }\r
150 \r
151 int Surface::drawTextCentre(const char* text, int x, int y, const DrawStyle& c)\r
152 {\r
153   int i, n, w;\r
154   w = 0;\r
155 \r
156   n = strlen(text);\r
157 \r
158   for (i = 0; i < n; i++)\r
159   {\r
160     w += font->width[(unsigned char)text[i]]; //Characters bigger then 128 can appear\r
161   }\r
162 \r
163   x -= w / 2;\r
164 \r
165   if (x < 0) return 0;\r
166   else return drawText(text, x, y, c);\r
167 }\r
168 \r
169 int Surface::getCharWidth(char c)\r
170 {\r
171   return font->width[(unsigned char) c];\r
172 }\r
173 \r
174 int Surface::getFontHeight()\r
175 {\r
176   return font->spacing;\r
177 }\r
178 \r
179 //Moved from Teletext view in order to allow device depend optimizations\r
180 \r
181 Colour Surface::enumTeletextColorToCoulour(enumTeletextColor ttcol)\r
182 {\r
183     switch (ttcol) {\r
184         case ttcBlack:\r
185             return Colour(0,0,0);\r
186         case ttcRed:\r
187             return Colour(255,0,0);\r
188         case ttcGreen:\r
189             return Colour(0,255,0);\r
190         case ttcYellow:\r
191             return Colour(255,255,0);\r
192         case ttcBlue:\r
193             return Colour(0,0,255);\r
194         case ttcMagenta:\r
195             return Colour(255,0,255);\r
196         case ttcCyan:\r
197             return Colour(0,255,255);\r
198         case ttcWhite:\r
199             return Colour(255,255,255);\r
200         case ttcTransparent:\r
201             return Colour(0,0,0,0);\r
202         case ttcHalfRed:\r
203             return Colour(127,0,0);\r
204         case ttcHalfGreen:\r
205             return Colour(0,127,0);\r
206         case ttcHalfYellow:\r
207             return Colour(127,127,0);\r
208         case ttcHalfBlue:\r
209             return Colour(0,0,127);\r
210         case ttcHalfMagenta:\r
211             return Colour(127,0,127);\r
212         case ttcHalfCyan:\r
213             return Colour(0,127,127);\r
214         case ttcGrey:\r
215             return Colour(127,127,127);\r
216         default:\r
217             return Colour(0,0,0);\r
218     };\r
219 }\r
220 \r
221 \r
222 \r
223 //Next function inspired by osdteletext plugin\r
224 void Surface::drawTTChar(int ox, int oy, int x, int y, cTeletextChar c)\r
225 {\r
226         if (!pol_table_inited){\r
227                 initpol_tables();\r
228                 pol_table_inited=true;\r
229         }\r
230     unsigned int buffer [10];\r
231     unsigned int * charmap=GetFontChar(c,buffer);\r
232     if (!charmap) { //invalid char\r
233         memset(&buffer,0,10);\r
234         charmap=buffer;\r
235     }\r
236     enumTeletextColor ttforegcolour=c.GetFGColor();\r
237     enumTeletextColor ttbackgcolour=c.GetBGColor();\r
238     if (c.GetBoxedOut()) {\r
239         ttforegcolour=ttcTransparent;\r
240         ttbackgcolour=ttcTransparent;\r
241     }\r
242     int charsizex;\r
243     int charsizey;\r
244     charsizex=16;\r
245 \r
246     if (Video::getInstance()->getFormat() == Video::PAL)\r
247     {\r
248         charsizey=22;\r
249     } else {\r
250         charsizey=18;\r
251     }\r
252     int ttcharsizex=12;\r
253     int ttcharsizey=10;\r
254     int screenposx=charsizex*x+ox; //12*40= 480 250\r
255     int screenposy=y*charsizey+oy;\r
256 \r
257 \r
258    // Log::getInstance()->log("Surface", Log::ERR, "TTpos %d %d %d %d %d %d",x,y,ox,oy,screenposx,screenposy);\r
259     Colour fgcharcl=enumTeletextColorToCoulour(ttforegcolour);\r
260     Colour bgcharcl=enumTeletextColorToCoulour(ttbackgcolour);\r
261 \r
262     startFastDraw();\r
263     for (int py=0;py<charsizey;py++) {\r
264         int upperbitline=charmap[interpol_upline[py]];\r
265         int lowerbitline=charmap[interpol_lowline[py]];\r
266         for (int px=0;px<charsizex;px++) {\r
267             int upperbit= interpol_upbit[px];\r
268             int lowerbit= interpol_lowbit[px];\r
269             Colour uuc=( upperbitline &(0x8000>>upperbit)) ? fgcharcl: bgcharcl;\r
270             Colour ulc=( upperbitline &(0x8000>>lowerbit)) ? fgcharcl: bgcharcl;\r
271             Colour luc=( lowerbitline &(0x8000>>upperbit)) ? fgcharcl: bgcharcl;\r
272             Colour llc=( lowerbitline &(0x8000>>lowerbit)) ? fgcharcl: bgcharcl;\r
273             unsigned int fac1,fac2,fac3,fac4;\r
274             fac1=interpol_table_fac1[px][py];\r
275             fac2=interpol_table_fac2[px][py];\r
276             fac3=interpol_table_fac3[px][py];\r
277             fac4=interpol_table_fac4[px][py];\r
278 \r
279             Colour res((uuc.red*fac1+ulc.red*fac2+luc.red*fac3+llc.red*fac4)/256,\r
280                 (uuc.green*fac1+ulc.green*fac2+luc.green*fac3+llc.green*fac4)/256,\r
281                 (uuc.blue*fac1+ulc.blue*fac2+luc.blue*fac3+llc.blue*fac4)/256,\r
282                 (uuc.alpha*fac1+ulc.alpha*fac2+luc.alpha*fac3+llc.alpha*fac4)/256); //if this is too slow make a table\r
283             int c = (  (res.alpha << 24 )\r
284                         | (res.red    << 16)\r
285                         | (res.green  <<  8)\r
286                         | (res.blue        ) );\r
287             drawPixel(screenposx+px,screenposy+py,c, true);\r
288         }\r
289     }\r
290 \r
291 \r
292     endFastDraw();\r
293 \r
294 \r
295 }\r
296 \r
297 void Surface::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height,\r
298                 unsigned int width, Colour& nextColour) {\r
299         startFastDraw();\r
300         int x, y;\r
301         unsigned int bytesIn, bitsIn;\r
302         int widthBytes=width/8;\r
303         for (y = 0; y < height; y++) {\r
304                 for (x = 0; x < width; x++) {\r
305                         bytesIn = (y * widthBytes) + (int) (x / 8);\r
306                         bitsIn = x % 8;\r
307 \r
308                         if ((base[bytesIn] >> (7 - bitsIn)) & 0x01) {\r
309                                 drawPixel(dx+x, dy+y, nextColour, true);\r
310                         }\r
311                 }\r
312         }\r
313         endFastDraw();\r
314 }\r
315 \r
316 void Surface::drawPoint(int x, int y, Colour& c, bool fastdraw)\r
317 {\r
318         drawPixel(x,y,c,fastdraw);\r
319 }\r