#include "Schrift.h" #include "Bild.h" #include "Globals.h" #include "Scroll.h" #include "Text.h" #ifdef WIN32 # include #endif #include "FrameworkMath.h" using namespace Framework; // Inhalt der Buchstabe Klasse aus Schrift.h // Konstruktor Buchstabe::Buchstabe() : ReferenceCounter(), size(0, 0), alpha(0), schriftSize(0) {} // Destruktor Buchstabe::~Buchstabe() { if (alpha) delete[] alpha; } // nicht constant void Buchstabe::NeuBuchstabe(Punkt& size) // Initialisierung { this->size = size; if (alpha) delete[] alpha; alpha = new unsigned char[size.x * size.y]; ZeroMemory(alpha, size.x * size.y); } void Buchstabe::setPixel( Punkt& pos, unsigned char alpha) // setzt den alphawert des Pixels { this->alpha[pos.x + pos.y * size.x] = alpha; } void Buchstabe::setPixel(int x, int y, unsigned char alpha) { this->alpha[x + y * size.x] = alpha; } void Buchstabe::setPixel(int i, unsigned char alpha) { this->alpha[i] = alpha; } void Buchstabe::setSchriftSize(int sg) // setzt die Schriftgröße des Buchstaben { schriftSize = sg; } int Buchstabe::getSchriftSize() const { return schriftSize; } // constant const Punkt& Buchstabe::getSize() const // gibt die Buchstabenbildgröße zurück { return size; } int Buchstabe::getBreite() const // Buchstabenbreite { return size.x; } int Buchstabe::getHeight() const // Buchstabenhöhe { return size.y; } unsigned char* Buchstabe::getBuff() const // gibt den Alphabuffer zurück { return alpha; } // Inhalt der Alphabet Klasse aus Schrift.h // Konstruktor Alphabet::Alphabet() : ReferenceCounter(), zeichen(new Buchstabe*[256]), schriftSize(12) { for (int i = 0; i < 256; ++i) zeichen[i] = 0; } // Destruktor Alphabet::~Alphabet() { for (int i = 0; i < 256; ++i) { if (zeichen[i]) zeichen[i]->release(); } delete[] zeichen; } // 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; } 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]->setSchriftSize(schriftSize); } } void Alphabet::setSchriftSize(int gr) // setzt die Schriftgröße { schriftSize = gr; for (int i = 0; i < 256; ++i) { if (zeichen[i]) zeichen[i]->setSchriftSize(gr); } } // constant Buchstabe* Alphabet::getBuchstabe( unsigned char i) const // gibt einen Buchstaben zurück { if (zeichen[i]) return dynamic_cast(zeichen[i]->getThis()); return 0; } Buchstabe* Alphabet::zBuchstabe(unsigned char i) const { return zeichen[i]; } bool Alphabet::hatBuchstabe(unsigned char b) const { return zeichen[b] != 0; } int Alphabet::getSchriftSize() const // gibt die Schriftgröße zurück { return schriftSize; } // Inhalt der AlphabetArray Klasse aus Schrift.h // Konstruktor AlphabetArray::AlphabetArray() { memset(alphabets, 0, sizeof(Alphabet*) * 256); } // nicht constant bool AlphabetArray::addAlphabet(Alphabet* alphabet) // Fügt ein Alphabet hinzu { if (alphabets[alphabet->getSchriftSize()] != 0) { alphabet->release(); return 0; } alphabets[alphabet->getSchriftSize()] = alphabet; return 1; } bool AlphabetArray::removeAlphabet(unsigned char sg) // entfernt ein Alphabet { if (alphabets[sg]) { alphabets[sg]->release(); alphabets[sg] = 0; return 1; } return 0; } // constant Alphabet* AlphabetArray::getAlphabet( unsigned char sg) const // gibt getThis von einem Alphabet zurück { if (alphabets[sg]) return dynamic_cast(alphabets[sg]->getThis()); return 0; } Alphabet* AlphabetArray::zAlphabet( unsigned char sg) const // gibt ein Alphabet zurück { return alphabets[sg]; } // Inhalt der Schrift Klasse aus Schrift.h // Konstruktor Schrift::Schrift() : ReferenceCounter(), alphabetAnzahl(0), alphabet(new AlphabetArray()) {} // Destruktor Schrift::~Schrift() { delete alphabet; } bool Schrift::addAlphabet( Alphabet* alphabet) // Fügt der Schrift ein Alphabet hinzu { if (this->alphabet->addAlphabet(alphabet)) { ++alphabetAnzahl; return true; } return false; } void Schrift::removeAlphabet(unsigned char sg) // Entfernt ein Alphabet { if (alphabet->removeAlphabet(sg)) --alphabetAnzahl; } // constant Alphabet* Schrift::getAlphabet(unsigned char sg) const { Alphabet* drawAlphabet = alphabet->zAlphabet(sg); if (!drawAlphabet) { for (int i = 0; i < 256; ++i) { if (sg - i > 0) { drawAlphabet = alphabet->zAlphabet((unsigned char)(sg - i)); if (drawAlphabet) break; } if (sg + i < 256) { drawAlphabet = alphabet->zAlphabet((unsigned char)(sg + i)); if (drawAlphabet) break; } } } return dynamic_cast(drawAlphabet->getThis()); } Alphabet* Schrift::zAlphabet(unsigned char sg) const { Alphabet* drawAlphabet = alphabet->zAlphabet(sg); if (!drawAlphabet) { for (int i = 0; i < 256; ++i) { if (sg - i > 0) { drawAlphabet = alphabet->zAlphabet((unsigned char)(sg - i)); if (drawAlphabet) break; } if (sg + i < 256) { drawAlphabet = alphabet->zAlphabet((unsigned char)(sg + i)); if (drawAlphabet) break; } } } return drawAlphabet; } unsigned char Schrift::getAlphabetAnzahl() const // gibt die anzahl von in der Schrift enthaltenen Alphabeten zurück { return alphabetAnzahl; } TextRenderer::TextRenderer() : TextRenderer(0) {} TextRenderer::TextRenderer(Schrift* schrift) : ReferenceCounter() { s = schrift; zeilenAbstand = 5; zeichenAbstand = 0; schriftSize = 0; setSchriftSize(12); } TextRenderer::~TextRenderer() { if (s) s->release(); } void TextRenderer::setSchriftZ(Schrift* schrift) { if (s != schrift) { if (s) s->release(); s = schrift; memset(charWidths, 0, sizeof(charWidths)); memset(charHeights, 0, sizeof(charHeights)); if (s) { Alphabet* a = s->zAlphabet((unsigned char)schriftSize); for (int i = 0; i < 256; i++) { Buchstabe* b = a->zBuchstabe((unsigned char)i); if (b) { charWidths[i] = (int)((b->getBreite() / (double)a->getSchriftSize()) * schriftSize + 0.5); charHeights[i] = (int)((b->getHeight() / (double)a->getSchriftSize()) * schriftSize + 0.5); } else { charWidths[i] = 0; charHeights[i] = 0; } } } } else { schrift->release(); } } Schrift* TextRenderer::getSchrift() { if (s) return dynamic_cast(s->getThis()); return 0; } Schrift* TextRenderer::zSchrift() { return s; } // Setzt die Schriftgröße, in der gezeichnet werden soll. Die Schrift wählt // automatisch das passende Alphabet zum Zeichnen // sg: Die Schriftgröße void TextRenderer::setSchriftSize(int sg) { if (schriftSize != sg) { schriftSize = sg; memset(charWidths, 0, sizeof(charWidths)); memset(charHeights, 0, sizeof(charHeights)); if (s) { Alphabet* a = s->zAlphabet((unsigned char)schriftSize); for (int i = 0; i < 256; i++) { Buchstabe* b = a->zBuchstabe((unsigned char)i); if (b) { charWidths[i] = (int)((b->getBreite() / (double)a->getSchriftSize()) * schriftSize + 0.5); charHeights[i] = (int)((b->getHeight() / (double)a->getSchriftSize()) * schriftSize + 0.5); } else { charWidths[i] = 0; charHeights[i] = 0; } } } } } // Setzt den Zeilenabstand, der zum zeichnen verwendet werden soll // za: Der Zeilenabstand zum unteren Ende der darüber liegenden zeile in Pixeln void TextRenderer::setZeilenAbstand(int za) { zeilenAbstand = za; } // Setzt den Zeichenabstand, der zum zeichnen verwendet werden soll // za: Der Zeichenabstand zum unteren Ende der darüber liegenden zeile in // Pixeln void TextRenderer::setZeichenAbstand(int za) { zeichenAbstand = za; } // Fügt Zeilenumbrüche in den Text ein, so dass er bei einer vorgegebenen Breite // follständig angezeigt wird // zText: Der text, in den die Zeilenumbrüche eingefügt werden sollen // maxBreite: Die Breite in Pixeln auf der der Text follständig angezeigt // werden soll void TextRenderer::textFormatieren(Text* zTxt, int maxBreite) { int lastPos = -1; int x = 0; const char* txt = zTxt->getText(); Text result = txt; int len = zTxt->getLength(); for (int i = 0; i < len; ++i) { if (txt[i] == ' ') { lastPos = i; x += schriftSize / 2 + zeichenAbstand; continue; } if (txt[i] == '\t') { lastPos = i; x += schriftSize + zeichenAbstand; continue; } if (txt[i] == '\n') { x = 0; lastPos = -1; continue; } x += getCharWidth(txt[i]) + zeichenAbstand; if (x > maxBreite && lastPos > -1) { result.ersetzen(lastPos, lastPos + 1, "\n"); x = 0; i = lastPos; lastPos = -1; } } zTxt->setText(result); } // Zeichnet einen Bestimmten Text mit Cursor und einfärbung auf ein Bild // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe // zu verändern // x: x position des ersten zeichens // y: y position des ersten zeichens // txt: Der Text, der gezeichnet werden soll // zRObj: Das Bild, auf das gezeichnet werden soll // cpos: Die position des Cursors im Text // cf: Die Farbe des Cursors // fbeg: Die Position des Zeichens im Text, wo die Einfärbung beginnen soll. // Der Text wird von dort bis zur Cursorposition eingefärbt ff: Die Hintergrund // Farbe des eingefärbten Textes f: Eine Funktion die für jeden Buchstaben // aufgerufen wird und seine Farbe zurückgibt void TextRenderer::renderText(int x, int y, const char* txt, Bild& zRObj, std::function f, int cpos, int cf, int fbeg, int ff) { if (!s) return; if (fbeg == -1) fbeg = cpos; int zRObjBr = zRObj.getBreite(); int zRObjHi = zRObj.getHeight(); const Punkt& zRObjOff = zRObj.getDrawOff(); int beginX = x; int zh = getZeilenHeight(); if (y + (zh + zeilenAbstand) * Text(txt).anzahlVon('\n') + zh + zRObjOff.y < 0 || x + zRObjOff.x >= zRObjBr || y + zRObjOff.y >= zRObjHi) return; bool faerb = 0; int len = textLength(txt); for (int i = 0; i < len; ++i) { if (i == fbeg) faerb = !faerb; if (i == cpos) { zRObj.drawLinieVAlpha(x, y, zh, cf); faerb = !faerb; } if (txt[i] == ' ') { if (faerb) zRObj.alphaRegion( x, y, schriftSize / 2 + zeichenAbstand, zh, ff); x += schriftSize / 2 + zeichenAbstand; continue; } if (txt[i] == '\t') { if (faerb) zRObj.alphaRegion(x, y, schriftSize + zeichenAbstand, zh, ff); x += schriftSize + zeichenAbstand; continue; } if (txt[i] == '\n') { y += zh + zeilenAbstand; x = beginX; continue; } renderChar(x, y, txt[i], zRObj, f(x, y, i), 0, faerb, ff); } if (textLength(txt) == cpos) zRObj.drawLinieVAlpha(x, y, zh, cf); } // Zeichnet einen Bestimmten Text mit Cursor und einfärbung auf ein Bild // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe // zu verändern // x: x position des ersten zeichens // y: y position des ersten zeichens // txt: Der Text, der gezeichnet werden soll // zRObj: Das Bild, auf das gezeichnet werden soll // cpos: Die position des Cursors im Text // cf: Die Farbe des Cursors // fbeg: Die Position des Zeichens im Text, wo die Einfärbung beginnen soll. // Der Text wird von dort bis zur Cursorposition eingefärbt ff: Die Hintergrund // Farbe des eingefärbten Textes f: Die Farbe, in der der Text gezeichnet // werden soll void TextRenderer::renderText(int x, int y, const char* txt, Bild& zRObj, int f, int cpos, int cf, int fbeg, int ff) { return renderText( x, y, txt, zRObj, [f](int a, int b, int c) { return f; }, cpos, cf, fbeg, ff); } // Zeichnet einen Bestimmten Buchstaben mit einfärbung auf ein Bild // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe // zu verändern // x: x position des ersten zeichens // y: y position des ersten zeichens // txt: Der Text, der gezeichnet werden soll // zRObj: Das Bild, auf das gezeichnet werden soll // color: Die Farbe, in der der Text gezeichnet werden soll // underlined: 1, falls der Text unterstrichen sein soll // selected: 1, falls das zeichen eingefärbt sein soll // selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes void TextRenderer::renderChar(int& x, int y, char c, Bild& zRObj, int color, bool underlined, bool selected, int selectedBackgroundColor) { if (!s) return; Alphabet* a = s->zAlphabet((unsigned char)schriftSize); if (!a) return; Buchstabe* b = a->zBuchstabe(c); if (b) { if (x >= zRObj.getBreite()) return; if (zRObj.isAreaDrawable(x, y, getCharWidth(c), getCharHeight(c))) { if (selected) { int br = getCharWidth(c) + zeichenAbstand; zRObj.alphaRegion( x, y, br, getZeilenHeight(), selectedBackgroundColor); } if (b->getBuff()) { const Punkt& zRObjGr = zRObj.getDrawGr(); const Punkt& zRObjPos = zRObj.getDrawPos(); const Punkt& zRObjOff = zRObj.getDrawOff(); int xp = x + zRObjOff.x, yp = y + zRObjOff.y; int xs = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0, ys = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0; int br = b->getBreite(); unsigned char a2 = (unsigned char)(255 - (color >> 24)); color &= 0x00FFFFFF; float xoff = (float)b->getSchriftSize() / (float)schriftSize, yoff = (float)b->getSchriftSize() / (float)schriftSize; float x = (float)xs * xoff, y = (float)ys * yoff; int maxX = getCharWidth(c), maxY = getCharHeight(c); maxX = (xp + maxX) >= zRObjGr.x ? (zRObjGr.x - xp) : maxX; maxY = (yp + maxY) >= zRObjGr.y ? (zRObjGr.y - yp) : maxY; int a, dx, ygr, ygr2; if (zRObj.hasAlpha3D()) { for (int dy = ys; dy < maxY; ++dy) { ygr2 = (yp + dy) * zRObj.getBreite() + xp; ygr = (int)y * br; for (dx = xs; dx < maxX; ++dx) { a = b->getBuff()[(int)x + ygr] - a2; zRObj.alphaPixel3D(dx + ygr2, color | (a << 24)); x += xoff; } x = (float)xs; y += yoff; } } else { for (int dy = ys; dy < maxY; ++dy) { ygr2 = (yp + dy) * zRObj.getBreite() + xp; ygr = (int)y * br; for (dx = xs; dx < maxX; ++dx) { a = b->getBuff()[(int)x + ygr] - a2; zRObj.alphaPixel2D(dx + ygr2, color | (a << 24)); x += xoff; } x = (float)xs; y += yoff; } } } if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); } x += getCharWidth(c) + zeichenAbstand; } else if (c == ' ') { if (selected) zRObj.alphaRegion(x, y, schriftSize / 2 + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor); if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, schriftSize / 2 + zeichenAbstand + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); x += schriftSize / 2 + zeichenAbstand; } else if (c == '\t') { if (selected) zRObj.alphaRegion(x, y, schriftSize + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor); if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, schriftSize + zeichenAbstand + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); x += schriftSize + zeichenAbstand; } } // Gibt die Schriftgröße zurück, die zum Zeichnen verwendet wird int TextRenderer::getSchriftSize() const { return schriftSize; } // Gibt den Abstand in Pixeln zum unteren Ende der darüber ligenden Zeile zurück int TextRenderer::getZeilenabstand() const { return zeilenAbstand; } // Gibt den Abstand in Pixeln zum zwischen zwei zeichen auf der x Achse zurück int TextRenderer::getZeichenAbstand() const { return zeichenAbstand; } // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text // vollständig darzustellen // txt: Der Text, von dem die Breite in Pixeln ermitelt werden soll int TextRenderer::getTextBreite(const char* txt) const { int ret = 0; int tmp = 0; int len = textLength(txt); for (int i = 0; i < len; ++i) { if (txt[i] == '\n') { if (tmp > ret) ret = tmp; tmp = 0; } else if (txt[i] == '\t') tmp += schriftSize + zeichenAbstand; else if (txt[i] == ' ') tmp += schriftSize / 2 + zeichenAbstand; else tmp += getCharWidth(txt[i]) + zeichenAbstand; } if (tmp > ret) ret = tmp; return ret; } // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text // vollständig darzustellen // txt: Der Text, von dem die Höhe in Pixeln ermitelt werden soll int TextRenderer::getTextHeight(const char* txt) const { int hi = getZeilenHeight(); return hi + ((hi + zeilenAbstand) * Text(txt).anzahlVon('\n')); } // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Buchstaben // vollständig darzustellen // c: Der Buchstabe, von dem die Breite in Pixeln ermitelt werden soll int TextRenderer::getCharWidth(const char c) const { return charWidths[(unsigned char)c]; } // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text // vollständig darzustellen // c: Der Buchstabe, von dem die Höhe in Pixeln ermitelt werden soll int TextRenderer::getCharHeight(const char c) const { return charHeights[(unsigned char)c]; } // Gibt den Abstand in Pixeln zum unteren Ende der darüber ligenden Zeile zurück int TextRenderer::getZeilenAbstand() const { return zeilenAbstand; } // Gibt die skallierte Höhe zurück, die eine gezeichnete Zeile in Pixeln // benötigt int TextRenderer::getZeilenHeight() const { int zh = 0; for (int i = 0; i < 256; ++i) { zh = maxInt(getCharHeight((char)i), zh); } return zh; } // Ermittelt das Zeichen im Text, auf das die Maus zeigt // txt: Der Text, auf den die Maus Zeigt // mausX: Die X Position der Maus in Pixeln Relativ zur Position des ersten // Zeichens mausY: Die Y Position der Maus in Pixeln Relativ zur Position des // ersten Zeichens int TextRenderer::textPos(const char* txt, int mausX, int mausY) const { int tx = 0; int ty = 0; int sh = getZeilenHeight(); if (mausX < 0 || mausY < 0) return -1; int len = textLength(txt); for (int i = 0; i < len; ++i) { if (txt[i] == '\n') { ty += sh + zeilenAbstand; tx = 0; if (mausY < ty) return i; } if (txt[i] == '\t') tx += schriftSize + zeichenAbstand; if (txt[i] == ' ') tx += schriftSize / 2 + zeichenAbstand; tx += getCharWidth(txt[i]); int txpl = getCharWidth(txt[i + 1]) / 2; if (mausX < tx - txpl && mausY < ty + sh + zeilenAbstand) return i; } if (mausY < ty + sh + zeilenAbstand) return textLength(txt); return -1; } GravurTextRenderer::GravurTextRenderer() : GravurTextRenderer(0) {} GravurTextRenderer::GravurTextRenderer(Schrift* schrift) : TextRenderer(schrift) {} GravurTextRenderer::~GravurTextRenderer() {} // Zeichnet einen Bestimmten Buchstaben mit einfärbung auf ein Bild // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe // zu verändern // x: x position des ersten zeichens // y: y position des ersten zeichens // txt: Der Text, der gezeichnet werden soll // zRObj: Das Bild, auf das gezeichnet werden soll // color: Die Farbe, in der der Text gezeichnet werden soll // underlined: 1, falls der Text unterstrichen sein soll // selected: 1, falls das zeichen eingefärbt sein soll // selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes void GravurTextRenderer::renderChar(int& x, int y, char c, Bild& zRObj, int color, bool underlined, bool selected, int selectedBackgroundColor) { if (!s) return; Alphabet* a = s->zAlphabet((unsigned char)schriftSize); Buchstabe* b = a->zBuchstabe(c); if (b) { if (x >= zRObj.getBreite()) return; if (zRObj.isAreaDrawable(x, y, getCharWidth(c), getCharHeight(c))) { if (selected) { int br = getCharWidth(c) + zeichenAbstand; zRObj.alphaRegion( x, y, br, getZeilenHeight(), selectedBackgroundColor); } if (b->getBuff()) { const Punkt& zRObjGr = zRObj.getDrawGr(); const Punkt& zRObjPos = zRObj.getDrawPos(); const Punkt& zRObjOff = zRObj.getDrawOff(); int xp = x + zRObjOff.x, yp = y + zRObjOff.y; int xs = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0, ys = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0; int br = b->getBreite(), h = b->getHeight(); color &= 0x00FFFFFF; double xoff = (double)b->getSchriftSize() / (schriftSize * 2.0), yoff = (double)b->getSchriftSize() / (schriftSize * 2.0); double x = xs * xoff, y = ys * yoff; int maxX = getCharWidth(c), maxY = getCharHeight(c); maxX = (xp + maxX) >= zRObjGr.x ? (zRObjGr.x - xp) : maxX; maxY = (yp + maxY) >= zRObjGr.y ? (zRObjGr.y - yp) : maxY; int dx, ygr, ygr2; if (zRObj.hasAlpha3D()) { for (int dy = ys; dy < maxY; ++dy) { ygr2 = (yp + dy) * zRObj.getBreite(); ygr = (int)y * br; for (dx = xs; dx < maxX; ++dx) { int f = 0; if (b->getBuff()[(int)x + ygr]) f = 0x50000000; else if (((int)(x + xoff) < br && b->getBuff()[(int)(x + xoff) + ygr]) || ((int)(y - yoff) < h && b->getBuff()[(int)x + (int)(y - yoff) * br] > 0xF0)) f = 0xA0000000; else if (((int)(x - xoff) < br && b->getBuff()[(int)(x - xoff) + ygr]) || ((int)(y + yoff) < h && b->getBuff()[(int)x + (int)(y + yoff) * br] > 0xF0)) { f = 0xA0FFFFFF; } zRObj.alphaPixel3D(xp + dx + ygr2, f); x += xoff; } x = xs; y += yoff; } } else { for (int dy = ys; dy < maxY; ++dy) { ygr2 = (yp + dy) * zRObj.getBreite(); ygr = (int)y * br; for (dx = xs; dx < maxX; ++dx) { int f = 0; if (b->getBuff()[(int)x + ygr]) f = 0x50000000; else if (((int)(x + xoff) < br && b->getBuff()[(int)(x + xoff) + ygr]) || ((int)(y - yoff) < h && b->getBuff()[(int)x + (int)(y - yoff) * br] > 0xF0)) f = 0xA0000000; else if (((int)(x - xoff) < br && b->getBuff()[(int)(x - xoff) + ygr]) || ((int)(y + yoff) < h && b->getBuff()[(int)x + (int)(y + yoff) * br] > 0xF0)) { f = 0xA0FFFFFF; } zRObj.alphaPixel2D(xp + dx + ygr2, f); x += xoff; } x = xs; y += yoff; } } } if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); } x += getCharWidth(c) + zeichenAbstand; } else if (c == ' ') { if (selected) zRObj.alphaRegion(x, y, schriftSize / 2 + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor); if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, schriftSize / 2 + zeichenAbstand + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); x += schriftSize / 2 + zeichenAbstand; } else if (c == '\t') { if (selected) zRObj.alphaRegion(x, y, schriftSize + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor); if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, schriftSize + zeichenAbstand + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); x += schriftSize + zeichenAbstand; } } // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Buchstaben // vollständig darzustellen // c: Der Buchstabe, von dem die Breite in Pixeln ermitelt werden soll int GravurTextRenderer::getCharWidth(const char c) const { return TextRenderer::getCharWidth(c) * 2; } // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text // vollständig darzustellen // c: Der Buchstabe, von dem die Höhe in Pixeln ermitelt werden soll int GravurTextRenderer::getCharHeight(const char c) const { return TextRenderer::getCharHeight(c) * 2; } KursivTextRenderer::KursivTextRenderer() : KursivTextRenderer(0) {} KursivTextRenderer::KursivTextRenderer(Schrift* schrift) : TextRenderer(schrift) {} KursivTextRenderer::~KursivTextRenderer() {} // Zeichnet einen Bestimmten Buchstaben mit einfärbung auf ein Bild // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe // zu verändern // x: x position des ersten zeichens // y: y position des ersten zeichens // txt: Der Text, der gezeichnet werden soll // zRObj: Das Bild, auf das gezeichnet werden soll // color: Die Farbe, in der der Text gezeichnet werden soll // underlined: 1, falls der Text unterstrichen sein soll // selected: 1, falls das zeichen eingefärbt sein soll // selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes void KursivTextRenderer::renderChar(int& x, int y, char c, Bild& zRObj, int color, bool underlined, bool selected, int selectedBackgroundColor) { if (!s) return; Alphabet* a = s->zAlphabet((unsigned char)schriftSize); if (!a) return; Buchstabe* b = a->zBuchstabe(c); if (b) { if (x >= zRObj.getBreite()) return; if (zRObj.isAreaDrawable(x, y, getCharWidth(c), getCharHeight(c))) { if (selected) { int br = getCharWidth(c) + zeichenAbstand; zRObj.alphaRegion( x, y, br, getZeilenHeight(), selectedBackgroundColor); } if (b->getBuff()) { const Punkt& zRObjGr = zRObj.getDrawGr(); const Punkt& zRObjPos = zRObj.getDrawPos(); const Punkt& zRObjOff = zRObj.getDrawOff(); int xp = x + zRObjOff.x, yp = y + zRObjOff.y; int xStartBuffer = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0, yStartBuffer = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0; int bufferBreite = b->getBreite(), bufferHeight = b->getHeight(); unsigned char colorAlpha = (unsigned char)(255 - (color >> 24)); color &= 0x00FFFFFF; double xStepBuffer = (double)b->getSchriftSize() / (double)schriftSize, yStepBuffer = (double)b->getSchriftSize() / (double)schriftSize; double xBuffer = xStartBuffer * xStepBuffer, yBuffer = yStartBuffer * yStepBuffer; int charHeight = getCharHeight(c); int maxXBuffer = getCharWidth(c), maxYBuffer = charHeight; maxXBuffer = (xp + maxXBuffer) >= zRObjGr.x ? (zRObjGr.x - xp) : maxXBuffer; maxYBuffer = (yp + maxYBuffer) >= zRObjGr.y ? (zRObjGr.y - yp) : maxYBuffer; std::function colorF = [charHeight, bufferBreite, bufferHeight, colorAlpha, b, color]( int xx, int yy) { xx -= (int)((float)(charHeight - yy) / 4.f + 0.5f); if (xx < 0 || xx >= bufferBreite) return 0x00FFFFFF; int a = b->getBuff()[yy * bufferBreite + xx] - colorAlpha; return color | (a << 24); }; if (zRObj.hasAlpha3D()) { for (int yS = yStartBuffer; yS < maxYBuffer; ++yS) { int ygr2 = (yp + yS) * zRObj.getBreite(); for (int xS = xStartBuffer; xS < maxXBuffer; ++xS) { zRObj.alphaPixel3D( xp + xS + ygr2, colorF((int)xS, (int)yS)); xBuffer += xStepBuffer; } xBuffer = xStartBuffer; yBuffer += yStepBuffer; } } else { for (int yS = yStartBuffer; yS < maxYBuffer; ++yS) { int ygr2 = (yp + yS) * zRObj.getBreite(); for (int xS = xStartBuffer; xS < maxXBuffer; ++xS) { zRObj.alphaPixel2D( xp + xS + ygr2, colorF((int)xS, (int)yS)); xBuffer += xStepBuffer; } xBuffer = xStartBuffer; yBuffer += yStepBuffer; } } } if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); } x += getCharWidth(c) + zeichenAbstand; } else if (c == ' ') { if (selected) zRObj.alphaRegion(x, y, schriftSize / 2 + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor); if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, schriftSize / 2 + zeichenAbstand + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); x += schriftSize / 2 + zeichenAbstand; } else if (c == '\t') { if (selected) zRObj.alphaRegion(x, y, schriftSize + zeichenAbstand, getZeilenHeight(), selectedBackgroundColor); if (underlined) zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5), y + getZeilenHeight() + getZeichenAbstand() / 2, schriftSize + zeichenAbstand + (int)(zeichenAbstand / 2.0 + 0.5), 0xFF000000 | color); x += schriftSize + zeichenAbstand; } } // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Buchstaben // vollständig darzustellen // c: Der Buchstabe, von dem die Breite in Pixeln ermitelt werden soll int KursivTextRenderer::getCharWidth(const char c) const { return (int)(TextRenderer::getCharWidth(c) + getCharHeight(c) / 4.0 + 0.5); }