]> git.vomp.tv Git - vompclient-marten.git/blob - surface.cc
Switch to OpenVG based OSD, note Teletext and Subtitle rendering not working and...
[vompclient-marten.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 float Surface::getCharWidth(wchar_t c)\r
170 {\r
171   return (float)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  wchar_t Surface::getWChar(const char* str, unsigned int *length)\r
180  {\r
181          *length=1;\r
182          return *str;\r
183  }\r
184 \r
185 //Moved from Teletext view in order to allow device depend optimizations\r
186 \r
187 Colour Surface::enumTeletextColorToCoulour(enumTeletextColor ttcol)\r
188 {\r
189     switch (ttcol) {\r
190         case ttcBlack:\r
191             return Colour(0,0,0);\r
192         case ttcRed:\r
193             return Colour(255,0,0);\r
194         case ttcGreen:\r
195             return Colour(0,255,0);\r
196         case ttcYellow:\r
197             return Colour(255,255,0);\r
198         case ttcBlue:\r
199             return Colour(0,0,255);\r
200         case ttcMagenta:\r
201             return Colour(255,0,255);\r
202         case ttcCyan:\r
203             return Colour(0,255,255);\r
204         case ttcWhite:\r
205             return Colour(255,255,255);\r
206         case ttcTransparent:\r
207             return Colour(0,0,0,0);\r
208         case ttcHalfRed:\r
209             return Colour(127,0,0);\r
210         case ttcHalfGreen:\r
211             return Colour(0,127,0);\r
212         case ttcHalfYellow:\r
213             return Colour(127,127,0);\r
214         case ttcHalfBlue:\r
215             return Colour(0,0,127);\r
216         case ttcHalfMagenta:\r
217             return Colour(127,0,127);\r
218         case ttcHalfCyan:\r
219             return Colour(0,127,127);\r
220         case ttcGrey:\r
221             return Colour(127,127,127);\r
222         default:\r
223             return Colour(0,0,0);\r
224     };\r
225 }\r
226 \r
227 \r
228 \r
229 //Next function inspired by osdteletext plugin\r
230 void Surface::drawTTChar(int ox, int oy, int x, int y, cTeletextChar c)\r
231 {\r
232         if (!pol_table_inited){\r
233                 initpol_tables();\r
234                 pol_table_inited=true;\r
235         }\r
236     unsigned int buffer [10];\r
237     unsigned int * charmap=GetFontChar(c,buffer);\r
238     if (!charmap) { //invalid char\r
239         memset(&buffer,0,10);\r
240         charmap=buffer;\r
241     }\r
242     enumTeletextColor ttforegcolour=c.GetFGColor();\r
243     enumTeletextColor ttbackgcolour=c.GetBGColor();\r
244     if (c.GetBoxedOut()) {\r
245         ttforegcolour=ttcTransparent;\r
246         ttbackgcolour=ttcTransparent;\r
247     }\r
248     int charsizex;\r
249     int charsizey;\r
250     charsizex=16;\r
251 \r
252     if (Video::getInstance()->getFormat() == Video::PAL)\r
253     {\r
254         charsizey=22;\r
255     } else {\r
256         charsizey=18;\r
257     }\r
258     int ttcharsizex=12;\r
259     int ttcharsizey=10;\r
260     int screenposx=charsizex*x+ox; //12*40= 480 250\r
261     int screenposy=y*charsizey+oy;\r
262 \r
263 \r
264    // Log::getInstance()->log("Surface", Log::ERR, "TTpos %d %d %d %d %d %d",x,y,ox,oy,screenposx,screenposy);\r
265     Colour fgcharcl=enumTeletextColorToCoulour(ttforegcolour);\r
266     Colour bgcharcl=enumTeletextColorToCoulour(ttbackgcolour);\r
267 \r
268     startFastDraw();\r
269     for (int py=0;py<charsizey;py++) {\r
270         int upperbitline=charmap[interpol_upline[py]];\r
271         int lowerbitline=charmap[interpol_lowline[py]];\r
272         for (int px=0;px<charsizex;px++) {\r
273             int upperbit= interpol_upbit[px];\r
274             int lowerbit= interpol_lowbit[px];\r
275             Colour uuc=( upperbitline &(0x8000>>upperbit)) ? fgcharcl: bgcharcl;\r
276             Colour ulc=( upperbitline &(0x8000>>lowerbit)) ? fgcharcl: bgcharcl;\r
277             Colour luc=( lowerbitline &(0x8000>>upperbit)) ? fgcharcl: bgcharcl;\r
278             Colour llc=( lowerbitline &(0x8000>>lowerbit)) ? fgcharcl: bgcharcl;\r
279             unsigned int fac1,fac2,fac3,fac4;\r
280             fac1=interpol_table_fac1[px][py];\r
281             fac2=interpol_table_fac2[px][py];\r
282             fac3=interpol_table_fac3[px][py];\r
283             fac4=interpol_table_fac4[px][py];\r
284 \r
285             Colour res((uuc.red*fac1+ulc.red*fac2+luc.red*fac3+llc.red*fac4)/256,\r
286                 (uuc.green*fac1+ulc.green*fac2+luc.green*fac3+llc.green*fac4)/256,\r
287                 (uuc.blue*fac1+ulc.blue*fac2+luc.blue*fac3+llc.blue*fac4)/256,\r
288                 (uuc.alpha*fac1+ulc.alpha*fac2+luc.alpha*fac3+llc.alpha*fac4)/256); //if this is too slow make a table\r
289             int c = (  (res.alpha << 24 )\r
290                         | (res.red    << 16)\r
291                         | (res.green  <<  8)\r
292                         | (res.blue        ) );\r
293             drawPixel(screenposx+px,screenposy+py,c, true);\r
294         }\r
295     }\r
296 \r
297 \r
298     endFastDraw();\r
299 \r
300 \r
301 }\r
302 \r
303 void Surface::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height,\r
304                 unsigned int width, Colour& nextColour) {\r
305         startFastDraw();\r
306         int x, y;\r
307         unsigned int bytesIn, bitsIn;\r
308         int widthBytes=width/8;\r
309         for (y = 0; y < height; y++) {\r
310                 for (x = 0; x < width; x++) {\r
311                         bytesIn = (y * widthBytes) + (int) (x / 8);\r
312                         bitsIn = x % 8;\r
313 \r
314                         if ((base[bytesIn] >> (7 - bitsIn)) & 0x01) {\r
315                                 drawPixel(dx+x, dy+y, nextColour, true);\r
316                         }\r
317                 }\r
318         }\r
319         endFastDraw();\r
320 }\r
321 \r
322 void Surface::drawPoint(int x, int y, DrawStyle& c, bool fastdraw)\r
323 {\r
324         drawPixel(x,y,c,fastdraw);\r
325 }\r