#include "Schrift.h"
#include "Punkt.h"
#include "Farbe.h"
#include "Bild.h"
#include "Text.h"
#include <Windows.h>

using namespace Framework;

// Inhalt der Buchstabe Klasse aus Schrift.h
// Konstruktor 
Buchstabe::Buchstabe()
{
	größe = new Punkt( 0, 0 );
	pos = new Punkt( 0, 0 );
	alpha = 0;
	f = new Farbe();
	schriftGröße = 0;
	drawSg = 0;
	ref = 1;
}

// Destruktor 
Buchstabe::~Buchstabe()
{
	größe->release();
	pos->release();
	f->release();
	if( alpha )
		delete []alpha;
}

// nicht constant 
void Buchstabe::NeuBuchstabe( Punkt *größe ) // Initialisierung
{
	if( !größe->x || !größe->y )
		MessageBox( NULL, "ERROR", "Es kann kein neuer Buchstabe erzeugt werden.", MB_ICONERROR );
	this->größe->setP( größe->getX(), größe->getY() );
	if( alpha )
		delete []alpha;
	alpha = new unsigned char[ größe->getX() * größe->getY() ];
	ZeroMemory( alpha,  größe->getX() * größe->getY() );
	größe->release();
}

void Buchstabe::setPixel( Punkt *pos, unsigned char alpha ) // setzt den alphawert des Pixels
{
	this->alpha[ pos->getX() + pos->getY() * größe->getX() ]  = alpha;
	pos->release();
}

void Buchstabe::setPixel( int x, int y, unsigned char alpha )
{
	this->alpha[ x + y * größe->getX() ] = alpha;
}

void Buchstabe::setPixel( int i, unsigned char alpha )
{
	this->alpha[ i ] = alpha;
}

void Buchstabe::setPosition( Punkt *pos ) // setzt die Buchstabenposition
{
	this->pos->setP( pos->getX(), pos->getY() );
	pos->release();
}

void Buchstabe::setPosition( int x, int y )
{
	this->pos->setP( x, y );
}

void Buchstabe::setFarbe( int fc ) // setzt die Buchstabenfarbe
{
	f->setFarbe( fc );
}

void Buchstabe::setFarbe( Farbe *f )
{
	this->f->setFarbe( f->getFarbe() );
	f->release();
}

void Buchstabe::setSchriftGröße( int sg ) // setzt die Schriftgröße des Buchstaben
{
	schriftGröße = sg;
}

void Buchstabe::setDrawSchriftGröße( int dsg ) // setzt die Zeichengröße des Buchstaben
{
	drawSg = dsg;
}

// constant 
Farbe *Buchstabe::getFarbe() const // gibt die Buchstabenfarbe zurück
{
	return f->getThis();
}

Punkt *Buchstabe::getGröße() const // gibt die Buchstabenbildgröße zurück
{
	return größe->getThis();
}

int Buchstabe::getBreite() const // Buchstabenbreite
{
	return (int)( ( (double)größe->getX() / (double)schriftGröße ) * (double)drawSg + 0.5 );
}

int Buchstabe::getHöhe() const // Buchstabenhöhe
{
	return (int)( ( (double)größe->getY() / (double)schriftGröße ) *(double)drawSg + 0.5 );
}

unsigned char *Buchstabe::getBuff() const // gibt den Alphabuffer zurück
{
	return alpha;
}

void Buchstabe::render( Bild *rObj ) const // Zeichnet nach rObj
{
	if( alpha && f->getA() )
	{
		int rObjBr = rObj->getDOBX(), rObjHö = rObj->getDOHY();
		int rObjX = rObj->getDOX(), rObjY = rObj->getDOY();
		int xp = pos->getX(), yp = pos->getY();
		int xs = xp < rObjX ? ( rObjX - xp ) : 0, ys = yp < rObjY ? ( rObjY - yp ) : 0;
		int b = größe->x, h = größe->y;
		int fc = f->getFarbe();
		unsigned char a2 = ( 255 - ( fc >> 24 ) );
		fc &= 0x00FFFFFF;
		if( schriftGröße == drawSg )
		{
			if( xp >= rObjBr || yp >= rObjHö || xp + b < rObjX || yp + h < rObjY )
				return;
			b = ( xp + b ) > rObjBr ? ( rObjBr - xp ) : b;
			h = ( yp + h ) > rObjHö ? ( rObjHö - yp ) : h;
			if( !a2 )
			{
				for( int xx = xs; xx < b; xx++ )
					for( int yy = ys; yy < h; yy++ )
						rObj->alphaPixel( xp + xx , yp + yy, fc | ( alpha[ xx + yy * größe->x ] << 24 ) );
			}
			else
			{
				int a;
				for( int xx = xs; xx < b; xx++ )
				{
					for( int yy = ys; yy < h; yy++ )
					{
						a = alpha[ xx + yy * größe->x ];
						a -= a2;
						if( a < 0 )
							a = 0;
						rObj->alphaPixel( xp + xx , yp + yy, fc | ( a << 24 ) );
					}
				}
			}
		}
		else
		{
			double xoff = (double)schriftGröße / (double)drawSg,
				   yoff = (double)schriftGröße / (double)drawSg;
			double x = xs * xoff, y = ys * yoff;
			int maxX = getBreite(), maxY = getHöhe();
			maxX = ( xp + maxX ) >= rObjBr ? ( rObjBr - xp ) : maxX;
			maxY = ( yp + maxY ) >= rObjHö ? ( rObjHö - yp ) : maxY;
			for( int dx = xs; dx < maxX; dx++ )
			{
				for( int dy = ys; dy < maxY; dy++ )
				{
					rObj->alphaPixel( dx + pos->x, dy + pos->y, fc | ( alpha[ (int)( x ) + (int)( y ) * b ] << 24 ) );
					y += yoff;
				}
				y = 0;
				x += xoff;
			}
		}
	}
}

// Reference Counting 
Buchstabe *Buchstabe::getThis()
{
	ref++;
	return this;
}

Buchstabe *Buchstabe::release()
{
	ref--;
	if( ref == 0 )
		delete this;
	return 0;
}

// Inhalt der Alphabet Klasse aus Schrift.h
// Konstruktor 
Alphabet::Alphabet()
{
	zeichen = new Buchstabe*[ 256 ];
	for( int i = 0; i < 256; i++ )
		zeichen[ i ] = 0;
	ref = 1;
	zeilenAbstand = 5;
	zeilenHöhe = 0;
	drawSchriftGröße = 12;
	schriftGröße = 12;
	f = new Farbe();
	pos = new Punkt();
}

// Destruktor 
Alphabet::~Alphabet()
{
	for( int i = 0; i < 256; i++ )
		if( zeichen[ i ] )
			zeichen[ i ]->release();
	delete []zeichen;
	f->release();
	pos->release();
}

// nicht constant 
void Alphabet::NeuAlphabet() // Initialisierung 
{
	for( int i = 0; i < 256; i++ )
		if( zeichen[ i ] )
			zeichen[ i ]->release();
	for( int i = 0; i < 256; i++ )
		zeichen[ i ] = 0;
	zeilenHöhe = 0;
}

void Alphabet::setBuchstabe( unsigned char i, Buchstabe *buchstabe ) // setzt einen Buchstaben
{
	if( zeichen[ i ] )
		zeichen[ i ]->release();
	zeichen[ i ] = buchstabe;
	if( zeichen[ i ] )
	{
		zeichen[ i ]->setSchriftGröße( schriftGröße );
		zeichen[ i ]->setDrawSchriftGröße( drawSchriftGröße );
		zeichen[ i ]->setFarbe( f->getFarbe() );
	}
	zeilenHöhe = getZeilenHöhe();
}

void Alphabet::setSchriftgröße( int gr ) // setzt die Schriftgröße
{
	schriftGröße = gr;
	for( int i = 0; i < 256; i++ )
		if( zeichen[ i ] )
			zeichen[ i ]->setSchriftGröße( gr );
}

void Alphabet::setDrawSchriftgröße( int gr ) // setzt die Zeichengröße
{
	drawSchriftGröße = gr;
	for( int i = 0; i < 256; i++ )
		if( zeichen[ i ] )
			zeichen[ i ]->setDrawSchriftGröße( gr );
}

void Alphabet::setZeilenAbstand( int za ) // setzt die Zeilenhöhe( Zeilenabstand )
{
	zeilenAbstand = za;
}

void Alphabet::setDrawPosition( Punkt *pos ) // setzt die Draw Position
{
	this->pos->setP( pos->getX(), pos->getY() );
	pos->release();
}

void Alphabet::setDrawPosition( int x, int y )
{
	this->pos->setP( x, y );
}

void Alphabet::setFarbe( Farbe *f ) // setzt die Schriftfarbe
{
	int ff = f->getFarbe();
	this->f->setFarbe( ff );
	f->release();
	for( int i = 0; i < 256; i++ )
		if( zeichen[ i ] )
			zeichen[ i ]->setFarbe( ff );
}

void Alphabet::setFarbe( int fc )
{
	f->setFarbe( fc );
	for( int i = 0; i < 256; i++ )
		if( zeichen[ i ] )
			zeichen[ i ]->setFarbe( fc );
}

// constant 
Buchstabe *Alphabet::getBuchstabe( unsigned char i ) const // gibt einen Buchstaben zurück
{
	if( zeichen[ i ] )
		return zeichen[ i ]->getThis();
	return 0;
}

int Alphabet::getSchriftgröße() const // gibt die Schriftgröße zurück
{
	return schriftGröße;
}

int Alphabet::getDrawSchriftGröße() const // gibt die Zeichengröße zurück
{
	return drawSchriftGröße;
}

int Alphabet::getZeilenAbstand() const // gibt den Zeilenabstand zurück
{
	return zeilenAbstand;
}

int Alphabet::getZeilenHöhe() const // gibt die Höhe des höchsten Zeichens zurück
{
	int ret = 0;
	for( int i = 0; i < 256; i++ )
	{
		if( zeichen[ i ] != 0 )
			if( zeichen[ i ]->getHöhe() > ret )
				ret = zeichen[ i ]->getHöhe();
	}
	return ret;
}

Punkt *Alphabet::getPosition() const // gibt die DrawPosition zurück
{
	return pos->getThis();
}

Farbe *Alphabet::getFarbe() const // gibt die Farbe zurück
{
	return f->getThis();
}

int Alphabet::getTextBreite( Text *txt ) const // gibt die Breite des Textes zurück
{
	int ret = 0;
	int län = txt->getLänge();
	char *buff = txt->getText();
	unsigned char c = 0;
	int tmp = 0;
	for( int i = 0; i < län; i++ )
	{
		c = (unsigned char)buff[ i ];
		if( buff[ i ] == '\n' )
		{
			if( tmp > ret )
				ret = tmp;
			tmp = 0;
		}
		else if( buff[ i ] == '\r' )
		{
			i += 10;
			continue;
		}
		else if( buff[ i ] == ' ' )
			tmp += drawSchriftGröße / 2;
		else if( zeichen[ c ] )
			tmp += zeichen[ c ]->getBreite();
	}
	if( tmp > ret )
		ret = tmp;
	txt->release();
	return ret;
}

int Alphabet::getTextHöhe( Text *txt ) const // gibt die Höhe des Textes zurück
{
	int hö = getZeilenHöhe();
	int ret = hö + ( ( hö + zeilenAbstand ) * txt->anzahlVon( '\n' ) );
	txt->release();
	return ret;
}

int Alphabet::textPos( Text *txt, int mausX, int mausY ) const // gibt den Buchstaben zurück, auf den die Maus zeigt
{
	char *buffer = txt->getText();
	int län = txt->getLänge();
	int tx = 0;
	int ty = 0;
	int sh = getZeilenHöhe();
	if( mausX < 0 || mausY < 0 )
	{
		txt->release();
		return -1;
	}
	for( int i = 0; i < län; i++ )
	{
		if( buffer[ i ] == '\n' )
		{
			ty += sh + zeilenAbstand / 2;
			tx = 0;
			if( mausY < ty )
			{
				txt->release();
				return i;
			}
		}
		if( buffer[ i ] == ' ' )
		{
			tx += drawSchriftGröße / 2;
		}
		if( zeichen[ (unsigned char)buffer[ i ] ] )
			tx += zeichen[ (unsigned char)buffer[ i ] ]->getBreite();
		int txpl = 0;
		if( zeichen[ (unsigned char)buffer[ i + 1 ] ] )
			txpl = zeichen[ (unsigned char)buffer[ i + 1 ] ]->getBreite() / 2;
		if( mausX < tx - txpl && mausY < ty + sh + zeilenAbstand / 2 )
		{
			txt->release();
			return i;
		}
	}
	txt->release();
	if( mausY < ty + sh + zeilenAbstand / 2 )
		return län;
	return -1;
}

void Alphabet::render( Text *txt, Bild *renderObj ) const // Zeichnet txt nach renderObj
{
	int rObjBr = renderObj->getBreite();
	int rObjHö = renderObj->getHöhe();
	int xp = pos->getX();
	int yp = pos->getY();
	int zh = getZeilenHöhe();
	if( yp + zh < 0 ||xp >= rObjBr || yp >= rObjHö )
		return;
	unsigned char *text = (unsigned char*)txt->getText();
	int län = txt->getLänge();
	for( int i = 0; i < län; i++ )
	{
		if( text[ i ] == ' ' )
		{
			xp += drawSchriftGröße / 2;
			continue;
		}
		if( text[ i ] == '\n' )
		{
			yp += zh + zeilenAbstand;
			xp = pos->getX();
			continue;
		}
		if( text[ i ] == '\r' && län - i >= 11 )
		{
			i += 3;
			Text *hex1 = txt->getTeilText( i, i + 6 );
			Text *hex2 = txt->getTeilText( i + 6, i + 8 );
			unsigned int fc = ( TextZuInt( hex1->getText(), 16 ) << 8 ) |
							  ( TextZuInt( hex2->getText(), 16 ) );
			hex1->release();
			hex2->release();
			for( int i2 = 0; i2 < 256; i2++ )
				if( zeichen[ i2 ] )
					zeichen[ i2 ]->setFarbe( fc );
			i += 7;
			continue;
		}
		if( zeichen[ text[ i ] ] )
		{
			if( xp >= rObjBr )
				continue;
			zeichen[ text[ i ] ]->setPosition( xp, yp );
			zeichen[ text[ i ] ]->render( renderObj );
			xp += zeichen[ text[ i ] ]->getBreite();
		}
	}
	txt->release();
}

void Alphabet::render( int xOff, int yOff, int bOff, int hOff, Text *txt, Bild *renderObj ) const
{
	renderObj->setDrawOptions( xOff, yOff, xOff + bOff, yOff + hOff );
	int rObjBr = xOff + bOff;
	int rObjHö = yOff + hOff;
	int xp = pos->getX() + xOff;
	int yp = pos->getY() + yOff;
	int zh = getZeilenHöhe();
	if( yp + zh < yOff ||xp >= rObjBr || yp >= rObjHö )
		return;
	unsigned char *text = (unsigned char*)txt->getText();
	int län = txt->getLänge();
	for( int i = 0; i < län; i++ )
	{
		if( text[ i ] == ' ' )
		{
			xp += drawSchriftGröße / 2;
			continue;
		}
		if( text[ i ] == '\n' )
		{
			yp += zh + zeilenAbstand;
			xp = pos->getX();
			continue;
		}
		if( text[ i ] == '\r' && län - i >= 11 )
		{
			i += 3;
			Text *hex1 = txt->getTeilText( i, i + 6 );
			Text *hex2 = txt->getTeilText( i + 6, i + 8 );
			unsigned int fc = ( TextZuInt( hex1->getText(), 16 ) << 8 ) |
							  ( TextZuInt( hex2->getText(), 16 ) );
			hex1->release();
			hex2->release();
			for( int i2 = 0; i2 < 256; i2++ )
				if( zeichen[ i2 ] )
					zeichen[ i2 ]->setFarbe( fc );
			i += 7;
			continue;
		}
		if( zeichen[ text[ i ] ] )
		{
			if( xp >= rObjBr )
				continue;
			zeichen[ text[ i ] ]->setPosition( xp, yp );
			zeichen[ text[ i ] ]->render( renderObj );
			xp += zeichen[ text[ i ] ]->getBreite();
		}
	}
	txt->release();
	renderObj->setDrawOptions( -1, -1, -1, -1 );
}

void Alphabet::render( Text *txt, Bild *renderObj, int cpos, int cf, int fbeg, int ff ) const
{
	int rObjBr = renderObj->getBreite();
	int rObjHö = renderObj->getHöhe();
	int xp = pos->getX();
	int yp = pos->getY();
	int zh = getZeilenHöhe();
	if( yp + zh < 0 ||xp >= rObjBr || yp >= rObjHö )
		return;
	unsigned char *text = (unsigned char*)txt->getText();
	int län = txt->getLänge();
	bool färb = 0;
	for( int i = 0; i < län; i++ )
	{
		if( i == fbeg )
			färb = !färb;
		if( i == cpos )
		{
			xp += 2;
			renderObj->drawLinieVAlpha( xp, yp, zh, cf );
			xp += 2;
			färb = !färb;
		}
		if( text[ i ] == ' ' )
		{
			if( färb )
				renderObj->alphaRegion( xp, yp, drawSchriftGröße / 2, zh, ff );
			xp += drawSchriftGröße / 2;
			continue;
		}
		if( text[ i ] == '\n' )
		{
			yp += zh + zeilenAbstand;
			xp = pos->getX();
			continue;
		}
		if( text[ i ] == '\r' && län - i >= 11 )
		{
			i += 3;
			Text *hex1 = txt->getTeilText( i, i + 6 );
			Text *hex2 = txt->getTeilText( i + 6, i + 8 );
			unsigned int fc = ( TextZuInt( hex1->getText(), 16 ) << 8 ) |
							  ( TextZuInt( hex2->getText(), 16 ) );
			hex1->release();
			hex2->release();
			for( int i2 = 0; i2 < 256; i2++ )
				if( zeichen[ i2 ] )
					zeichen[ i2 ]->setFarbe( fc );
			i += 7;
			continue;
		}
		if( zeichen[ text[ i ] ] )
		{
			if( xp >= rObjBr )
				continue;
			if( färb )
			{
				int br = zeichen[ text[ i ] ]->getBreite();
				renderObj->alphaRegion( xp, yp, br, zh, ff );
			}
			zeichen[ text[ i ] ]->setPosition( xp, yp );
			zeichen[ text[ i ] ]->render( renderObj );
			xp += zeichen[ text[ i ] ]->getBreite();
		}
	}
	if( län == cpos )
		renderObj->drawLinieVAlpha( xp, yp, zh, cf );
	txt->release();
}

void Alphabet::render( int xOff, int yOff, int bOff, int hOff, Text *txt, Bild *renderObj, int cpos, int cf, int fbeg, int ff ) const
{
	renderObj->setDrawOptions( xOff, yOff, xOff + bOff, yOff + hOff );
	int rObjBr = xOff + bOff;
	int rObjHö = yOff + hOff;
	int xp = pos->getX() + xOff;
	int yp = pos->getY() + yOff;
	int zh = getZeilenHöhe();
	if( yp + zh < yOff ||xp >= rObjBr || yp >= rObjHö )
		return;
	unsigned char *text = (unsigned char*)txt->getText();
	int län = txt->getLänge();
	bool färb = 0;
	for( int i = 0; i < län; i++ )
	{
		if( i == fbeg )
			färb = !färb;
		if( i == cpos )
		{
			xp += 2;
			renderObj->drawLinieVAlpha( xp, yp, zh, cf );
			xp += 2;
			färb = !färb;
		}
		if( text[ i ] == ' ' )
		{
			if( färb )
				renderObj->alphaRegion( xp, yp, drawSchriftGröße / 2, zh, ff );
			xp += drawSchriftGröße / 2;
			continue;
		}
		if( text[ i ] == '\n' )
		{
			yp += zh + zeilenAbstand;
			xp = pos->getX();
			continue;
		}
		if( text[ i ] == '\r' && län - i >= 11 )
		{
			i += 3;
			Text *hex1 = txt->getTeilText( i, i + 6 );
			Text *hex2 = txt->getTeilText( i + 6, i + 8 );
			unsigned int fc = ( TextZuInt( hex1->getText(), 16 ) << 8 ) |
							  ( TextZuInt( hex2->getText(), 16 ) );
			hex1->release();
			hex2->release();
			for( int i2 = 0; i2 < 256; i2++ )
				if( zeichen[ i2 ] )
					zeichen[ i2 ]->setFarbe( fc );
			i += 7;
			continue;
		}
		if( zeichen[ text[ i ] ] )
		{
			if( xp >= rObjBr )
				continue;
			if( färb )
			{
				int br = zeichen[ text[ i ] ]->getBreite();
				renderObj->alphaRegion( xp, yp, br, zh, ff );
			}
			zeichen[ text[ i ] ]->setPosition( xp, yp );
			zeichen[ text[ i ] ]->render( renderObj );
			xp += zeichen[ text[ i ] ]->getBreite();
		}
	}
	if( län == cpos )
		renderObj->drawLinieVAlpha( xp, yp, zh, cf );
	txt->release();
	renderObj->setDrawOptions( -1, -1, -1, -1 );
}

// Reference Counting 
Alphabet *Alphabet::getThis()
{
	ref++;
	return this;
}

Alphabet *Alphabet::release()
{
	ref--;
	if( ref == 0 )
		delete this;
	return 0;
}

// Inhalt der AlphabetArray Klasse aus Schrift.h
// Konstruktor 
AlphabetArray::AlphabetArray()
{
	This = 0;
	next = 0;
}

// Destruktor 
AlphabetArray::~AlphabetArray()
{
	if( This )
		This->release();
	delete next;
}

// nicht constant 
void AlphabetArray::addAlphabet( Alphabet *alphabet ) // Fügt ein Alphabet hinzu
{
	if( This )
	{
		if( This->getSchriftgröße() == alphabet->getSchriftgröße() )
		{
			alphabet->release();
			return;
		}
	}
	else
	{
		This = alphabet;
		return;
	}
	if( !next )
		next = new AlphabetArray();
	next->addAlphabet( alphabet );
}

bool AlphabetArray::removeAlphabet( int sg ) // entfernt ein Alphabet
{
	if( This )
	{
		if( This->getSchriftgröße() == sg )
			This = This->release();
			return 1;
	}
	if( !next )
		return 0;
	if( next->removeAlphabet( sg ) )
	{
		AlphabetArray *tmp = next->getNext();
		next->setNext0();
		delete next;
		next = tmp;
	}
	return 0;
}

void AlphabetArray::setDrawSchriftGröße( int sg ) // Setzt die Draw Schriftgröße aller Alphabete
{
	if( This )
		This->setDrawSchriftgröße( sg );
	if( next )
		next->setDrawSchriftGröße( sg );
}

void AlphabetArray::setZeilenAbstand( int za ) // setzt den Zeilenabstant aller Alphabete
{
	if( This )
		This->setZeilenAbstand( za );
	if( next )
		next->setZeilenAbstand( za );
}

void AlphabetArray::setSchriftFarbe( Farbe *farbe ) // setzt die Schriftfarbe aller Alphabete
{
	if( This )
		This->setFarbe( farbe->getFarbe() );
	if( next )
		next->setSchriftFarbe( farbe->getFarbe() );
	farbe->release();
}

void AlphabetArray::setSchriftFarbe( int fc )
{
	if( This )
		This->setFarbe( fc );
	if( next )
		next->setSchriftFarbe( fc );
}

void AlphabetArray::setNext0() // setzt den next Zeiger zu 0
{
	next = 0;
}

// constant 
Alphabet *AlphabetArray::getAlphabet( unsigned char sg ) const // gibt getThis von einem Alphabet zurück
{
	if( !This )
		return 0;
	if( This->getSchriftgröße() == sg )
		return This->getThis();
	if( next )
		return next->getAlphabet( sg );
	return 0;
}

Alphabet *AlphabetArray::zAlphabet( unsigned char sg ) const // gibt ein Alphabet zurück
{
	if( !This )
		return 0;
	if( This->getSchriftgröße() == sg )
		return This;
	if( next )
		return next->getAlphabet( sg );
	return 0;
}

Alphabet *AlphabetArray::getAlphabetI( int index, int count ) const
{
	if( count == index )
		return This;
	if( next )
		return next->getAlphabetI( index, count + 1 );
	return 0;
}

AlphabetArray *AlphabetArray::getNext() const // gibt das nächste Alphabet zurück
{
	return next;
}

// Inhalt der Schrift Klasse aus Schrift.h
// Konstruktor 
Schrift::Schrift()
{
	drawPos = new Punkt();
	zeilenAbstand = 5;
	schriftGröße = 12;
	alphabet = new AlphabetArray();
	alphabetAnzahl = 0;
	farbe = new Farbe();
	InitializeCriticalSection( &threadSave );
	ref = 1;
}

// Destruktor 
Schrift::~Schrift()
{
	drawPos->release();
	delete alphabet;
	farbe->release();
	DeleteCriticalSection( &threadSave );
}

// nicht constant 
void Schrift::addAlphabet( Alphabet *alphabet ) // Fügt der Schrift ein Alphabet hinzu
{
	lockSchrift();
	alphabetAnzahl++;
	alphabet->setDrawSchriftgröße( schriftGröße );
	this->alphabet->addAlphabet( alphabet );
	unlockSchrift();
}

void Schrift::removeAlphabet( int sg ) // Entfernt ein Alphabet
{
	lockSchrift();
	alphabetAnzahl--;
	alphabet->removeAlphabet( sg );
	unlockSchrift();
}

void Schrift::setDrawPosition( int x, int y ) // setzt die Zeichenposition
{
	lockSchrift();
	drawPos->setP( x, y );
	unlockSchrift();
}

void Schrift::setDrawPosition( Punkt *pos )
{
	lockSchrift();
	drawPos->setP( pos->x, pos->y );
	pos->release();
	unlockSchrift();
}

void Schrift::setSchriftGröße( int sg ) // setzt die Schriftgröße
{
	lockSchrift();
	schriftGröße = sg;
	alphabet->setDrawSchriftGröße( sg );
	unlockSchrift();
}

void Schrift::setZeilenAbstand( int za ) // setzt den Zeilenabstand
{
	lockSchrift();
	zeilenAbstand = za;
	alphabet->setZeilenAbstand( za );
	unlockSchrift();
}

void Schrift::setFarbe( Farbe *f ) // setzt die Schriftfarbe
{
	lockSchrift();
	farbe->setFarbe( f->getFarbe() );
	alphabet->setSchriftFarbe( f );
	unlockSchrift();
}

void Schrift::setFarbe( int fc )
{
	lockSchrift();
	farbe->setFarbe( fc );
	alphabet->setSchriftFarbe( fc );
	unlockSchrift();
}

void Schrift::renderText( Text *txt, Bild *rObj ) // zeichnet txt nach rObj
{
	lockSchrift();
	Alphabet *drawAlphabet = alphabet->zAlphabet( schriftGröße );
	if( !drawAlphabet )
	{
		for( int i = 0; i < 256; i++ )
		{
			drawAlphabet = alphabet->zAlphabet( schriftGröße - i );
			if( drawAlphabet )
				break;
			drawAlphabet = alphabet->zAlphabet( schriftGröße + i );
			if( drawAlphabet )
				break;
		}
	}
	if( drawAlphabet )
	{
		drawAlphabet->setDrawPosition( drawPos->x, drawPos->y );
		drawAlphabet->render( txt, rObj );
	}
	else
		txt->release();
	unlockSchrift();
}

void Schrift::renderText( int xOff, int yOff, int bOff, int hOff, Text *txt, Bild *rObj )
{
	lockSchrift();
	Alphabet *drawAlphabet = alphabet->zAlphabet( schriftGröße );
	if( !drawAlphabet )
	{
		for( int i = 0; i < 256; i++ )
		{
			drawAlphabet = alphabet->zAlphabet( schriftGröße - i );
			if( drawAlphabet )
				break;
			drawAlphabet = alphabet->zAlphabet( schriftGröße + i );
			if( drawAlphabet )
				break;
		}
	}
	if( drawAlphabet )
	{
		drawAlphabet->setDrawPosition( drawPos->x, drawPos->y );
		drawAlphabet->render( xOff, yOff, bOff, hOff, txt, rObj );
	}
	else
		txt->release();
	unlockSchrift();
}

void Schrift::renderText( Text *txt, Bild *rObj, int cpos, int cf, int fbeg, int ff )
{
	lockSchrift();
	Alphabet *drawAlphabet = alphabet->zAlphabet( schriftGröße );
	if( !drawAlphabet )
	{
		for( int i = 0; i < 256; i++ )
		{
			drawAlphabet = alphabet->zAlphabet( schriftGröße - i );
			if( drawAlphabet )
				break;
			drawAlphabet = alphabet->zAlphabet( schriftGröße + i );
			if( drawAlphabet )
				break;
		}
	}
	if( drawAlphabet )
	{
		drawAlphabet->setDrawPosition( drawPos->x, drawPos->y );
		drawAlphabet->render( txt, rObj, cpos, cf, fbeg, ff );
	}
	else
		txt->release();
	unlockSchrift();
}

void Schrift::renderText( int xOff, int yOff, int bOff, int hOff, Text *txt, Bild *rObj, int cpos, int cf, int fbeg, int ff )
{
	lockSchrift();
	Alphabet *drawAlphabet = alphabet->zAlphabet( schriftGröße );
	if( !drawAlphabet )
	{
		for( int i = 0; i < 256; i++ )
		{
			drawAlphabet = alphabet->zAlphabet( schriftGröße - i );
			if( drawAlphabet )
				break;
			drawAlphabet = alphabet->zAlphabet( schriftGröße + i );
			if( drawAlphabet )
				break;
		}
	}
	if( drawAlphabet )
	{
		drawAlphabet->setDrawPosition( drawPos->x, drawPos->y );
		drawAlphabet->render( xOff, yOff, bOff, hOff, txt, rObj, cpos, cf, fbeg, ff );
	}
	else
		txt->release();
	unlockSchrift();
}

void Schrift::lockSchrift() // blockiert die Schrift für andere Threads
{
	EnterCriticalSection( &threadSave );
}

void Schrift::unlockSchrift() // gibt die Schrift für andere Threads frei
{
	LeaveCriticalSection( &threadSave );
}

// constant 
Alphabet *Schrift::getAlphabet( int sg ) const // gibt einen Alphaberarray zurück
{
	return alphabet->getAlphabet( sg );
}

Alphabet *Schrift::getAlphabetI( int index ) const
{
	return alphabet->getAlphabetI( index, 0 );
}

unsigned char Schrift::getAlphabetAnzahl() const // gibt die anzahl von in der Schrift enthaltenen Alphabeten zurück
{
	return alphabetAnzahl;
}

int Schrift::getSchriftGröße() const // gibt die Schriftgröße zurück
{
	return schriftGröße;
}

int Schrift::getZeilenabstand() const // gibt den Zeilenabstand zurück
{
	return zeilenAbstand;
}

int Schrift::getDrawX() const // gibt die Zeichenposition zurück
{
	return drawPos->x;
}

int Schrift::getDrawY() const
{
	return drawPos->y;
}

Punkt *Schrift::getDrawPosition() const
{
	return drawPos->getThis();
}

Farbe *Schrift::getFarbe() const // gibt die Farbe zurück
{
	return farbe->getThis();
}

unsigned int Schrift::getFarbeCode() const
{
	return farbe->getFarbe();
}

int Schrift::getTextBreite( Text *txt ) const // gibt die Breite des Textes zurück
{
	Alphabet *drawAlphabet = alphabet->zAlphabet( schriftGröße );
	if( !drawAlphabet )
	{
		for( int i = 0; i < 256; i++ )
		{
			drawAlphabet = alphabet->zAlphabet( schriftGröße - i );
			if( drawAlphabet )
				break;
			drawAlphabet = alphabet->zAlphabet( schriftGröße + i );
			if( drawAlphabet )
				break;
		}
	}
	if( !drawAlphabet )
		return 0;
	return drawAlphabet->getTextBreite( txt );
}

int Schrift::getTextHöhe( Text *txt ) const // gibt die Höhe des Textes zurück
{
	Alphabet *drawAlphabet = alphabet->zAlphabet( schriftGröße );
	if( !drawAlphabet )
	{
		for( int i = 0; i < 256; i++ )
		{
			drawAlphabet = alphabet->zAlphabet( schriftGröße - i );
			if( drawAlphabet )
				break;
			drawAlphabet = alphabet->zAlphabet( schriftGröße + i );
			if( drawAlphabet )
				break;
		}
	}
	if( !drawAlphabet )
	{
		txt->release();
		return 0;
	}
	return drawAlphabet->getTextHöhe( txt );
}

int Schrift::textPos( Text *txt, int mausX, int mausY ) const // gibt den Buchstaben zurück, auf den die Maus zeigt
{
	Alphabet *drawAlphabet = alphabet->zAlphabet( schriftGröße );
	if( !drawAlphabet )
	{
		for( int i = 0; i < 256; i++ )
		{
			drawAlphabet = alphabet->zAlphabet( schriftGröße - i );
			if( drawAlphabet )
				break;
			drawAlphabet = alphabet->zAlphabet( schriftGröße + i );
			if( drawAlphabet )
				break;
		}
	}
	if( !drawAlphabet )
		return 0;
	return drawAlphabet->textPos( txt, mausX, mausY );
}

// Reference Counting 
Schrift *Schrift::getThis()
{
	ref++;
	return this;
}

Schrift *Schrift::release()
{
	ref--;
	if( ref == 0 )
		delete this;
	return 0;
}