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