2 Copyright 2012 Marten Richter
4 This file is part of VOMP.
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.
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.
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/>.
24 #include "staticartwork.h"
25 #include "surfacevector.h"
27 SurfaceVector::SurfaceVector(OsdVector* vosd)
30 commands.reserve(2048);
33 SurfaceVector::~SurfaceVector()
35 osd->removeSurface(this);
37 for (SVGCommand& command : commands)
39 osd->decrementStyleRefCount(command.getRef()); // We remove the Style reference, so that osd can free stuff
41 ImageIndex ii = command.getImageIndex();
42 if (ii) osd->removeImageRef(ii);
44 LoadIndex li = command.getLoadIndex();
45 if (li) osd->removeLoadIndexRef(li);
49 int SurfaceVector::getFontHeight()
51 return (int)osd->getFontHeight();
54 float SurfaceVector::getCharWidth(wchar_t c)
56 return osd->getCharWidth(c);
59 int SurfaceVector::drawText(const char* text, int x, int y, const DrawStyle& c)
61 return drawText(text, x, y, 0, c);
64 int SurfaceVector::drawText(const char* text, int x, int y, int width, const DrawStyle& c)
67 const char* run = text;
68 size_t length = strlen(text);
74 float* charwidtharray = osd->getCharWidthArray();
75 int commands_size = commands.size();
77 commands.resize(commands_size + strlen(text));
82 memset((void*)&state, 0, sizeof(state));
83 num_bytes = mbrtowc(&tempo, run, length, &state);
85 while (num_bytes != ((size_t) -1) && num_bytes != ((size_t) -2) && length > 0)
87 ref = osd->getStyleRef(c); // Need to call this each time to have OSD get the ref count right. Maybe expose incRefCount sometime
88 SVGCommand::PaintGlyph(commands[commands_size + chars], x + shift, y, tempo, ref);
91 float cur_shift = charwidtharray[tempo & 0xFF];
93 if (tempo && 0xFFFFFF00) cur_shift = osd->getCharWidth(tempo);
99 if (shift > width && width > 0)
101 command_mutex.unlock();
105 num_bytes = mbrtowc(&tempo, run, length, &state);
109 wchar_t* temptext = new wchar_t[length + 1];
110 int real_length = MultiByteToWideChar(CP_UTF8, 0, text, -1,
111 temptext, length + 1) - 1;
113 for (int i = 0; i < real_length; i++)
115 ref = osd->getStyleRef(c); // Need to call this each time to have OSD get the ref count right. Maybe expose incRefCount sometime
116 SVGCommand::PaintGlyph(commands[commands_size + chars], x + shift, y, temptext[i], ref);
119 float cur_shift = charwidtharray[temptext[i] & 0xFF];
121 if (temptext[i] && 0xFFFFFF00) cur_shift = osd->getCharWidth(temptext[i]);
129 commands.resize(commands_size + chars);
130 command_mutex.unlock();
134 int SurfaceVector::drawTextRJ(const char* text, int x, int y, const DrawStyle& c)
137 const char* run = text;
138 size_t length = strlen(text);
143 size_t num_bytes = 1;
144 memset((void*)&state, 0, sizeof(state));
145 num_bytes = mbrtowc(tempo, run, length, &state);
147 while (num_bytes != ((size_t) -1) && num_bytes != ((size_t) -2) && length > 0)
149 shift += osd->getCharWidth(*tempo);
152 num_bytes = mbrtowc(tempo, run, length, &state);
156 wchar_t* temptext = new wchar_t[length + 1];
157 int real_length = MultiByteToWideChar(CP_UTF8, 0, text, -1,
158 temptext, length + 1) - 1;
160 for (int i = 0; i < real_length; i++)
162 shift += osd->getCharWidth(temptext[i]);
167 return drawText(text, (int)(x - shift), y, c);
170 int SurfaceVector::drawTextCentre(const char* text, int x, int y, const DrawStyle& c)
173 const char* run = text;
174 size_t length = strlen(text);
179 size_t num_bytes = 1;
180 memset((void*)&state, 0, sizeof(state));
181 num_bytes = mbrtowc(tempo, run, length, &state);
183 while (num_bytes != ((size_t) -1) && num_bytes != ((size_t) -2) && length > 0)
185 shift += osd->getCharWidth(*tempo);
188 num_bytes = mbrtowc(tempo, run, length, &state);
192 wchar_t* temptext = new wchar_t[length + 1];
193 int real_length = MultiByteToWideChar(CP_UTF8, 0, text, -1,
194 temptext, length + 1) - 1;
196 for (int i = 0; i < real_length; i++)
198 shift += osd->getCharWidth(temptext[i]);
204 return drawText(text, (int)(x - shift / 2.), y, c);
207 void SurfaceVector::drawJpeg(const char* fileName, int x, int y, int* width, int* height)
209 StaticArtwork index = sa_MAX; // This is for compatibility only
211 if (strcmp(fileName, "/vdr.jpg") == 0)
214 *height = 100; // this is faked so that the system does use the old coordinate system
215 *width = (int)ceil(190.f * osd->getPixelAspect());
217 else if (strcmp(fileName, "/wallpaperPAL.jpg") == 0)
219 index = sa_wallpaper;
220 *width = 720; // this is faked so that the system does use the old coordinate system
227 info.setStaticArtwork(index);
228 drawTVMedia(info, x, y, *width, *height, TopLeft);
233 void SurfaceVector::drawJpeg(const char *fileName,int x, int y,int *width, int *height)
235 command_mutex.lock();
236 ImageIndex image=osd->getJpegRef(fileName,width,height);
237 commands.push_back(SVGCommand::PaintImage(x,y,*width,*height,image,0));
238 command_mutex.unlock();
242 void SurfaceVector::drawTVMedia(TVMediaInfo& tvmedia, float x, float y, float width, float height, Corner corner)
244 command_mutex.lock();
245 ImageIndex image = 0;
246 LoadIndex load_index = osd->getTVMediaRef(tvmedia, image);
248 if (width != 0 && height != 0)
250 removeCommands(x, y, width, height);
255 //Log::getInstance()->log("SurfaceVector", Log::DEBUG, "TVMedia Add instru image %d %d", load_index,image);
256 commands.push_back(SVGCommand::PaintImage(x, y, width, height, image, 0, corner));
261 commands.push_back(SVGCommand::PaintImageLoading(load_index, x, y, width, height, 0, corner));
262 //Log::getInstance()->log("SurfaceVector", Log::DEBUG, "TVMedia Add instru image loading %d %d", load_index,image);
265 command_mutex.unlock();
268 void SurfaceVector::drawClippingRectangle(float x, float y, float w, float h)
270 command_mutex.lock();
271 commands.push_back(SVGCommand::PaintClipping((float)x, (float)y, (float)w, (float)h));
272 command_mutex.unlock();
275 int SurfaceVector::create(UINT width, UINT height)
281 void SurfaceVector::display()
283 //nothing this is really mvp specific
286 int SurfaceVector::fillblt(int x, int y, int width, int height, const DrawStyle& c)
288 command_mutex.lock();
289 removeCommands(x, y, width, height); // remove commands below the box
290 VectorHandle ref = osd->getStyleRef(c);
291 commands.push_back(SVGCommand::PaintPath(x, y, width, height, PIRectangle, ref));
292 command_mutex.unlock();
296 void SurfaceVector::drawHorzLine(int x1, int x2, int y, const DrawStyle& c)
298 command_mutex.lock();
299 VectorHandle ref = osd->getStyleRef(c);
300 commands.push_back(SVGCommand::PaintPath(x1, y, x2 - x1, 1, PIHorzLine, ref));
301 command_mutex.unlock();
304 void SurfaceVector::drawVertLine(int x, int y1, int y2, const DrawStyle& c)
306 command_mutex.lock();
307 VectorHandle ref = osd->getStyleRef(c);
308 commands.push_back(SVGCommand::PaintPath(x, y1, 1, y2 - y1, PIVertLine, ref));
309 command_mutex.unlock();
312 void SurfaceVector::drawBitmap(int x, int y, const Bitmap& bm, const DisplayRegion& region)
314 //this is complicated
315 command_mutex.lock();
317 unsigned int * data=(unsigned int*)malloc(sizeof(unsigned int)*bm.getWidth()*bm.getHeight());
318 for (UINT j = 0; j < bm.getHeight(); ++j){
319 for (UINT i = 0; i < bm.getWidth(); ++i)
321 data[i+j*bm.getHeight()]=bm.getColour(i,j);
324 ImageIndex image = osd->getImagePalette(bm.getWidth(), bm.getHeight(), &(bm.rawData()[0]),
325 (const unsigned int*)&bm.palette.getColourVector()[0]); // data is freed by the OSD
327 float tx = x + region.windowx;
328 float ty = y + region.windowy;
329 float th = bm.getHeight();
330 float tw = bm.getWidth();
332 float scalex = 720.f / ((float) (region.framewidth + 1));
333 float scaley = 576.f / ((float) (region.frameheight + 1));
338 SVGCommand temp = SVGCommand::PaintImage(tx, ty, tw, th, image, 0);
339 removeCommands(tx, ty, tw, th);
340 commands.push_back(temp);
341 command_mutex.unlock();
344 void SurfaceVector::drawPoint(int x, int y, DrawStyle& c, bool fastdraw)
346 if (!fastdraw) command_mutex.lock();
348 VectorHandle ref = osd->getStyleRef(c);
349 commands.push_back(SVGCommand::PaintPath(x, y, 1, 1, PIPoint, ref));
351 if (!fastdraw) command_mutex.unlock();
353 void SurfaceVector::drawMonoBitmap(UCHAR* base, int dx, int dy, unsigned int height, unsigned int width, DrawStyle& nextColour)
355 command_mutex.lock();
356 ImageIndex image = osd->getMonoBitmapRef(base, width, height);
357 VectorHandle ref = osd->getStyleRef(nextColour);
358 removeCommands(dx, dy, width, height);
359 commands.push_back(SVGCommand::PaintImage(dx, dy, height, width, image, ref));
360 command_mutex.unlock();
364 int SurfaceVector::removeCommands(float x, float y, float width, float height)
366 // we iterate through all old commands in order to remove commands hidden by this rectangle
367 std::vector<SVGCommand>::iterator itty = commands.begin();
368 std::vector<SVGCommand>::iterator remstart;
370 float cx, cy, cw, ch;
374 bool clipping_erases = false;
376 while (itty != commands.end())
378 if ((clipping_erases // test if clipping helps
379 || (*itty).Test(x, y, width, height) )
380 && (*itty).instr != DrawClipping)
382 //Log::getInstance()->log("OSD", Log::DEBUG, "Remove command %d %g %g %g %g %d %d",(*itty).instr,
383 //(*itty).x,(*itty).y,(*itty).w,(*itty).h,(*itty).reference,(*itty).target.image);
384 osd->decrementStyleRefCount((*itty).getRef()); // We remove the Style reference, so that osd can free stuff
385 ImageIndex ii = (*itty).getImageIndex();
387 if (ii) osd->removeImageRef(ii);
389 LoadIndex li = (*itty).getLoadIndex();
391 if (li) osd->removeLoadIndexRef(li);
401 if ((*itty).instr == DrawClipping)
403 if ((*itty).w == 0.f && (*itty).h == 0.f)
418 clipping_erases = (cx >= x) && (cy >= y) && ((cx + cw) <= (x + width)) && ((cy + ch) <= (y + height));
423 itty = commands.erase(remstart, itty);
433 itty = commands.erase(remstart, itty);
440 int SurfaceVector::updateToScreen(int sx, int sy, int w, int h, int dx, int dy)
442 // ok this method really works in a pixel oriented way
443 command_mutex.lock();
444 osd->updateOrAddSurface(this, dx - sx, dy - sy, swidth, sheight, commands);
445 command_mutex.unlock();
450 /* This is for systems which need a locking of the drawing surface to speed up drawing */
451 void SurfaceVector::startFastDraw()
453 command_mutex.lock();
455 void SurfaceVector::endFastDraw()
457 command_mutex.unlock();
461 void SurfaceVector::drawTTChar(int ox, int oy, int x, int y, cTeletextChar c)
463 command_mutex.lock();
464 std::vector<SVGCommand>::iterator itty = commands.begin();
466 while (itty != commands.end())
468 if ((*itty).TTTest(ox, oy, x, y) )
470 itty = commands.erase(itty);
479 commands.push_back(SVGCommand::PaintTTchar(ox, oy, x, y, c.getInternal()));
480 command_mutex.unlock();