mirror of
https://projects.vdr-developer.org/git/vdr-plugin-skindesigner.git
synced 2023-10-19 17:58:31 +02:00
Version 0.0.5 - added SVG Support
This commit is contained in:
commit
0ed710a868
50
HISTORY
50
HISTORY
@ -7,14 +7,17 @@ VDR Plugin 'skindesigner' Revision History
|
||||
|
||||
Version 0.0.2
|
||||
|
||||
- added some more tokens with more detailed audio information in displaychannel -> statusinfo
|
||||
- added some more tokens with more detailed audio information in
|
||||
displaychannel -> statusinfo
|
||||
- added hasVPS for current scheduling in displaychannel -> epginfo
|
||||
- added common channel logo path for all skins
|
||||
- changed skin handling so that every skin is directly shown in VDR OSD Menu
|
||||
- added Theme support, each skin can now have various themes
|
||||
- fixed a crash if no skindesigner skins are found and plugin setup menu is called from another skin
|
||||
- fixed a crash if no skindesigner skins are found and plugin setup menu is
|
||||
called from another skin
|
||||
- added {durationhours} and {durationminutes} tokens in several view elements
|
||||
- added discusage icons to menu header view element so that it discusage can be displayed in every menu view
|
||||
- added discusage icons to menu header view element so that it discusage can be
|
||||
displayed in every menu view
|
||||
- added numeric day, month and year tokens in different view elements
|
||||
- support for global variables type "double"
|
||||
- added setup options to configure rerun display behaviour
|
||||
@ -23,36 +26,46 @@ Version 0.0.2
|
||||
- added vps token in menudetailepg
|
||||
- implemented cSDDisplayMenu::GetTextAreaFont()
|
||||
- introduced new viewelement audioinfo in displaychannel
|
||||
- added setup option to choose Menu Item display method between "at one go" and "after one another"
|
||||
- fixed bug that new skin was not properly loaded sometimes when skin was changed in OSD Setup menu
|
||||
- fixed bug that new font was displayed first after VDR restart when font was changed in OSD Setup menu
|
||||
- display always newest recording of folders in recordings list, thanks@ Lars Hanisch for providing the patch
|
||||
- added setup option to choose Menu Item display method between "at one go" and
|
||||
"after one another"
|
||||
- fixed bug that new skin was not properly loaded sometimes when skin was
|
||||
changed in OSD Setup menu
|
||||
- fixed bug that new font was displayed first after VDR restart when font was
|
||||
changed in OSD Setup menu
|
||||
- display always newest recording of folders in recordings list,
|
||||
thanks@ Lars Hanisch for providing the patch
|
||||
- added extented recording information
|
||||
- added token {nummenuitem} as number of item for every list, value starts with 1
|
||||
- added token {nummenuitem} as number of item for every list, value starts
|
||||
with 1
|
||||
- fixed bug that x and y of subviews was not respected
|
||||
- if a subview is completely not set in a skin, the default menu is used
|
||||
- fixed a bug if displaydetailedtext is called without correct menucat (mailbox plugin)
|
||||
- fixed a bug if displaydetailedtext is called without correct menucat (mailbox
|
||||
plugin)
|
||||
- implemented function drawslope, see Wiki for documentation
|
||||
- using default menu list in case an invalid MenuCategory is set
|
||||
- added device info in displaychannel, example in metrixHD
|
||||
- improved menu icon display, additionally using menu cat
|
||||
- changed devices list, device numbers start with 0
|
||||
- fixed bug that hasposter is only true if poster really exists
|
||||
- no absolute pathes allowed for image type "image", path has to start with {ressourcedir}
|
||||
- no absolute pathes allowed for image type "image", path has to start with
|
||||
{ressourcedir}
|
||||
|
||||
Version 0.0.3
|
||||
|
||||
- added tokens for current video and audio bitrate in displaychannel. Thx @rofafor for the original code
|
||||
- added tokens for current video and audio bitrate in displaychannel.
|
||||
Thx @rofafor for the original code
|
||||
in the femon plugin and _Martin_ for extracting the code in skinflatplus
|
||||
- changed skin metrixHD to display bitrate infos
|
||||
- added "active" Token for cutting marks so that a mark can be displayed in a dedicated way if current position
|
||||
in replay exactly hits the mark
|
||||
- added {channelname}, {channelid}, {channellogoexists} for all schedules list and current views
|
||||
- added "active" Token for cutting marks so that a mark can be displayed in a
|
||||
dedicated way if current position in replay exactly hits the mark
|
||||
- added {channelname}, {channelid}, {channellogoexists} for all schedules list
|
||||
and current views
|
||||
- added printf function for <drawtext>, see Wiki for documentation
|
||||
- removed code for displaying bitrates in displaychannel again because of incompatibility with dvbapi Plugin
|
||||
- removed code for displaying bitrates in displaychannel again because of
|
||||
incompatibility with dvbapi Plugin
|
||||
- optimized performance when creating a menu list
|
||||
- fixed Bug that displaychannel was not shown after closing displaymenu with "backspace" (with active
|
||||
menuorg plugin)
|
||||
- fixed Bug that displaychannel was not shown after closing displaymenu with
|
||||
"backspace" (with active menuorg plugin)
|
||||
- fixed Bug with menuselection Patch
|
||||
- added tokens {month}, {monthname} and {year} in displaymenutimers listitem and currentitem
|
||||
- added dedicated tokens for posters and banners in <srapercontent> in displaychannel and displayreplay
|
||||
@ -62,3 +75,6 @@ Version 0.0.3
|
||||
|
||||
Version 0.0.4
|
||||
|
||||
- added SVG Support - thanks to Manuel Reimer!
|
||||
|
||||
Version 0.0.5
|
||||
|
14
Makefile
14
Makefile
@ -3,9 +3,6 @@
|
||||
#
|
||||
# $Id$ Makefile 1.0 2014/07/24 louis Exp $
|
||||
|
||||
# External image lib to use: imagemagick, graphicsmagick
|
||||
IMAGELIB = imagemagick
|
||||
|
||||
# Config
|
||||
CONFIG := #-DDOPROFILE # enable profiling code
|
||||
|
||||
@ -50,13 +47,8 @@ DEFINES += $(shell xml2-config --cflags)
|
||||
|
||||
INCLUDES += $(shell pkg-config --cflags freetype2 fontconfig)
|
||||
|
||||
ifeq ($(IMAGELIB), imagemagick)
|
||||
INCLUDES += $(shell pkg-config --cflags Magick++)
|
||||
LIBS += $(shell pkg-config --libs Magick++)
|
||||
else ifeq ($(IMAGELIB), graphicsmagick)
|
||||
INCLUDES += $(shell pkg-config --cflags GraphicsMagick++)
|
||||
LIBS += $(shell pkg-config --libs GraphicsMagick++)
|
||||
endif
|
||||
INCLUDES += $(shell pkg-config --cflags librsvg-2.0 cairo-png) -ljpeg
|
||||
LIBS += $(shell pkg-config --libs librsvg-2.0 cairo-png) -ljpeg
|
||||
|
||||
LIBS += $(shell xml2-config --libs)
|
||||
|
||||
@ -74,8 +66,6 @@ OBJS = $(PLUGIN).o \
|
||||
libcore/pixmapcontainer.o \
|
||||
libcore/fontmanager.o \
|
||||
libcore/imagecache.o \
|
||||
libcore/imagemagickwrapper.o \
|
||||
libcore/imagescaler.o \
|
||||
libcore/helpers.o \
|
||||
libcore/imageloader.o \
|
||||
libcore/recfolderinfo.o \
|
||||
|
71
README
71
README
@ -5,7 +5,7 @@ Written by: Louis Braun <louis DOT braun AT gmx DOT de>
|
||||
Project's homepage: http://projects.vdr-developer.org/projects/plg-skindesigner
|
||||
|
||||
Latest version: http://projects.vdr-developer.org/projects/plg-skindesigner/files
|
||||
GIT repository: git clone git://projects.vdr-developer.org/vdr-plugin-skindesigner.git
|
||||
GIT repository: git clone git://projects.vdr-developer.org/vdr-plugin-skindesigner.git
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -16,9 +16,9 @@ See the file COPYING for more information.
|
||||
Description
|
||||
-----------
|
||||
|
||||
Skindesigner is a VDR skin engine that displays XML based Skins.
|
||||
Skindesigner is a VDR skin engine that displays XML based Skins.
|
||||
|
||||
Currently two XML Skins (MetrixHD and nOpacity freestyle) are included in
|
||||
Currently two XML Skins (MetrixHD and nOpacity freestyle) are included in
|
||||
<pluginsourcedir>/skins/
|
||||
|
||||
Requirements
|
||||
@ -26,19 +26,19 @@ Requirements
|
||||
|
||||
- VDR version >= 2.0.0
|
||||
|
||||
- Installed ImageMagick or GraphicsMagick for displaying png/jpg Icons, Channel Logos
|
||||
and EPG Images (configurable during make via IMAGELIB = imagemagick|graphicsmagick
|
||||
parameter)
|
||||
- cairo
|
||||
|
||||
- librsvg-2
|
||||
|
||||
- libxml2
|
||||
|
||||
- for scaling the video picture to fit into the VDR menu window please use
|
||||
- for scaling the video picture to fit into the VDR menu window please use
|
||||
softhddevice plugin revision 87c1c7be (2013-01-01) or newer.
|
||||
|
||||
- epgsearch Git since commit ba7c6277 (2013-01-03) to correctly replace the schedules
|
||||
menu with epgsearch
|
||||
- epgsearch Git since commit ba7c6277 (2013-01-03) to correctly replace the
|
||||
schedules menu with epgsearch
|
||||
|
||||
Installation
|
||||
Installation
|
||||
------------
|
||||
|
||||
After "normal" Plugin installation you have to care about the paths for the
|
||||
@ -53,10 +53,10 @@ XML skins and epg images. The following paths can be set at startup:
|
||||
-e path, --epgimages=path
|
||||
Path to the epgimages (Default: <CacheDirectory>/epgimages/)
|
||||
|
||||
ResourceDirectory and CacheDirectory are taken from your VDR configuration (make.config
|
||||
or vdr.pc).
|
||||
ResourceDirectory and CacheDirectory are taken from your VDR configuration
|
||||
(make.config or vdr.pc).
|
||||
|
||||
During a "make install" the included skins are automatically copied from
|
||||
During a "make install" the included skins are automatically copied from
|
||||
<SkinSourceDirectory>/skins/ to the configured path.
|
||||
|
||||
For S2-6400 Users: Disable High Level OSD, otherwise the plugin will not be
|
||||
@ -67,20 +67,21 @@ an suitable true color OSD.
|
||||
|
||||
For Xineliboutput Users: Start vdr-sxfe with the --hud option enabled
|
||||
|
||||
Since the default skin MetrixHD uses VDROpenSans as font which is not installed per
|
||||
default, you may want to install this font (included in <SkinSourceDirectory>/fonts/)
|
||||
first. Otherwise the inside VDRs OSD menu configured vdrOsd Font is used as default.
|
||||
Since the default skin MetrixHD uses VDROpenSans as font which is not installed
|
||||
per default, you may want to install this font (included in
|
||||
<SkinSourceDirectory>/fonts/) first. Otherwise the inside VDRs OSD menu
|
||||
configured vdrOsd Font is used as default.
|
||||
|
||||
Channel Logos
|
||||
-------------
|
||||
|
||||
Since each XML skin is responsible for it's used channel logos, skindesigner searches
|
||||
for channel logos only in the skin dependend directory
|
||||
Since each XML skin is responsible for it's used channel logos, skindesigner
|
||||
searches for channel logos only in the skin dependend directory
|
||||
|
||||
<ResourceDirectory>/plugins/skindesigner/skins/<skinname>/logos
|
||||
|
||||
Each copy your used logos directly to this directory or set a symbolic link to a common
|
||||
channellogo directory.
|
||||
Each copy your used logos directly to this directory or set a symbolic link to
|
||||
a common channellogo directory.
|
||||
|
||||
I recommend to use channel logos from https://github.com/3PO/Senderlogos
|
||||
To download them just change in the directory you want to place the logos
|
||||
@ -89,17 +90,19 @@ git clone https://github.com/3PO/Senderlogos.git logos
|
||||
An update of the logos can then be done with a "git pull" just inside this
|
||||
directory.
|
||||
|
||||
In this logo pack all files are named only with lower case letters.
|
||||
Skindesigner uses the channel name CONVERTED TO LOWER CASE LETTERS to search for an
|
||||
appropriate channel logo. With this, approximately 90% of the channel logos should work
|
||||
immediately after placing the channel logos in the correct place. So if you have to change
|
||||
the name of a channel logo (may be by inserting a space or a hyphen) so that it fits to
|
||||
the channel name, only use lower case letters, and not the name of the channel with upper
|
||||
and lower letters as displayed inside VDR.
|
||||
If no logo is found for the channel name, additionally a search for a logo named as the
|
||||
ChannelID is performed. Analog to the channel name the ChannelID is also converted to lower
|
||||
case letters. This allows channel logos for channels with changing names (for instance
|
||||
Sky Feed Channels).
|
||||
Additional hint: some channels have slashes in their name (in germany nick/comedy for instance).
|
||||
In this example, as a dirty hack just create a folder in your channel logo directory named
|
||||
"nick" and place an image named "comedy.png" inside this folder.
|
||||
In this logo pack all files are named only with lower case letters.
|
||||
Skindesigner uses the channel name CONVERTED TO LOWER CASE LETTERS to search
|
||||
for an appropriate channel logo. With this, approximately 90% of the channel
|
||||
logos should work immediately after placing the channel logos in the correct
|
||||
place. So if you have to change the name of a channel logo (may be by inserting
|
||||
a space or a hyphen) so that it fits to the channel name, only use lower case
|
||||
letters, and not the name of the channel with upper and lower letters as
|
||||
displayed inside VDR.
|
||||
If no logo is found for the channel name, additionally a search for a logo
|
||||
named as the ChannelID is performed. Analog to the channel name the ChannelID
|
||||
is also converted to lower case letters. This allows channel logos for channels
|
||||
with changing names (for instance Sky Feed Channels).
|
||||
Additional hint: some channels have slashes in their name (in germany
|
||||
nick/comedy for instance).
|
||||
In this example, as a dirty hack just create a folder in your channel logo
|
||||
directory named "nick" and place an image named "comedy.png" inside this folder.
|
||||
|
1
config.c
1
config.c
@ -7,7 +7,6 @@ cDesignerConfig::cDesignerConfig() {
|
||||
skinPathSet = false;
|
||||
logoPathSet = false;
|
||||
//Common
|
||||
logoExtension = "png";
|
||||
numLogosPerSizeInitial = 30;
|
||||
limitLogoCache = 1;
|
||||
numLogosMax = 200;
|
||||
|
1
config.h
1
config.h
@ -48,7 +48,6 @@ public:
|
||||
void AddPlugin(string name, map < int, string > &menus);
|
||||
void InitPluginIterator(void);
|
||||
map <int,string> *GetPluginTemplates(string &name);
|
||||
cString logoExtension;
|
||||
cString skinPath;
|
||||
cString logoPath;
|
||||
cString epgImagePath;
|
||||
|
@ -7,14 +7,13 @@
|
||||
#include "../config.h"
|
||||
#include "helpers.h"
|
||||
|
||||
using namespace Magick;
|
||||
|
||||
cMutex cImageCache::mutex;
|
||||
|
||||
string cImageCache::items[16] = { "Schedule", "Channels", "Timers", "Recordings", "Setup", "Commands",
|
||||
"OSD", "EPG", "DVB", "LNB", "CAM", "Recording", "Replay", "Miscellaneous", "Plugins", "Restart"};
|
||||
|
||||
cImageCache::cImageCache() : cImageMagickWrapper() {
|
||||
cImageCache::cImageCache() {
|
||||
tempStaticLogo = NULL;
|
||||
}
|
||||
|
||||
@ -141,27 +140,19 @@ bool cImageCache::LogoExists(string channelID) {
|
||||
if (!channel)
|
||||
return false;
|
||||
string logoLower = StrToLowerCase(channel->Name());
|
||||
string logoExt = *config.logoExtension;
|
||||
bool logoExists = FileExists(logoPath.c_str(), logoLower, logoExt);
|
||||
if (logoExists) {
|
||||
return true;
|
||||
}
|
||||
logoExists = FileExists(logoPath.c_str(), channelID, logoExt);
|
||||
if (logoExists) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return (FileExists(logoPath.c_str(), logoLower, "svg") ||
|
||||
FileExists(logoPath.c_str(), logoLower, "png") ||
|
||||
FileExists(logoPath.c_str(), channelID, "svg") ||
|
||||
FileExists(logoPath.c_str(), channelID, "png"));
|
||||
}
|
||||
|
||||
bool cImageCache::SeparatorLogoExists(string name) {
|
||||
string separatorPath = *cString::sprintf("%sseparatorlogos/", logoPath.c_str());
|
||||
string nameLower = StrToLowerCase(name.c_str());
|
||||
string logoExt = *config.logoExtension;
|
||||
bool logoExists = FileExists(separatorPath, nameLower, logoExt);
|
||||
if (logoExists) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return (FileExists(separatorPath, nameLower, "svg") ||
|
||||
FileExists(separatorPath, nameLower, "png"));
|
||||
}
|
||||
|
||||
void cImageCache::CacheIcon(eImageType type, string name, int width, int height) {
|
||||
@ -312,18 +303,17 @@ cImage *cImageCache::GetSkinpart(string name, int width, int height) {
|
||||
}
|
||||
|
||||
bool cImageCache::LoadIcon(eImageType type, string name) {
|
||||
bool success = false;
|
||||
cString subdir("");
|
||||
if (type == itMenuIcon)
|
||||
subdir = "menuicons";
|
||||
else if (type == itIcon)
|
||||
subdir = "icons";
|
||||
cString subIconPath = cString::sprintf("%s%s/", iconPath.c_str(), *subdir);
|
||||
success = LoadImage(name, *subIconPath, "png");
|
||||
if (success) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
if (FileExists(*subIconPath, name, "svg"))
|
||||
return LoadImage(*subIconPath, name, "svg");
|
||||
else
|
||||
return LoadImage(*subIconPath, name, "png");
|
||||
}
|
||||
|
||||
bool cImageCache::LoadLogo(const cChannel *channel) {
|
||||
@ -331,33 +321,33 @@ bool cImageCache::LoadLogo(const cChannel *channel) {
|
||||
return false;
|
||||
string channelID = StrToLowerCase(*(channel->GetChannelID().ToString()));
|
||||
string logoLower = StrToLowerCase(channel->Name());
|
||||
bool success = false;
|
||||
success = LoadImage(channelID.c_str(), logoPath.c_str(), *config.logoExtension);
|
||||
if (success)
|
||||
return true;
|
||||
success = LoadImage(logoLower.c_str(), logoPath.c_str(), *config.logoExtension);
|
||||
if (success)
|
||||
return true;
|
||||
|
||||
if (FileExists(logoPath.c_str(), channelID.c_str(), "svg"))
|
||||
return LoadImage(logoPath.c_str(), channelID.c_str(), "svg");
|
||||
if (FileExists(logoPath.c_str(), channelID.c_str(), "png"))
|
||||
return LoadImage(logoPath.c_str(), channelID.c_str(), "png");
|
||||
if (FileExists(logoPath.c_str(), logoLower.c_str(), "svg"))
|
||||
return LoadImage(logoPath.c_str(), logoLower.c_str(), "svg");
|
||||
if (FileExists(logoPath.c_str(), logoLower.c_str(), "png"))
|
||||
return LoadImage(logoPath.c_str(), logoLower.c_str(), "png");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cImageCache::LoadSeparatorLogo(string name) {
|
||||
cString separatorPath = cString::sprintf("%sseparatorlogos/", logoPath.c_str());
|
||||
string separatorPath = *cString::sprintf("%sseparatorlogos/", logoPath.c_str());
|
||||
string nameLower = StrToLowerCase(name.c_str());
|
||||
bool success = false;
|
||||
success = LoadImage(nameLower.c_str(), *separatorPath, *config.logoExtension);
|
||||
if (success)
|
||||
return true;
|
||||
return false;
|
||||
if (FileExists(separatorPath, nameLower.c_str(), "svg"))
|
||||
return LoadImage(separatorPath, nameLower.c_str(), "svg");
|
||||
else
|
||||
return LoadImage(separatorPath, nameLower.c_str(), "png");
|
||||
}
|
||||
|
||||
bool cImageCache::LoadSkinpart(string name) {
|
||||
bool success = false;
|
||||
success = LoadImage(name, skinPartsPath.c_str(), "png");
|
||||
if (success) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (FileExists(skinPartsPath.c_str(), name, "svg"))
|
||||
return LoadImage(skinPartsPath.c_str(), name, "svg");
|
||||
else
|
||||
return LoadImage(skinPartsPath.c_str(), name, "png");
|
||||
}
|
||||
|
||||
void cImageCache::Clear(void) {
|
||||
|
@ -5,14 +5,11 @@
|
||||
|
||||
#include <vdr/osd.h>
|
||||
#include <vdr/skins.h>
|
||||
#include <Magick++.h>
|
||||
#include <vector>
|
||||
#include "imagemagickwrapper.h"
|
||||
#include "imageloader.h"
|
||||
#include "../libtemplate/templatefunction.h"
|
||||
|
||||
using namespace Magick;
|
||||
|
||||
class cImageCache : public cImageMagickWrapper {
|
||||
class cImageCache : public cImageLoader {
|
||||
public:
|
||||
cImageCache();
|
||||
~cImageCache();
|
||||
|
@ -1,62 +1,400 @@
|
||||
#include "../config.h"
|
||||
#include "helpers.h"
|
||||
#include "imageloader.h"
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include <dirent.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Magick;
|
||||
|
||||
cImageLoader::cImageLoader() : cImageMagickWrapper() {
|
||||
cImageLoader::cImageLoader() {
|
||||
importer = NULL;
|
||||
}
|
||||
|
||||
cImageLoader::~cImageLoader() {
|
||||
delete(importer);
|
||||
}
|
||||
|
||||
cImage cImageLoader::GetImage() {
|
||||
return CreateImageCopy();
|
||||
}
|
||||
cImage *cImageLoader::CreateImage(int width, int height, bool preserveAspect) {
|
||||
if (!importer)
|
||||
return NULL;
|
||||
|
||||
bool cImageLoader::LoadImage(const char *path, int width, int height) {
|
||||
if (cImageMagickWrapper::LoadImage(path)) {
|
||||
buffer.sample(Geometry(width, height));
|
||||
return true;
|
||||
int w, h;
|
||||
importer->GetImageSize(w, h);
|
||||
if (width == 0)
|
||||
width = w;
|
||||
if (height == 0)
|
||||
height = h;
|
||||
|
||||
cairo_surface_t *surface;
|
||||
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
|
||||
cairo_t *cr;
|
||||
cr = cairo_create(surface);
|
||||
|
||||
double sx = width / (double)w;
|
||||
double sy = height / (double)h;
|
||||
if (preserveAspect) {
|
||||
double tx = 0;
|
||||
double ty = 0;
|
||||
if (sx < sy) {
|
||||
sy = sx;
|
||||
ty = (height - h * sy) / 2;
|
||||
}
|
||||
if (sy < sx) {
|
||||
sx = sy;
|
||||
tx = (width - w * sx) / 2;
|
||||
}
|
||||
cairo_translate(cr, tx, ty);
|
||||
}
|
||||
return false;
|
||||
cairo_scale(cr, sx, sy);
|
||||
|
||||
importer->DrawToCairo(cr);
|
||||
|
||||
cairo_status_t status = cairo_status(cr);
|
||||
if (status && config.debugImageLoading)
|
||||
dsyslog("skindesigner: Cairo CreateImage Error %s", cairo_status_to_string(status));
|
||||
|
||||
unsigned char *data = cairo_image_surface_get_data(surface);
|
||||
cImage *image = new cImage(cSize(width, height), (tColor*)data);
|
||||
|
||||
cairo_destroy(cr);
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
bool cImageLoader::LoadImage(const char *fullpath) {
|
||||
if ((fullpath == NULL) || (strlen(fullpath) < 5))
|
||||
return false;
|
||||
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: trying to load: %s", fullpath);
|
||||
|
||||
delete(importer);
|
||||
importer = NULL;
|
||||
|
||||
if (endswith(fullpath, ".png"))
|
||||
importer = new cImageImporterPNG;
|
||||
else if (endswith(fullpath, ".svg"))
|
||||
importer = new cImageImporterSVG;
|
||||
else if (endswith(fullpath, ".jpg"))
|
||||
importer = new cImageImporterJPG;
|
||||
else
|
||||
return false;
|
||||
|
||||
return importer->LoadImage(fullpath);
|
||||
}
|
||||
|
||||
// Just a different way to call LoadImage. Calls the above one.
|
||||
bool cImageLoader::LoadImage(std::string Path, std::string FileName, std::string Extension) {
|
||||
std::stringstream sstrImgFile;
|
||||
sstrImgFile << Path << FileName << "." << Extension;
|
||||
std::string imgFile = sstrImgFile.str();
|
||||
return LoadImage(imgFile.c_str());
|
||||
}
|
||||
|
||||
void cImageLoader::DeterminateChannelLogoSize(int &width, int &height) {
|
||||
cString logoPath;
|
||||
cString logoPathSkin = cString::sprintf("%s%s/themes/%s/logos/", *config.skinPath, Setup.OSDSkin, Setup.OSDTheme);
|
||||
if (FolderExists(*logoPathSkin)) {
|
||||
|
||||
if (FolderExists(*logoPathSkin))
|
||||
logoPath = logoPathSkin;
|
||||
} else {
|
||||
else
|
||||
logoPath = config.logoPath;
|
||||
}
|
||||
cString logoExt = config.logoExtension;
|
||||
|
||||
DIR *folder = NULL;
|
||||
struct dirent *file;
|
||||
folder = opendir(logoPath);
|
||||
if (!folder) {
|
||||
if (!folder)
|
||||
return;
|
||||
}
|
||||
while (file = readdir(folder)) {
|
||||
if (endswith(file->d_name, *logoExt)) {
|
||||
|
||||
while ( (file = readdir(folder)) ) {
|
||||
if (endswith(file->d_name, ".png") ||
|
||||
endswith(file->d_name, ".svg")) {
|
||||
std::stringstream filePath;
|
||||
filePath << *logoPath << file->d_name;
|
||||
Image logo;
|
||||
try {
|
||||
logo.read(filePath.str().c_str());
|
||||
Geometry g = logo.size();
|
||||
int logoWidth = g.width();
|
||||
int logoHeight = g.height();
|
||||
if (LoadImage(filePath.str().c_str())) {
|
||||
int logoWidth = 0;
|
||||
int logoHeight = 0;
|
||||
importer->GetImageSize(logoWidth, logoHeight);
|
||||
if (logoWidth > 0 && logoHeight > 0) {
|
||||
width = logoWidth;
|
||||
height = logoHeight;
|
||||
delete(importer);
|
||||
importer = NULL;
|
||||
return;
|
||||
}
|
||||
} catch( ... ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Image importer for PNG
|
||||
//
|
||||
|
||||
cImageImporterPNG::cImageImporterPNG() {
|
||||
surface = NULL;
|
||||
}
|
||||
|
||||
cImageImporterPNG::~cImageImporterPNG() {
|
||||
if (surface)
|
||||
cairo_surface_destroy(surface);
|
||||
}
|
||||
|
||||
bool cImageImporterPNG::LoadImage(const char *path) {
|
||||
if (surface)
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
surface = cairo_image_surface_create_from_png(path);
|
||||
|
||||
if (cairo_surface_status(surface)) {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: Cairo LoadImage Error: %s", cairo_status_to_string(cairo_surface_status(surface)));
|
||||
surface = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cImageImporterPNG::DrawToCairo(cairo_t *cr) {
|
||||
if (surface) {
|
||||
cairo_set_source_surface(cr, surface, 0, 0);
|
||||
cairo_paint(cr);
|
||||
}
|
||||
}
|
||||
|
||||
void cImageImporterPNG::GetImageSize(int &width, int &height) {
|
||||
if (surface) {
|
||||
width = cairo_image_surface_get_width(surface);
|
||||
height = cairo_image_surface_get_height(surface);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Image importer for SVG
|
||||
//
|
||||
|
||||
cImageImporterSVG::cImageImporterSVG() {
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
cImageImporterSVG::~cImageImporterSVG() {
|
||||
if (handle) {
|
||||
rsvg_handle_close(handle, NULL);
|
||||
g_object_unref(handle);
|
||||
}
|
||||
}
|
||||
|
||||
bool cImageImporterSVG::LoadImage(const char *path) {
|
||||
if (handle) {
|
||||
rsvg_handle_close(handle, NULL);
|
||||
g_object_unref(handle);
|
||||
}
|
||||
|
||||
GError *error = NULL;
|
||||
handle = rsvg_handle_new_from_file(path, &error);
|
||||
if (!handle) {
|
||||
if (config.debugImageLoading && error) {
|
||||
dsyslog("skindesigner: RSVG Error: %s", error->message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 90 dpi is the hardcoded default setting of the Inkscape SVG editor
|
||||
rsvg_handle_set_dpi(handle, 90);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void cImageImporterSVG::DrawToCairo(cairo_t *cr) {
|
||||
if (handle)
|
||||
rsvg_handle_render_cairo(handle, cr);
|
||||
}
|
||||
|
||||
void cImageImporterSVG::GetImageSize(int &width, int &height) {
|
||||
if (handle) {
|
||||
RsvgDimensionData dim;
|
||||
rsvg_handle_get_dimensions(handle, &dim);
|
||||
width = dim.width;
|
||||
height = dim.height;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Image importer for JPG
|
||||
//
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; // "public" fields
|
||||
jmp_buf setjmp_buffer; // for return to caller
|
||||
};
|
||||
|
||||
METHODDEF(void)
|
||||
my_error_exit(j_common_ptr cinfo) {
|
||||
// cinfo->err really points to a my_error_mgr struct, so coerce pointer
|
||||
my_error_mgr *myerr = (my_error_mgr*) cinfo->err;
|
||||
|
||||
// Always display the message.
|
||||
(*cinfo->err->output_message) (cinfo);
|
||||
|
||||
// Return control to the setjmp point
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
METHODDEF(void)
|
||||
my_output_message(j_common_ptr cinfo) {
|
||||
char buf[JMSG_LENGTH_MAX];
|
||||
cinfo->err->format_message(cinfo, buf);
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: libjpeg error: %s", buf);
|
||||
}
|
||||
|
||||
cImageImporterJPG::cImageImporterJPG() {
|
||||
cinfo = NULL;
|
||||
}
|
||||
|
||||
cImageImporterJPG::~cImageImporterJPG() {
|
||||
if (cinfo) {
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
free(cinfo);
|
||||
fclose(infile);
|
||||
}
|
||||
}
|
||||
|
||||
bool cImageImporterJPG::LoadImage(const char *path) {
|
||||
if (cinfo) {
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
free(cinfo);
|
||||
fclose(infile);
|
||||
cinfo = NULL;
|
||||
}
|
||||
|
||||
// Open input file
|
||||
if ((infile = fopen(path, "rb")) == NULL) {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: Can't open %s", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate space for our decompress struct
|
||||
cinfo = (j_decompress_ptr)malloc(sizeof(struct jpeg_decompress_struct));
|
||||
|
||||
// We set up the normal JPEG error routines, then override error_exit
|
||||
// and output_message.
|
||||
struct my_error_mgr jerr;
|
||||
cinfo->err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
jerr.pub.output_message = my_output_message;
|
||||
// Establish the setjmp return context for my_error_exit to use.
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
// If we get here, the JPEG code has signaled an error.
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
free(cinfo);
|
||||
fclose(infile);
|
||||
cinfo = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now we can initialize the JPEG decompression object.
|
||||
jpeg_create_decompress(cinfo);
|
||||
|
||||
// Step 2: specify data source (eg, a file)
|
||||
jpeg_stdio_src(cinfo, infile);
|
||||
|
||||
// Step 3: read file parameters with jpeg_read_header()
|
||||
(void) jpeg_read_header(cinfo, TRUE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cImageImporterJPG::DrawToCairo(cairo_t *cr) {
|
||||
if (!cinfo)
|
||||
return;
|
||||
|
||||
unsigned char *bmp_buffer = NULL;
|
||||
|
||||
// Re-establish error handling. We have to do this again as the saved
|
||||
// calling environment of "LoadImage" is invalid if we reach here!
|
||||
struct my_error_mgr jerr;
|
||||
cinfo->err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
jerr.pub.output_message = my_output_message;
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
free(cinfo);
|
||||
fclose(infile);
|
||||
free(bmp_buffer);
|
||||
cinfo = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 4: set parameters for decompression
|
||||
cinfo->out_color_space = JCS_RGB;
|
||||
|
||||
// Step 5: Start decompressor
|
||||
(void) jpeg_start_decompress(cinfo);
|
||||
|
||||
// Allocate buffer. Directly allocate the space needed for ARGB
|
||||
unsigned int width = cinfo->output_width;
|
||||
unsigned int height = cinfo->output_height;
|
||||
bmp_buffer = (unsigned char*)malloc(width * height * 4);
|
||||
|
||||
// Step 6: while (scan lines remain to be read)
|
||||
int jpg_stride = width * cinfo->output_components;
|
||||
while (cinfo->output_scanline < height) {
|
||||
unsigned char *buffer_array[1];
|
||||
buffer_array[0] = bmp_buffer + (cinfo->output_scanline) * jpg_stride;
|
||||
jpeg_read_scanlines(cinfo, buffer_array, 1);
|
||||
}
|
||||
|
||||
// Step 7: Finish decompression.
|
||||
(void)jpeg_finish_decompress(cinfo);
|
||||
|
||||
// Cleanup. In this "ImageImporter" we clean up everything in "DrawToCairo"
|
||||
// as I'm not really sure whether we are able to draw a second time.
|
||||
fclose(infile);
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
free(cinfo);
|
||||
cinfo = NULL;
|
||||
|
||||
// --> At this point we have raw RGB data in bmp_buffer
|
||||
|
||||
// Do some ugly byte shifting.
|
||||
// Byte order in libjpeg: RGB
|
||||
// Byte order in cairo and VDR: BGRA
|
||||
unsigned char temp[3];
|
||||
for (int index = (width * height) - 1; index >= 0; index--) {
|
||||
unsigned char *target = bmp_buffer + (index * 4);
|
||||
unsigned char *source = bmp_buffer + (index * 3);
|
||||
memcpy(&temp[0], source + 2, 1);
|
||||
memcpy(&temp[1], source + 1, 1);
|
||||
memcpy(&temp[2], source, 1);
|
||||
memcpy(target, &temp, 3);
|
||||
}
|
||||
|
||||
// Create new Cairo surface from our raw image data
|
||||
cairo_surface_t *surface;
|
||||
surface = cairo_image_surface_create_for_data(bmp_buffer,
|
||||
CAIRO_FORMAT_RGB24,
|
||||
width,
|
||||
height,
|
||||
width * 4);
|
||||
|
||||
// Draw surface to Cairo
|
||||
if (surface) {
|
||||
cairo_set_source_surface(cr, surface, 0, 0);
|
||||
cairo_paint(cr);
|
||||
cairo_surface_destroy(surface);
|
||||
}
|
||||
|
||||
// Free our memory
|
||||
free(bmp_buffer);
|
||||
}
|
||||
|
||||
void cImageImporterJPG::GetImageSize(int &width, int &height) {
|
||||
if (cinfo) {
|
||||
width = cinfo->image_width;
|
||||
height = cinfo->image_height;
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,82 @@
|
||||
#ifndef __NOPACITY_IMAGELOADER_H
|
||||
#define __NOPACITY_IMAGELOADER_H
|
||||
|
||||
#define X_DISPLAY_MISSING
|
||||
|
||||
#include <cairo.h>
|
||||
#include <librsvg/rsvg.h>
|
||||
#ifndef LIBRSVG_VERSION // Workaround for librsvg < 2.36.2
|
||||
#include <librsvg/rsvg-cairo.h>
|
||||
#endif
|
||||
#include <jpeglib.h>
|
||||
#include <setjmp.h>
|
||||
#include <vdr/osd.h>
|
||||
#include <vdr/skins.h>
|
||||
#include <Magick++.h>
|
||||
#include "imagemagickwrapper.h"
|
||||
#include <vdr/tools.h>
|
||||
|
||||
using namespace Magick;
|
||||
//
|
||||
// Image importers
|
||||
//
|
||||
class cImageImporter {
|
||||
public:
|
||||
cImageImporter() {};
|
||||
virtual ~cImageImporter() {};
|
||||
virtual bool LoadImage(const char *path) { return false; };
|
||||
virtual void DrawToCairo(cairo_t *cr) {};
|
||||
virtual void GetImageSize(int &width, int &height) {};
|
||||
};
|
||||
|
||||
class cImageLoader : public cImageMagickWrapper {
|
||||
// Image importer for PNG
|
||||
class cImageImporterPNG : public cImageImporter {
|
||||
public:
|
||||
cImageImporterPNG();
|
||||
~cImageImporterPNG();
|
||||
bool LoadImage(const char *path);
|
||||
void DrawToCairo(cairo_t *cr);
|
||||
void GetImageSize(int &width, int &height);
|
||||
private:
|
||||
cairo_surface_t *surface;
|
||||
};
|
||||
|
||||
// Image importer for SVG
|
||||
class cImageImporterSVG : public cImageImporter {
|
||||
public:
|
||||
cImageImporterSVG();
|
||||
~cImageImporterSVG();
|
||||
bool LoadImage(const char *path);
|
||||
void DrawToCairo(cairo_t *cr);
|
||||
void GetImageSize(int &width, int &height);
|
||||
private:
|
||||
RsvgHandle *handle;
|
||||
};
|
||||
|
||||
// Image importer for JPG
|
||||
#if BITS_IN_JSAMPLE != 8
|
||||
#error libjpeg has to be compiled with 8-bit samples!
|
||||
#endif
|
||||
|
||||
class cImageImporterJPG : public cImageImporter {
|
||||
public:
|
||||
cImageImporterJPG();
|
||||
~cImageImporterJPG();
|
||||
bool LoadImage(const char *path);
|
||||
void DrawToCairo(cairo_t *cr);
|
||||
void GetImageSize(int &width, int &height);
|
||||
private:
|
||||
j_decompress_ptr cinfo;
|
||||
FILE *infile;
|
||||
};
|
||||
|
||||
//
|
||||
// Image loader class
|
||||
//
|
||||
class cImageLoader {
|
||||
private:
|
||||
cImageImporter *importer;
|
||||
public:
|
||||
cImageLoader();
|
||||
~cImageLoader();
|
||||
cImage GetImage();
|
||||
bool LoadImage(const char *path, int width, int height);
|
||||
virtual ~cImageLoader();
|
||||
cImage *CreateImage(int width, int height, bool preserveAspect = true);
|
||||
bool LoadImage(std::string Path, std::string FileName, std::string Extension);
|
||||
bool LoadImage(const char *fullpath);
|
||||
void DeterminateChannelLogoSize(int &width, int &height);
|
||||
private:
|
||||
};
|
||||
|
||||
#endif //__NOPACITY_IMAGELOADER_H
|
||||
|
@ -1,162 +0,0 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "imagemagickwrapper.h"
|
||||
#include "../config.h"
|
||||
#include "imagescaler.h"
|
||||
|
||||
cImageMagickWrapper::cImageMagickWrapper() {
|
||||
InitializeMagick(NULL);
|
||||
}
|
||||
|
||||
cImageMagickWrapper::~cImageMagickWrapper() {
|
||||
}
|
||||
|
||||
cImage *cImageMagickWrapper::CreateImage(int width, int height, bool preserveAspect) {
|
||||
int w, h;
|
||||
w = buffer.columns();
|
||||
h = buffer.rows();
|
||||
if (width == 0)
|
||||
width = w;
|
||||
if (height == 0)
|
||||
height = h;
|
||||
if (preserveAspect) {
|
||||
unsigned scale_w = 1000 * width / w;
|
||||
unsigned scale_h = 1000 * height / h;
|
||||
if (scale_w > scale_h)
|
||||
width = w * height / h;
|
||||
else
|
||||
height = h * width / w;
|
||||
}
|
||||
const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
|
||||
cImage *image = new cImage(cSize(width, height));
|
||||
tColor *imgData = (tColor *)image->Data();
|
||||
if (w != width || h != height) {
|
||||
ImageScaler scaler;
|
||||
scaler.SetImageParameters(imgData, width, width, height, w, h);
|
||||
for (const void *pixels_end = &pixels[w*h]; pixels < pixels_end; ++pixels)
|
||||
scaler.PutSourcePixel(pixels->blue / ((MaxRGB + 1) / 256),
|
||||
pixels->green / ((MaxRGB + 1) / 256),
|
||||
pixels->red / ((MaxRGB + 1) / 256),
|
||||
~((unsigned char)(pixels->opacity / ((MaxRGB + 1) / 256))));
|
||||
return image;
|
||||
}
|
||||
for (const void *pixels_end = &pixels[width*height]; pixels < pixels_end; ++pixels)
|
||||
*imgData++ = ((~int(pixels->opacity / ((MaxRGB + 1) / 256)) << 24) |
|
||||
(int(pixels->green / ((MaxRGB + 1) / 256)) << 8) |
|
||||
(int(pixels->red / ((MaxRGB + 1) / 256)) << 16) |
|
||||
(int(pixels->blue / ((MaxRGB + 1) / 256)) ));
|
||||
return image;
|
||||
}
|
||||
|
||||
cImage cImageMagickWrapper::CreateImageCopy() {
|
||||
int w, h;
|
||||
w = buffer.columns();
|
||||
h = buffer.rows();
|
||||
cImage image (cSize(w, h));
|
||||
const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
|
||||
for (int iy = 0; iy < h; ++iy) {
|
||||
for (int ix = 0; ix < w; ++ix) {
|
||||
tColor col = (~int(pixels->opacity * 255 / MaxRGB) << 24)
|
||||
| (int(pixels->green * 255 / MaxRGB) << 8)
|
||||
| (int(pixels->red * 255 / MaxRGB) << 16)
|
||||
| (int(pixels->blue * 255 / MaxRGB) );
|
||||
image.SetPixel(cPoint(ix, iy), col);
|
||||
++pixels;
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
bool cImageMagickWrapper::LoadImage(std::string FileName, std::string Path, std::string Extension) {
|
||||
try {
|
||||
std::stringstream sstrImgFile;
|
||||
sstrImgFile << Path << FileName << "." << Extension;
|
||||
std::string imgFile = sstrImgFile.str();
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: trying to load: %s", imgFile.c_str());
|
||||
buffer.read(imgFile.c_str());
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: %s sucessfully loaded", imgFile.c_str());
|
||||
} catch( Magick::Warning &warning ) {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: Magick Warning: %s", warning.what());
|
||||
return true;
|
||||
} catch( Magick::Error &error ) {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: Magick Error: %s", error.what());
|
||||
return false;
|
||||
} catch(...) {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: an unknown Magick error occured during image loading");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cImageMagickWrapper::LoadImage(const char *fullpath) {
|
||||
if ((fullpath == NULL) || (strlen(fullpath) < 5))
|
||||
return false;
|
||||
try {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: trying to load: %s", fullpath);
|
||||
buffer.read(fullpath);
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: %s sucessfully loaded", fullpath);
|
||||
} catch( Magick::Warning &warning ) {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: Magick Warning: %s", warning.what());
|
||||
return true;
|
||||
} catch( Magick::Error &error ) {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: Magick Error: %s", error.what());
|
||||
return false;
|
||||
} catch(...) {
|
||||
if (config.debugImageLoading)
|
||||
dsyslog("skindesigner: an unknown Magick error occured during image loading");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Color cImageMagickWrapper::Argb2Color(tColor col) {
|
||||
tIndex alpha = (col & 0xFF000000) >> 24;
|
||||
tIndex red = (col & 0x00FF0000) >> 16;
|
||||
tIndex green = (col & 0x0000FF00) >> 8;
|
||||
tIndex blue = (col & 0x000000FF);
|
||||
Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255);
|
||||
return color;
|
||||
}
|
||||
|
||||
void cImageMagickWrapper::CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor) {
|
||||
Color Back = Argb2Color(back);
|
||||
Color Blend = Argb2Color(blend);
|
||||
int maxw = MaxRGB * wfactor;
|
||||
int maxh = MaxRGB * hfactor;
|
||||
|
||||
Image imgblend(Geometry(width, height), Blend);
|
||||
imgblend.modifyImage();
|
||||
imgblend.type(TrueColorMatteType);
|
||||
PixelPacket *pixels = imgblend.getPixels(0, 0, width, height);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
PixelPacket *pixel = pixels + y * width + x;
|
||||
int opacity = (maxw / width * x + maxh - maxh / height * y) / 2;
|
||||
pixel->opacity = (opacity <= MaxRGB) ? opacity : MaxRGB;
|
||||
}
|
||||
}
|
||||
imgblend.syncPixels();
|
||||
|
||||
Image imgback(Geometry(width, height), Back);
|
||||
imgback.composite(imgblend, 0, 0, OverCompositeOp);
|
||||
|
||||
buffer = imgback;
|
||||
}
|
||||
|
||||
void cImageMagickWrapper::CreateBackground(tColor back, tColor blend, int width, int height, bool mirror) {
|
||||
CreateGradient(back, blend, width, height, 0.8, 0.8);
|
||||
if (mirror)
|
||||
buffer.flop();
|
||||
}
|
||||
void cImageMagickWrapper::CreateBackgroundReverse(tColor back, tColor blend, int width, int height) {
|
||||
CreateGradient(back, blend, width, height, 1.3, 0.7);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#ifndef __NOPACITY_IMAGEMAGICKWRAPPER_H
|
||||
#define __NOPACITY_IMAGEMAGICKWRAPPER_H
|
||||
|
||||
#define X_DISPLAY_MISSING
|
||||
|
||||
#include <Magick++.h>
|
||||
#include <vdr/osd.h>
|
||||
|
||||
using namespace Magick;
|
||||
|
||||
class cImageMagickWrapper {
|
||||
private:
|
||||
void CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor);
|
||||
public:
|
||||
cImageMagickWrapper();
|
||||
~cImageMagickWrapper();
|
||||
protected:
|
||||
Image buffer;
|
||||
Color Argb2Color(tColor col);
|
||||
cImage *CreateImage(int width, int height, bool preserveAspect = true);
|
||||
cImage CreateImageCopy(void);
|
||||
bool LoadImage(std::string FileName, std::string Path, std::string Extension);
|
||||
bool LoadImage(const char *fullpath);
|
||||
void CreateBackground(tColor back, tColor blend, int width, int height, bool mirror = false);
|
||||
void CreateBackgroundReverse(tColor back, tColor blend, int width, int height);
|
||||
};
|
||||
|
||||
#endif //__NOPACITY_IMAGEMAGICKWRAPPER_H
|
@ -1,149 +0,0 @@
|
||||
|
||||
#include "imagescaler.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
|
||||
ImageScaler::ImageScaler() :
|
||||
m_memory(NULL),
|
||||
m_hor_filters(NULL),
|
||||
m_ver_filters(NULL),
|
||||
m_buffer(NULL),
|
||||
m_dst_image(NULL),
|
||||
m_dst_stride(0),
|
||||
m_dst_width(0),
|
||||
m_dst_height(0),
|
||||
m_src_width(0),
|
||||
m_src_height(0),
|
||||
m_src_x(0),
|
||||
m_src_y(0),
|
||||
m_dst_x(0),
|
||||
m_dst_y(0) {
|
||||
}
|
||||
|
||||
ImageScaler::~ImageScaler() {
|
||||
if ( m_memory ) free( m_memory );
|
||||
}
|
||||
|
||||
// sin(x)/(x)
|
||||
static float sincf( float x ) {
|
||||
if ( fabsf(x) < 0.05f ) return 1.0f - (1.0f/6.0f)*x*x; // taylor series approximation to avoid 0/0
|
||||
return sin(x)/x;
|
||||
}
|
||||
|
||||
static void CalculateFilters( ImageScaler::Filter *filters, int dst_size, int src_size ) {
|
||||
const float fc = dst_size >= src_size ? 1.0f : ((float) dst_size)/((float) src_size);
|
||||
|
||||
for (int i = 0; i < dst_size; i++) {
|
||||
const int d = 2*dst_size; // sample position denominator
|
||||
const int e = (2*i+1) * src_size - dst_size; // sample position enumerator
|
||||
int offset = e / d; // truncated sample position
|
||||
const float sub_offset = ((float) (e - offset*d)) / ((float) d); // exact sample position is (float) e/d = offset + sub_offset
|
||||
|
||||
// calculate filter coefficients
|
||||
float h[4];
|
||||
for (int j=0; j<4; j++) {
|
||||
const float t = 3.14159265359f * (sub_offset+(1-j));
|
||||
h[j] = sincf( fc * t ) * cosf( 0.25f * t ); // sinc-lowpass and cos-window
|
||||
}
|
||||
|
||||
// ensure that filter does not reach out off image bounds:
|
||||
while ( offset < 1 ) {
|
||||
h[0] += h[1];
|
||||
h[1] = h[2];
|
||||
h[2] = h[3];
|
||||
h[3] = 0.0f;
|
||||
offset++;
|
||||
}
|
||||
|
||||
while ( offset+3 > src_size ) {
|
||||
h[3] += h[2];
|
||||
h[2] = h[1];
|
||||
h[1] = h[0];
|
||||
h[0] = 0.0f;
|
||||
offset--;
|
||||
}
|
||||
|
||||
// coefficients are normalized to sum up to 2048
|
||||
const float norm = 2048.0f / ( h[0] + h[1] + h[2] + h[3] );
|
||||
|
||||
offset--; // offset of fist used pixel
|
||||
|
||||
filters[i].m_offset = offset + 4; // store offset of first unused pixel
|
||||
|
||||
for (int j=0; j<4; j++) {
|
||||
const float t = norm * h[j];
|
||||
filters[i].m_coeff[(offset+j) & 3] = (int) ((t > 0.0f) ? (t+0.5f) : (t-0.5f)); // consider ring buffer index permutations
|
||||
}
|
||||
}
|
||||
|
||||
// set end marker
|
||||
filters[dst_size].m_offset = (unsigned) -1;
|
||||
|
||||
}
|
||||
|
||||
void ImageScaler::SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height ) {
|
||||
m_src_x = 0;
|
||||
m_src_y = 0;
|
||||
m_dst_x = 0;
|
||||
m_dst_y = 0;
|
||||
|
||||
m_dst_image = dst_image;
|
||||
m_dst_stride = dst_stride;
|
||||
|
||||
// if image dimensions do not change we can keep the old filter coefficients
|
||||
if ( (src_width == m_src_width) && (src_height == m_src_height) && (dst_width == m_dst_width) && (dst_height == m_dst_height) ) return;
|
||||
|
||||
m_dst_width = dst_width;
|
||||
m_dst_height = dst_height;
|
||||
m_src_width = src_width;
|
||||
m_src_height = src_height;
|
||||
|
||||
if ( m_memory ) free( m_memory );
|
||||
|
||||
const unsigned hor_filters_size = (m_dst_width + 1) * sizeof(Filter); // reserve one extra position for end marker
|
||||
const unsigned ver_filters_size = (m_dst_height + 1) * sizeof(Filter);
|
||||
const unsigned buffer_size = 4 * m_dst_width * sizeof(TmpPixel);
|
||||
|
||||
char *p = (char *) malloc( hor_filters_size + ver_filters_size + buffer_size );
|
||||
|
||||
m_memory = p;
|
||||
|
||||
m_hor_filters = (Filter *) p; p += hor_filters_size;
|
||||
m_ver_filters = (Filter *) p; p += ver_filters_size;
|
||||
m_buffer = (TmpPixel *) p;
|
||||
|
||||
CalculateFilters( m_hor_filters, m_dst_width , m_src_width );
|
||||
CalculateFilters( m_ver_filters, m_dst_height, m_src_height );
|
||||
}
|
||||
|
||||
// shift range to 0..255 and clamp overflows
|
||||
static unsigned shift_clamp( int x ) {
|
||||
x = ( x + (1<<21) ) >> 22;
|
||||
if ( x < 0 ) return 0;
|
||||
if ( x > 255 ) return 255;
|
||||
return x;
|
||||
}
|
||||
|
||||
void ImageScaler::NextSourceLine() {
|
||||
m_dst_x = 0;
|
||||
m_src_x = 0;
|
||||
m_src_y++;
|
||||
|
||||
while ( m_ver_filters[m_dst_y].m_offset == m_src_y ) {
|
||||
const int h0 = m_ver_filters[m_dst_y].m_coeff[0];
|
||||
const int h1 = m_ver_filters[m_dst_y].m_coeff[1];
|
||||
const int h2 = m_ver_filters[m_dst_y].m_coeff[2];
|
||||
const int h3 = m_ver_filters[m_dst_y].m_coeff[3];
|
||||
const TmpPixel *src = m_buffer;
|
||||
unsigned *dst = m_dst_image + m_dst_stride * m_dst_y;
|
||||
|
||||
for (unsigned i=0; i<m_dst_width; i++) {
|
||||
const ImageScaler::TmpPixel t( src[0]*h0 + src[1]*h1 + src[2]*h2 + src[3]*h3 );
|
||||
src += 4;
|
||||
dst[i] = shift_clamp(t[0]) | (shift_clamp(t[1])<<8) | (shift_clamp(t[2])<<16) | (shift_clamp(t[3])<<24);
|
||||
}
|
||||
|
||||
m_dst_y++;
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
#ifndef _ImageScaler_h
|
||||
#define _ImageScaler_h
|
||||
|
||||
/*!
|
||||
* this class scales images consisting of 4 components (RGBA)
|
||||
* to an arbitrary size using a 4-tap filter
|
||||
*/
|
||||
class ImageScaler {
|
||||
public:
|
||||
|
||||
struct Filter {
|
||||
unsigned m_offset;
|
||||
short m_coeff[4];
|
||||
};
|
||||
|
||||
ImageScaler();
|
||||
~ImageScaler();
|
||||
|
||||
//! set destination image and source image size
|
||||
void SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height );
|
||||
|
||||
/*! process one pixel of source image; destination image is written while input is processed
|
||||
* SetImageParameters() must be called first
|
||||
*/
|
||||
void PutSourcePixel( unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3 ) {
|
||||
m_hbuf[ (m_src_x++) & 3 ].Set( c0, c1, c2, c3 );
|
||||
|
||||
TmpPixel *bp = m_buffer + 4 * m_dst_x + (m_src_y & 3);
|
||||
const Filter *fh;
|
||||
|
||||
while ( (fh=m_hor_filters+m_dst_x)->m_offset == m_src_x ) {
|
||||
*bp = m_hbuf[0]*fh->m_coeff[0] + m_hbuf[1]*fh->m_coeff[1] + m_hbuf[2]*fh->m_coeff[2] + m_hbuf[3]*fh->m_coeff[3];
|
||||
m_dst_x++;
|
||||
bp += 4;
|
||||
}
|
||||
|
||||
if ( m_src_x == m_src_width ) NextSourceLine();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//! temporary image pixel class - a 4-element integer vector
|
||||
class TmpPixel {
|
||||
public:
|
||||
TmpPixel() {
|
||||
}
|
||||
|
||||
TmpPixel( int c0, int c1, int c2, int c3 ) {
|
||||
Set(c0,c1,c2,c3);
|
||||
}
|
||||
|
||||
void Set( int c0, int c1, int c2, int c3 ) {
|
||||
m_comp[0] = c0;
|
||||
m_comp[1] = c1;
|
||||
m_comp[2] = c2;
|
||||
m_comp[3] = c3;
|
||||
}
|
||||
|
||||
TmpPixel operator*( int s ) const {
|
||||
return TmpPixel( m_comp[0]*s, m_comp[1]*s, m_comp[2]*s, m_comp[3]*s );
|
||||
}
|
||||
|
||||
TmpPixel operator+( const TmpPixel &x ) const {
|
||||
return TmpPixel( m_comp[0] + x[0], m_comp[1] + x[1], m_comp[2] + x[2], m_comp[3] + x[3] );
|
||||
}
|
||||
|
||||
// return component i=[0..3] - No range check!
|
||||
int operator[](unsigned i) const {
|
||||
return m_comp[i];
|
||||
}
|
||||
|
||||
private:
|
||||
int m_comp[4];
|
||||
};
|
||||
|
||||
//! this is called whenever one input line is processed completely
|
||||
void NextSourceLine();
|
||||
|
||||
TmpPixel m_hbuf[4]; //! ring buffer for 4 input pixels
|
||||
char *m_memory; //! buffer container
|
||||
Filter *m_hor_filters; //! buffer for horizontal filters (one for each output image column)
|
||||
Filter *m_ver_filters; //! buffer for vertical filters (one for each output image row)
|
||||
TmpPixel *m_buffer; //! buffer contains 4 horizontally filtered input lines, multiplexed
|
||||
unsigned *m_dst_image; //! pointer to destination image
|
||||
unsigned m_dst_stride; //! destination image stride
|
||||
unsigned m_dst_width; //! destination image width
|
||||
unsigned m_dst_height; //! destination image height
|
||||
unsigned m_src_width; //! source image width
|
||||
unsigned m_src_height; //! source image height
|
||||
unsigned m_src_x; //! x position of next source image pixel
|
||||
unsigned m_src_y; //! y position of source image line currently beeing processed
|
||||
unsigned m_dst_x; //! x position of next destination image pixel
|
||||
unsigned m_dst_y; //! x position of next destination image line
|
||||
};
|
||||
|
||||
#endif // _ImageScaler_h
|
||||
|
@ -13,7 +13,6 @@ cXmlParser::cXmlParser(void) {
|
||||
root = NULL;
|
||||
ctxt = NULL;
|
||||
|
||||
xmlInitParser();
|
||||
initGenericErrorDefaultFunc(NULL);
|
||||
xmlSetStructuredErrorFunc(NULL, SkinDesignerXMLErrorHandler);
|
||||
ctxt = xmlNewParserCtxt();
|
||||
@ -22,7 +21,6 @@ cXmlParser::cXmlParser(void) {
|
||||
cXmlParser::~cXmlParser() {
|
||||
DeleteDocument();
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
xmlCleanupParser();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
@ -801,3 +799,11 @@ bool cXmlParser::DebugViewElement(xmlNodePtr node) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cXmlParser::InitLibXML() {
|
||||
xmlInitParser();
|
||||
}
|
||||
|
||||
void cXmlParser::CleanupLibXML() {
|
||||
xmlCleanupParser();
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ public:
|
||||
bool ParsePluginView(string plugName, int templateNumber);
|
||||
bool ParseGlobals(void);
|
||||
void DeleteDocument(void);
|
||||
static void InitLibXML();
|
||||
static void CleanupLibXML();
|
||||
};
|
||||
|
||||
#endif //__XMLPARSER_H
|
||||
#endif //__XMLPARSER_H
|
||||
|
@ -19,7 +19,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
static const char *VERSION = "0.0.4";
|
||||
static const char *VERSION = "0.0.5";
|
||||
static const char *DESCRIPTION = "SkinDesigner";
|
||||
static const char *MAINMENUENTRY = "Skin Designer";
|
||||
|
||||
@ -95,6 +95,7 @@ bool cPluginSkinDesigner::Initialize(void) {
|
||||
}
|
||||
|
||||
bool cPluginSkinDesigner::Start(void) {
|
||||
cXmlParser::InitLibXML();
|
||||
bool trueColorAvailable = true;
|
||||
if (!cOsdProvider::SupportsTrueColor()) {
|
||||
esyslog("skindesigner: No TrueColor OSD found! Using default Skin LCARS!");
|
||||
@ -121,6 +122,7 @@ bool cPluginSkinDesigner::Start(void) {
|
||||
void cPluginSkinDesigner::Stop(void) {
|
||||
delete imgCache;
|
||||
delete fontManager;
|
||||
cXmlParser::CleanupLibXML();
|
||||
}
|
||||
|
||||
void cPluginSkinDesigner::Housekeeping(void) {
|
||||
|
64
skins/metrixhd/themes/default/icons/ico_hd_off.svg
Normal file
64
skins/metrixhd/themes/default/icons/ico_hd_off.svg
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
width="49"
|
||||
height="24"
|
||||
sodipodi:docname="ico_hd_off.svg">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1769"
|
||||
inkscape:window-height="1195"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="6.9532167"
|
||||
inkscape:cx="-12.199961"
|
||||
inkscape:cy="10.824729"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.50196081000000004;opacity:0.4;fill-opacity:1"
|
||||
d="m 3.7627119,1.5762712 5.8474576,0 -1.220339,6.9661017 9.1525425,-0.050847 0.966102,-7.0677966 6.016389,0.014893 -2.965542,21.1376493 -5.993831,0.06883 1.20853,-8.712893 -9.3502922,0.08899 -1.6652543,8.491525 -5.30084738,0.06356 z"
|
||||
id="path3759"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.50196078000000000;opacity:0.4"
|
||||
d="m 28.398305,1.3728813 15.991526,0 C 46.277579,1.243275 49.255354,2.7574438 48.61017,8.0338983 47.616873,15.342244 46.343401,22.177506 41.288136,22.627119 L 24.915254,22.525424 27.20339,8.7966102 l 5.898305,-0.025424 -1.576271,9.5338988 7.677966,0 c 2.596312,0.118399 3.234177,-5.226757 3.457627,-7.90678 0.408058,-3.1501646 0.153706,-4.2577277 -1.420115,-4.3115034 L 27.61017,6.152542 z"
|
||||
id="path3767"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
64
skins/metrixhd/themes/default/icons/ico_hd_on.svg
Normal file
64
skins/metrixhd/themes/default/icons/ico_hd_on.svg
Normal file
@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
width="49"
|
||||
height="24"
|
||||
sodipodi:docname="ico_hd_on.svg">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1769"
|
||||
inkscape:window-height="1195"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="6.9532167"
|
||||
inkscape:cx="19.799617"
|
||||
inkscape:cy="10.824729"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
style="fill:#ffffff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.50196081000000004;opacity:1;fill-opacity:1"
|
||||
d="m 3.7627119,1.5762712 5.8474576,0 -1.220339,6.9661017 9.1525425,-0.050847 0.966102,-7.0677966 6.016389,0.014893 -2.965542,21.1376493 -5.993831,0.06883 1.20853,-8.712893 -9.3502922,0.08899 -1.6652543,8.491525 -5.30084738,0.06356 z"
|
||||
id="path3759"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.50196078000000000"
|
||||
d="m 28.398305,1.3728813 15.991526,0 C 46.277579,1.243275 49.255354,2.7574438 48.61017,8.0338983 47.616873,15.342244 46.343401,22.177506 41.288136,22.627119 L 24.915254,22.525424 27.20339,8.7966102 l 5.898305,-0.025424 -1.576271,9.5338988 7.677966,0 c 2.596312,0.118399 3.234177,-5.226757 3.457627,-7.90678 0.408058,-3.1501646 0.153706,-4.2577277 -1.420115,-4.3115034 L 27.61017,6.152542 z"
|
||||
id="path3767"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
58
skins/metrixhd/themes/default/icons/ico_widescreen_off.svg
Normal file
58
skins/metrixhd/themes/default/icons/ico_widescreen_off.svg
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
width="43"
|
||||
height="23"
|
||||
sodipodi:docname="ico_widescreen_off.svg">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2048"
|
||||
inkscape:window-height="1481"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="-4.8693805"
|
||||
inkscape:cy="19.882154"
|
||||
inkscape:window-x="-2"
|
||||
inkscape:window-y="-3"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
id="path3834"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.10000000000000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;opacity:0.4"
|
||||
d="M 26.31204,9.2549017 29.307138,8.946193 c 1.930719,-0.2361949 1.627499,7.01011 -0.03235,6.862976 L 26.236601,15.553807 z M 0,0 0,23 c 15.021262,-4.846203 26.918346,-4.787057 43,0 L 43,0 C 26.964088,7.5152881 15.064204,7.6359799 0,0 z m 41.5625,2.59375 0,2.90625 -3.96875,1.46875 0,3.6875 3.40625,-0.0625 0,2.4375 -3.40625,0 0,3.65625 4.15625,1.125 0,2.90625 -6.71875,-1.6875 0,-13.875 z M 1.90625,2.8125 4.59375,4.03125 6.375,14.5625 8.03125,5.3125 10.625,6.125 l 2.34375,8.5 1.5,-7.65625 L 17.0625,7.3125 14.71875,17.75 11.34375,18.21875 9.5,10.3125 l -1.53125,8.53125 -3.5,0.8125 z M 30,6.75 c 4.450278,0.058184 3.725392,11.914384 -0.5625,11.3125 l -5.6875,-0.53125 0.0625,-10.0625 5.75,-0.6875 C 29.716868,6.7577574 29.856443,6.7481231 30,6.75 z m -11.4375,0.71875 2.625,0.09375 0,9.84375 -2.625,0.09375 z"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccsccccsccccc" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
58
skins/metrixhd/themes/default/icons/ico_widescreen_on.svg
Normal file
58
skins/metrixhd/themes/default/icons/ico_widescreen_on.svg
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
width="43"
|
||||
height="23"
|
||||
sodipodi:docname="ico_widescreen_on.png">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2048"
|
||||
inkscape:window-height="1481"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="16"
|
||||
inkscape:cx="9.0368695"
|
||||
inkscape:cy="19.882154"
|
||||
inkscape:window-x="-2"
|
||||
inkscape:window-y="-3"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
id="path3834"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.10000000000000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 26.31204,9.2549017 29.307138,8.946193 c 1.930719,-0.2361949 1.627499,7.01011 -0.03235,6.862976 L 26.236601,15.553807 z M 0,0 0,23 c 15.021262,-4.846203 26.918346,-4.787057 43,0 L 43,0 C 26.964088,7.5152881 15.064204,7.6359799 0,0 z m 41.5625,2.59375 0,2.90625 -3.96875,1.46875 0,3.6875 3.40625,-0.0625 0,2.4375 -3.40625,0 0,3.65625 4.15625,1.125 0,2.90625 -6.71875,-1.6875 0,-13.875 z M 1.90625,2.8125 4.59375,4.03125 6.375,14.5625 8.03125,5.3125 10.625,6.125 l 2.34375,8.5 1.5,-7.65625 L 17.0625,7.3125 14.71875,17.75 11.34375,18.21875 9.5,10.3125 l -1.53125,8.53125 -3.5,0.8125 z M 30,6.75 c 4.450278,0.058184 3.725392,11.914384 -0.5625,11.3125 l -5.6875,-0.53125 0.0625,-10.0625 5.75,-0.6875 C 29.716868,6.7577574 29.856443,6.7481231 30,6.75 z m -11.4375,0.71875 2.625,0.09375 0,9.84375 -2.625,0.09375 z"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccsccccsccccc" />
|
||||
</svg>
|
After Width: | Height: | Size: 2.6 KiB |
@ -711,8 +711,10 @@ void cView::DoDrawImage(int num, cTemplateFunction *func, int x0, int y0) {
|
||||
break; }
|
||||
case itImage: {
|
||||
cImageLoader imgLoader;
|
||||
if (imgLoader.LoadImage(path.c_str(), width, height)) {
|
||||
DrawImage(num, pos, imgLoader.GetImage());
|
||||
if (imgLoader.LoadImage(path.c_str())) {
|
||||
cImage *image = imgLoader.CreateImage(width, height);
|
||||
DrawImage(num, pos, *image);
|
||||
delete(image);
|
||||
}
|
||||
break; }
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user