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