mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
245 lines
6.3 KiB
C++
245 lines
6.3 KiB
C++
|
//
|
||
|
// TextureHandler.cc for pekwm
|
||
|
// Copyright © 2004-2009 Claes Nästén <me@pekdon.net>
|
||
|
//
|
||
|
// This program is licensed under the GNU GPL.
|
||
|
// See the LICENSE file for more information.
|
||
|
//
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include "config.h"
|
||
|
#endif // HAVE_CONFIG_H
|
||
|
|
||
|
#include "PTexture.hh"
|
||
|
#include "TextureHandler.hh"
|
||
|
#include "PScreen.hh"
|
||
|
#include "PTexturePlain.hh"
|
||
|
#include "Util.hh"
|
||
|
|
||
|
#include <vector>
|
||
|
#include <iostream>
|
||
|
|
||
|
using std::list;
|
||
|
using std::vector;
|
||
|
using std::map;
|
||
|
using std::string;
|
||
|
using std::cerr;
|
||
|
using std::endl;
|
||
|
|
||
|
TextureHandler* TextureHandler::_instance = 0;
|
||
|
map<ParseUtil::Entry, PTexture::Type> TextureHandler::_parse_map = map<ParseUtil::Entry, PTexture::Type>();
|
||
|
|
||
|
const int TextureHandler::LENGTH_MIN = 5;
|
||
|
|
||
|
//! @brief TextureHandler constructor
|
||
|
TextureHandler::TextureHandler(void)
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
if (_instance) {
|
||
|
cerr << __FILE__ << "@" << __LINE__ << ": "
|
||
|
<< "TextureHandler(" << this << ")::TextureHandler()"
|
||
|
<< " *** _instance already set: " << _instance << endl;
|
||
|
}
|
||
|
#endif // DEBUG
|
||
|
_instance = this;
|
||
|
|
||
|
// fill parse map with values
|
||
|
_parse_map[""] = PTexture::TYPE_NO;
|
||
|
_parse_map["SOLID"] = PTexture::TYPE_SOLID;
|
||
|
_parse_map["SOLIDRAISED"] = PTexture::TYPE_SOLID_RAISED;
|
||
|
_parse_map["IMAGE"] = PTexture::TYPE_IMAGE;
|
||
|
_parse_map["EMPTY"] = PTexture::TYPE_EMPTY;
|
||
|
}
|
||
|
|
||
|
//! @brief TextureHandler destructor
|
||
|
TextureHandler::~TextureHandler(void)
|
||
|
{
|
||
|
_instance = 0;
|
||
|
}
|
||
|
|
||
|
//! @brief Gets or creates a PTexture
|
||
|
PTexture*
|
||
|
TextureHandler::getTexture(const std::string &texture)
|
||
|
{
|
||
|
// check for already existing entry
|
||
|
list<TextureHandler::Entry*>::iterator it(_texture_list.begin());
|
||
|
|
||
|
for (; it != _texture_list.end(); ++it) {
|
||
|
if (*(*it) == texture) {
|
||
|
(*it)->incRef();
|
||
|
return (*it)->getTexture();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// parse texture
|
||
|
PTexture *ptexture = parse(texture);
|
||
|
|
||
|
if (ptexture) {
|
||
|
// create new entry
|
||
|
TextureHandler::Entry *entry = new TextureHandler::Entry(texture, ptexture);
|
||
|
entry->incRef();
|
||
|
|
||
|
_texture_list.push_back(entry);
|
||
|
}
|
||
|
|
||
|
return ptexture;
|
||
|
}
|
||
|
|
||
|
//! @brief Add/Increment reference cont for texture.
|
||
|
//! @return Pointer to texture referenced.
|
||
|
PTexture*
|
||
|
TextureHandler::referenceTexture(PTexture *texture)
|
||
|
{
|
||
|
// Check for already existing entry
|
||
|
list<TextureHandler::Entry*>::iterator it(_texture_list.begin());
|
||
|
|
||
|
for (; it != _texture_list.end(); ++it) {
|
||
|
if ((*it)->getTexture() == texture) {
|
||
|
(*it)->incRef();
|
||
|
return texture;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create new entry
|
||
|
TextureHandler::Entry *entry = new TextureHandler::Entry("", texture);
|
||
|
entry->incRef();
|
||
|
|
||
|
_texture_list.push_back(entry);
|
||
|
|
||
|
return texture;
|
||
|
}
|
||
|
|
||
|
//! @brief Returns a texture
|
||
|
void
|
||
|
TextureHandler::returnTexture(PTexture *texture)
|
||
|
{
|
||
|
bool found = false;
|
||
|
|
||
|
list<TextureHandler::Entry*>::iterator it(_texture_list.begin());
|
||
|
for (; it != _texture_list.end(); ++it) {
|
||
|
if ((*it)->getTexture() == texture) {
|
||
|
found = true;
|
||
|
|
||
|
(*it)->decRef();
|
||
|
if ((*it)->getRef() == 0) {
|
||
|
delete *it;
|
||
|
_texture_list.erase(it);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (! found) {
|
||
|
delete texture;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//! @brief Parses the string, and creates a texture
|
||
|
PTexture*
|
||
|
TextureHandler::parse(const std::string &texture)
|
||
|
{
|
||
|
PTexture *ptexture = 0;
|
||
|
vector<string> tok;
|
||
|
|
||
|
PTexture::Type type;
|
||
|
if (Util::splitString(texture, tok, " \t")) {
|
||
|
type = ParseUtil::getValue<PTexture::Type>(tok[0], _parse_map);
|
||
|
} else {
|
||
|
type = ParseUtil::getValue<PTexture::Type>(texture, _parse_map);
|
||
|
}
|
||
|
|
||
|
// need at least type and parameter, except for EMPTY type
|
||
|
if (tok.size() > 1) {
|
||
|
tok.erase(tok.begin()); // remove type
|
||
|
switch (type) {
|
||
|
case PTexture::TYPE_SOLID:
|
||
|
ptexture = parseSolid(tok);
|
||
|
break;
|
||
|
case PTexture::TYPE_SOLID_RAISED:
|
||
|
ptexture = parseSolidRaised(tok);
|
||
|
break;
|
||
|
case PTexture::TYPE_IMAGE:
|
||
|
ptexture = new PTextureImage(PScreen::instance()->getDpy(), tok[1]);
|
||
|
break;
|
||
|
case PTexture::TYPE_NO:
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// If it fails to load, set clean resources and set it to 0.
|
||
|
if (ptexture && ! ptexture->isOk()) {
|
||
|
delete ptexture;
|
||
|
ptexture = 0;
|
||
|
}
|
||
|
|
||
|
} else if (type == PTexture::TYPE_EMPTY) {
|
||
|
ptexture = new PTexture(PScreen::instance()->getDpy());
|
||
|
}
|
||
|
|
||
|
return ptexture;
|
||
|
}
|
||
|
|
||
|
//! @brief Parse and create PTextureSolid
|
||
|
PTexture*
|
||
|
TextureHandler::parseSolid(std::vector<std::string> &tok)
|
||
|
{
|
||
|
if (tok.size() < 1) {
|
||
|
cerr << "*** WARNING: not enough parameters to texture Solid" << endl;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
PTextureSolid *tex = new PTextureSolid(PScreen::instance()->getDpy(), tok[0]); tok.erase(tok.begin());
|
||
|
|
||
|
// check if we have size
|
||
|
if (tok.size() == 1) {
|
||
|
parseSize(tex, tok[0]);
|
||
|
}
|
||
|
|
||
|
return tex;
|
||
|
}
|
||
|
|
||
|
//! @brief Parse and create PTextureSolidRaised
|
||
|
PTexture*
|
||
|
TextureHandler::parseSolidRaised(std::vector<std::string> &tok)
|
||
|
{
|
||
|
if (tok.size() < 3) {
|
||
|
cerr << "*** WARNING: not enough parameters to texture SolidRaised" << endl;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
PTextureSolidRaised *tex = new PTextureSolidRaised(PScreen::instance()->getDpy(),
|
||
|
tok[0], tok[1], tok[2]);
|
||
|
tok.erase(tok.begin(), tok.begin() + 3);
|
||
|
|
||
|
// Check if we have line width and offset.
|
||
|
if (tok.size() > 2) {
|
||
|
tex->setLineWidth(strtol(tok[0].c_str(), 0, 10));
|
||
|
tex->setLineOff(strtol(tok[1].c_str(), 0, 10));
|
||
|
tok.erase(tok.begin(), tok.begin() + 2);
|
||
|
}
|
||
|
// Check if have side draw specified.
|
||
|
if (tok.size() > 4) {
|
||
|
tex->setDraw(Util::isTrue(tok[0]), Util::isTrue(tok[1]),
|
||
|
Util::isTrue(tok[2]), Util::isTrue(tok[3]));
|
||
|
tok.erase(tok.begin(), tok.begin() + 4);
|
||
|
}
|
||
|
|
||
|
// Check if we have size
|
||
|
if (tok.size() == 1) {
|
||
|
parseSize(tex, tok[0]);
|
||
|
}
|
||
|
|
||
|
return tex;
|
||
|
}
|
||
|
|
||
|
//! @brief Parses size parameter, i.e. 10x20
|
||
|
void
|
||
|
TextureHandler::parseSize(PTexture *tex, const std::string &size)
|
||
|
{
|
||
|
vector<string> tok;
|
||
|
if ((Util::splitString(size, tok, "x", 2, true)) == 2) {
|
||
|
tex->setWidth(strtol(tok[0].c_str(), 0, 10));
|
||
|
tex->setHeight(strtol(tok[1].c_str(), 0, 10));
|
||
|
}
|
||
|
}
|