#include "imgGlyph.h"
imgGlyph::imgGlyph()
{
_touched = 0;
_glyphPtr = NULL;
_width = _height = 0;
_curX = _curY = 0;
_error = 0;
_errno = 0;
}
imgGlyph::~imgGlyph()
{
deleteGlyphPtr();
if (_error > 0) {
delete _error;
}
}
void
imgGlyph::setError(const char *str, short errno)
{
if (_error > 0) {
printf("WARNING: imgGlyph::setError() called twice (%s,%s)\n",_error,str);
delete _error;
}
_error = new char[strlen(str)+1];
strcpy(_error,str);
_errno = errno;
}
void
imgGlyph::printError()
{
printf("%s\n",getErrorString());
}
char *
imgGlyph::getErrorString()
{
static char str[2048];
sprintf(str,"imgArray: %.2007s (%d)",_error, _errno);
return str;
}
short
imgGlyph::getStatus()
{
return _errno;
}
int
imgGlyph::getWidth()
{
checkTouched();
return _width;
}
int
imgGlyph::getHeight()
{
checkTouched();
return _height;
}
int
imgGlyph::getCurX()
{
checkTouched();
return _curX;
}
int
imgGlyph::getCurY()
{
checkTouched();
return _curY;
}
short
imgGlyph::addGlyph(Glyph *glyph)
{
if (glyph == NULL) {
setError("No glyh to add (NULL)",2);
return -1;
}
_glyphList.push_back(glyph);
_touched = 1;
return 1;
}
imgProcess *
imgGlyph::createImg()
{
checkTouched();// update BBX
int count = _glyphList.size();
if (count == 0) {
setError("No glyph to create image",3);
return NULL;
}
if (_width <= 0 || _height <= 0) {
setError("Width or Height equal zero",4);
return NULL;
}
imgProcess *tmpImage = new imgProcess(_width, _height, 4);
if (tmpImage->getStatus() != ilOKAY) {
setError(tmpImage->getErrorString(),5);
delete tmpImage;
return NULL;
}
int destX, destY;
int cur_x = _curX;
int cur_y = _curY;
int lastX=0;
for (int i =0; i < count; i++) {
int offX = 0;
destX = _glyphPtr[i]->getBBXXO() + cur_x;
destY = _height - (_glyphPtr[i]->getBBXYO() + cur_y + _glyphPtr[i]->getBBXH());
if (lastX < destX) offX = destX - lastX;
for (int line=0; line < _height; line++) {
int Y = destY + line;
for (int bits= -offX; bits < _glyphPtr[i]->getBBXW(); bits++) {
int X = destX + bits;
if (line >= _glyphPtr[i]->getBBXH() ||
bits < 0) {
//get rid of memory thrash
tmpImage->setPixel(X, Y,
_glyphPtr[i]->getBackgroundR(),
_glyphPtr[i]->getBackgroundG(),
_glyphPtr[i]->getBackgroundB(),
_glyphPtr[i]->getBackgroundA());
} else {
int srcBit, srcByte;
srcByte = bits >> 3;
srcBit = 7 - (bits - (srcByte * 8));
const char *bitmap = _glyphPtr[i]->getBitmap();
if (bitmap[line* _glyphPtr[i]->getStride() + srcByte] &(1<<srcBit)) {
tmpImage->setPixel(X, Y,
_glyphPtr[i]->getForegroundR(),
_glyphPtr[i]->getForegroundG(),
_glyphPtr[i]->getForegroundB(),
_glyphPtr[i]->getForegroundA());
} else {
tmpImage->setPixel(X, Y,
_glyphPtr[i]->getBackgroundR(),
_glyphPtr[i]->getBackgroundG(),
_glyphPtr[i]->getBackgroundB(),
_glyphPtr[i]->getBackgroundA());
}
}
}
}
cur_x += _glyphPtr[i]->getOffsetToNextX();
cur_y += _glyphPtr[i]->getOffsetToNextY();
lastX = destX + _glyphPtr[i]->getBBXW();
}
if (tmpImage->getStatus() != ilOKAY) {
setError(tmpImage->getErrorString(),6);
delete tmpImage;
return NULL;
}
return tmpImage;
}
short
imgGlyph::blittInImage(imgProcess *image, int x, int y)
{
checkTouched(); // update BBX
int count = _glyphList.size();
if (count == 0) {
setError("No glyph to blitt",8);
return -1;
}
if (x >= image->getWidth() ||
y >= image->getHeight() ||
x+ _width < 0 ||
y+ _height < 0) {
setError("Blitting position is not in image",9);
return -1;
}
int destX, destY;
int drawFore, drawBack;
int cur_x = _curX;
int cur_y = _curY;
for (int i =0; i < count; i++) {
if (_glyphPtr[i]->getForegroundA() == 255) {
drawFore = 0;
} else {
drawFore = 1;
}
if (_glyphPtr[i]->getBackgroundA() == 255) {
drawBack = 0;
} else {
drawBack = 1;
}
destX = _glyphPtr[i]->getBBXXO() + cur_x + x;
destY = _height - (_glyphPtr[i]->getBBXYO() + cur_y + _glyphPtr[i]->getBBXH()) + y;
for (int line=0; line < _glyphPtr[i]->getBBXH(); line++) {
int Y = destY + line;
if (Y < 0 || Y >= image->getHeight()) continue;
for (int bits=0; bits < _glyphPtr[i]->getBBXW(); bits++) {
int X = destX + bits;
if (X < 0 || X >= image->getWidth()) continue;
int srcBit, srcByte;
srcByte = bits >> 3;
srcBit = 7 - (bits - (srcByte * 8));
const char *bitmap = _glyphPtr[i]->getBitmap();
if (bitmap[ line * _glyphPtr[i]->getStride() + srcByte] &(1<<srcBit)) {
if (drawFore)
if (image->setPixel(X, Y,
_glyphPtr[i]->getForegroundR(),
_glyphPtr[i]->getForegroundG(),
_glyphPtr[i]->getForegroundB(),
_glyphPtr[i]->getForegroundA()) == -1) {
setError("set pixel foreground failed",10);
return -1;
}
} else {
if (drawBack)
if (image->setPixel(X, Y,
_glyphPtr[i]->getBackgroundR(),
_glyphPtr[i]->getBackgroundG(),
_glyphPtr[i]->getBackgroundB(),
_glyphPtr[i]->getBackgroundA()) == -1) {
setError("set pixel background failed",11);
return -1;
}
}
}
}
cur_x += _glyphPtr[i]->getOffsetToNextX();
cur_y += _glyphPtr[i]->getOffsetToNextY();
}
return 1;
}
void
imgGlyph::checkTouched()
{
int count = _glyphList.size();
if (!_touched || !count) return;
int xmin, xmax;
int ymin, ymax;
_curX = _curY = 0;
deleteGlyphPtr();
_glyphPtr = new Glyph*[count];
for (int i=0; i < count; i++) {
_glyphPtr[i] = _glyphList[i];
}
Glyph::calcBBX(_glyphPtr, count, _curX, _curY, xmax, ymax, xmin, ymin);
// initialize new glyph
_width = xmax - xmin;
_height = ymax - ymin;
_touched = 0;
}
void
imgGlyph::deleteGlyphPtr()
{
if (_glyphPtr == NULL) return;
delete[] _glyphPtr;
_glyphPtr = NULL;
}