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