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