Schrift.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188
  1. #include "Schrift.h"
  2. #include "Bild.h"
  3. #include "Globals.h"
  4. #include "Scroll.h"
  5. #include "Text.h"
  6. #ifdef WIN32
  7. # include <Windows.h>
  8. #endif
  9. #include "FrameworkMath.h"
  10. using namespace Framework;
  11. // Inhalt der Buchstabe Klasse aus Schrift.h
  12. // Konstruktor
  13. Buchstabe::Buchstabe()
  14. : ReferenceCounter(),
  15. size(0, 0),
  16. alpha(0),
  17. schriftSize(0)
  18. {}
  19. // Destruktor
  20. Buchstabe::~Buchstabe()
  21. {
  22. if (alpha) delete[] alpha;
  23. }
  24. // nicht constant
  25. void Buchstabe::NeuBuchstabe(Punkt& size) // Initialisierung
  26. {
  27. this->size = size;
  28. if (alpha) delete[] alpha;
  29. alpha = new unsigned char[size.x * size.y];
  30. ZeroMemory(alpha, size.x * size.y);
  31. }
  32. void Buchstabe::setPixel(
  33. Punkt& pos, unsigned char alpha) // setzt den alphawert des Pixels
  34. {
  35. this->alpha[pos.x + pos.y * size.x] = alpha;
  36. }
  37. void Buchstabe::setPixel(int x, int y, unsigned char alpha)
  38. {
  39. this->alpha[x + y * size.x] = alpha;
  40. }
  41. void Buchstabe::setPixel(int i, unsigned char alpha)
  42. {
  43. this->alpha[i] = alpha;
  44. }
  45. void Buchstabe::setSchriftSize(int sg) // setzt die Schriftgröße des Buchstaben
  46. {
  47. schriftSize = sg;
  48. }
  49. int Buchstabe::getSchriftSize() const
  50. {
  51. return schriftSize;
  52. }
  53. // constant
  54. const Punkt& Buchstabe::getSize() const // gibt die Buchstabenbildgröße zurück
  55. {
  56. return size;
  57. }
  58. int Buchstabe::getBreite() const // Buchstabenbreite
  59. {
  60. return size.x;
  61. }
  62. int Buchstabe::getHeight() const // Buchstabenhöhe
  63. {
  64. return size.y;
  65. }
  66. unsigned char* Buchstabe::getBuff() const // gibt den Alphabuffer zurück
  67. {
  68. return alpha;
  69. }
  70. // Inhalt der Alphabet Klasse aus Schrift.h
  71. // Konstruktor
  72. Alphabet::Alphabet()
  73. : ReferenceCounter(),
  74. zeichen(new Buchstabe*[256]),
  75. schriftSize(12)
  76. {
  77. for (int i = 0; i < 256; ++i)
  78. zeichen[i] = 0;
  79. }
  80. // Destruktor
  81. Alphabet::~Alphabet()
  82. {
  83. for (int i = 0; i < 256; ++i)
  84. {
  85. if (zeichen[i]) zeichen[i]->release();
  86. }
  87. delete[] zeichen;
  88. }
  89. // nicht constant
  90. void Alphabet::NeuAlphabet() // Initialisierung
  91. {
  92. for (int i = 0; i < 256; ++i)
  93. {
  94. if (zeichen[i]) zeichen[i]->release();
  95. }
  96. for (int i = 0; i < 256; ++i)
  97. zeichen[i] = 0;
  98. }
  99. void Alphabet::setBuchstabe(
  100. unsigned char i, Buchstabe* buchstabe) // setzt einen Buchstaben
  101. {
  102. if (zeichen[i]) zeichen[i]->release();
  103. zeichen[i] = buchstabe;
  104. if (zeichen[i])
  105. {
  106. zeichen[i]->setSchriftSize(schriftSize);
  107. }
  108. }
  109. void Alphabet::setSchriftSize(int gr) // setzt die Schriftgröße
  110. {
  111. schriftSize = gr;
  112. for (int i = 0; i < 256; ++i)
  113. {
  114. if (zeichen[i]) zeichen[i]->setSchriftSize(gr);
  115. }
  116. }
  117. // constant
  118. Buchstabe* Alphabet::getBuchstabe(
  119. unsigned char i) const // gibt einen Buchstaben zurück
  120. {
  121. if (zeichen[i]) return dynamic_cast<Buchstabe*>(zeichen[i]->getThis());
  122. return 0;
  123. }
  124. Buchstabe* Alphabet::zBuchstabe(unsigned char i) const
  125. {
  126. return zeichen[i];
  127. }
  128. bool Alphabet::hatBuchstabe(unsigned char b) const
  129. {
  130. return zeichen[b] != 0;
  131. }
  132. int Alphabet::getSchriftSize() const // gibt die Schriftgröße zurück
  133. {
  134. return schriftSize;
  135. }
  136. // Inhalt der AlphabetArray Klasse aus Schrift.h
  137. // Konstruktor
  138. AlphabetArray::AlphabetArray()
  139. : next(0),
  140. This(0)
  141. {}
  142. // Destruktor
  143. AlphabetArray::~AlphabetArray()
  144. {
  145. if (This) This->release();
  146. delete next;
  147. }
  148. // nicht constant
  149. bool AlphabetArray::addAlphabet(Alphabet* alphabet) // Fügt ein Alphabet hinzu
  150. {
  151. if (This)
  152. {
  153. if (This->getSchriftSize() == alphabet->getSchriftSize())
  154. {
  155. alphabet->release();
  156. return false;
  157. }
  158. }
  159. else
  160. {
  161. This = alphabet;
  162. return true;
  163. }
  164. if (!next) next = new AlphabetArray();
  165. return next->addAlphabet(alphabet);
  166. }
  167. bool AlphabetArray::removeAlphabet(int sg) // entfernt ein Alphabet
  168. {
  169. if (This)
  170. {
  171. if (This->getSchriftSize() == sg) This = (Alphabet*)This->release();
  172. return 1;
  173. }
  174. if (!next) return 0;
  175. if (next->removeAlphabet(sg))
  176. {
  177. AlphabetArray* tmp = next->getNext();
  178. next->setNext0();
  179. delete next;
  180. next = tmp;
  181. }
  182. return 0;
  183. }
  184. void AlphabetArray::setNext0() // setzt den next Zeiger zu 0
  185. {
  186. next = 0;
  187. }
  188. // constant
  189. Alphabet* AlphabetArray::getAlphabet(
  190. unsigned char sg) const // gibt getThis von einem Alphabet zurück
  191. {
  192. if (!This) return 0;
  193. if (This->getSchriftSize() == sg)
  194. return dynamic_cast<Alphabet*>(This->getThis());
  195. if (next) return next->getAlphabet(sg);
  196. return 0;
  197. }
  198. Alphabet* AlphabetArray::zAlphabet(
  199. unsigned char sg) const // gibt ein Alphabet zurück
  200. {
  201. if (!This) return 0;
  202. if (This->getSchriftSize() == sg) return This;
  203. if (next) return next->zAlphabet(sg);
  204. return 0;
  205. }
  206. Alphabet* AlphabetArray::getAlphabetI(int index, int count) const
  207. {
  208. if (count == index) return dynamic_cast<Alphabet*>(This->getThis());
  209. if (next) return next->getAlphabetI(index, count + 1);
  210. return 0;
  211. }
  212. Alphabet* AlphabetArray::zAlphabetI(int index, int count) const
  213. {
  214. if (count == index) return This;
  215. if (next) return next->zAlphabetI(index, count + 1);
  216. return 0;
  217. }
  218. AlphabetArray*
  219. AlphabetArray::getNext() const // gibt das nächste Alphabet zurück
  220. {
  221. return next;
  222. }
  223. // Inhalt der Schrift Klasse aus Schrift.h
  224. // Konstruktor
  225. Schrift::Schrift()
  226. : ReferenceCounter(),
  227. alphabetAnzahl(0),
  228. alphabet(new AlphabetArray())
  229. {}
  230. // Destruktor
  231. Schrift::~Schrift()
  232. {
  233. delete alphabet;
  234. }
  235. bool Schrift::addAlphabet(
  236. Alphabet* alphabet) // Fügt der Schrift ein Alphabet hinzu
  237. {
  238. if (this->alphabet->addAlphabet(alphabet))
  239. {
  240. ++alphabetAnzahl;
  241. return true;
  242. }
  243. return false;
  244. }
  245. void Schrift::removeAlphabet(int sg) // Entfernt ein Alphabet
  246. {
  247. if (alphabet->removeAlphabet(sg)) --alphabetAnzahl;
  248. }
  249. // constant
  250. Alphabet* Schrift::getAlphabet(int sg) const
  251. {
  252. Alphabet* drawAlphabet = alphabet->zAlphabet((unsigned char)sg);
  253. if (!drawAlphabet)
  254. {
  255. for (int i = 0; i < 256; ++i)
  256. {
  257. drawAlphabet = alphabet->zAlphabet((unsigned char)(sg - i));
  258. if (drawAlphabet) break;
  259. drawAlphabet = alphabet->zAlphabet((unsigned char)(sg + i));
  260. if (drawAlphabet) break;
  261. }
  262. }
  263. return dynamic_cast<Alphabet*>(drawAlphabet->getThis());
  264. }
  265. Alphabet* Schrift::zAlphabet(int sg) const
  266. {
  267. Alphabet* drawAlphabet = alphabet->zAlphabet((unsigned char)sg);
  268. if (!drawAlphabet)
  269. {
  270. for (int i = 0; i < 256; ++i)
  271. {
  272. drawAlphabet = alphabet->zAlphabet((unsigned char)(sg - i));
  273. if (drawAlphabet) break;
  274. drawAlphabet = alphabet->zAlphabet((unsigned char)(sg + i));
  275. if (drawAlphabet) break;
  276. }
  277. }
  278. return drawAlphabet;
  279. }
  280. Alphabet* Schrift::getAlphabetI(int index) const
  281. {
  282. return alphabet->getAlphabetI(index, 0);
  283. }
  284. Alphabet* Schrift::zAlphabetI(int index) const
  285. {
  286. return alphabet->zAlphabetI(index, 0);
  287. }
  288. unsigned char Schrift::getAlphabetAnzahl()
  289. const // gibt die anzahl von in der Schrift enthaltenen Alphabeten zurück
  290. {
  291. return alphabetAnzahl;
  292. }
  293. TextRenderer::TextRenderer()
  294. : TextRenderer(0)
  295. {}
  296. TextRenderer::TextRenderer(Schrift* schrift)
  297. : ReferenceCounter()
  298. {
  299. s = schrift;
  300. schriftSize = 12;
  301. zeilenAbstand = 5;
  302. zeichenAbstand = 0;
  303. }
  304. TextRenderer::~TextRenderer()
  305. {
  306. if (s) s->release();
  307. }
  308. void TextRenderer::setSchriftZ(Schrift* schrift)
  309. {
  310. if (s) s->release();
  311. s = schrift;
  312. }
  313. Schrift* TextRenderer::getSchrift()
  314. {
  315. if (s) return dynamic_cast<Schrift*>(s->getThis());
  316. return 0;
  317. }
  318. Schrift* TextRenderer::zSchrift()
  319. {
  320. return s;
  321. }
  322. // Setzt die Schriftgröße, in der gezeichnet werden soll. Die Schrift wählt
  323. // automatisch das passende Alphabet zum Zeichnen
  324. // sg: Die Schriftgröße
  325. void TextRenderer::setSchriftSize(int sg)
  326. {
  327. schriftSize = sg;
  328. }
  329. // Setzt den Zeilenabstand, der zum zeichnen verwendet werden soll
  330. // za: Der Zeilenabstand zum unteren Ende der darüber liegenden zeile in Pixeln
  331. void TextRenderer::setZeilenAbstand(int za)
  332. {
  333. zeilenAbstand = za;
  334. }
  335. // Setzt den Zeichenabstand, der zum zeichnen verwendet werden soll
  336. // za: Der Zeichenabstand zum unteren Ende der darüber liegenden zeile in
  337. // Pixeln
  338. void TextRenderer::setZeichenAbstand(int za)
  339. {
  340. zeichenAbstand = za;
  341. }
  342. // Fügt Zeilenumbrüche in den Text ein, so dass er bei einer vorgegebenen Breite
  343. // follständig angezeigt wird
  344. // zText: Der text, in den die Zeilenumbrüche eingefügt werden sollen
  345. // maxBreite: Die Breite in Pixeln auf der der Text follständig angezeigt
  346. // werden soll
  347. void TextRenderer::textFormatieren(Text* zTxt, int maxBreite)
  348. {
  349. int lastPos = -1;
  350. int x = 0;
  351. const char* txt = zTxt->getText();
  352. Text result = txt;
  353. int len = zTxt->getLength();
  354. for (int i = 0; i < len; ++i)
  355. {
  356. if (txt[i] == ' ')
  357. {
  358. lastPos = i;
  359. x += schriftSize / 2 + zeichenAbstand;
  360. continue;
  361. }
  362. if (txt[i] == '\t')
  363. {
  364. lastPos = i;
  365. x += schriftSize + zeichenAbstand;
  366. continue;
  367. }
  368. if (txt[i] == '\n')
  369. {
  370. x = 0;
  371. lastPos = -1;
  372. continue;
  373. }
  374. x += getCharWidth(txt[i]) + zeichenAbstand;
  375. if (x > maxBreite && lastPos > -1)
  376. {
  377. result.ersetzen(lastPos, lastPos + 1, "\n");
  378. x = 0;
  379. i = lastPos;
  380. lastPos = -1;
  381. }
  382. }
  383. zTxt->setText(result);
  384. }
  385. // Zeichnet einen Bestimmten Text mit Cursor und einfärbung auf ein Bild
  386. // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe
  387. // zu verändern
  388. // x: x position des ersten zeichens
  389. // y: y position des ersten zeichens
  390. // txt: Der Text, der gezeichnet werden soll
  391. // zRObj: Das Bild, auf das gezeichnet werden soll
  392. // cpos: Die position des Cursors im Text
  393. // cf: Die Farbe des Cursors
  394. // fbeg: Die Position des Zeichens im Text, wo die Einfärbung beginnen soll.
  395. // Der Text wird von dort bis zur Cursorposition eingefärbt ff: Die Hintergrund
  396. // Farbe des eingefärbten Textes f: Eine Funktion die für jeden Buchstaben
  397. // aufgerufen wird und seine Farbe zurückgibt
  398. void TextRenderer::renderText(int x,
  399. int y,
  400. const char* txt,
  401. Bild& zRObj,
  402. std::function<int(int, int, int)> f,
  403. int cpos,
  404. int cf,
  405. int fbeg,
  406. int ff)
  407. {
  408. if (!s) return;
  409. if (fbeg == -1) fbeg = cpos;
  410. int zRObjBr = zRObj.getBreite();
  411. int zRObjHi = zRObj.getHeight();
  412. const Punkt& zRObjOff = zRObj.getDrawOff();
  413. int beginX = x;
  414. int zh = getZeilenHeight();
  415. if (y + (zh + zeilenAbstand) * Text(txt).anzahlVon('\n') + zh + zRObjOff.y
  416. < 0
  417. || x + zRObjOff.x >= zRObjBr || y + zRObjOff.y >= zRObjHi)
  418. return;
  419. bool faerb = 0;
  420. int len = textLength(txt);
  421. for (int i = 0; i < len; ++i)
  422. {
  423. if (i == fbeg) faerb = !faerb;
  424. if (i == cpos)
  425. {
  426. zRObj.drawLinieVAlpha(x, y, zh, cf);
  427. faerb = !faerb;
  428. }
  429. if (txt[i] == ' ')
  430. {
  431. if (faerb)
  432. zRObj.alphaRegion(
  433. x, y, schriftSize / 2 + zeichenAbstand, zh, ff);
  434. x += schriftSize / 2 + zeichenAbstand;
  435. continue;
  436. }
  437. if (txt[i] == '\t')
  438. {
  439. if (faerb)
  440. zRObj.alphaRegion(x, y, schriftSize + zeichenAbstand, zh, ff);
  441. x += schriftSize + zeichenAbstand;
  442. continue;
  443. }
  444. if (txt[i] == '\n')
  445. {
  446. y += zh + zeilenAbstand;
  447. x = beginX;
  448. continue;
  449. }
  450. renderChar(x, y, txt[i], zRObj, f(x, y, i), 0, faerb, ff);
  451. }
  452. if (textLength(txt) == cpos) zRObj.drawLinieVAlpha(x, y, zh, cf);
  453. }
  454. // Zeichnet einen Bestimmten Text mit Cursor und einfärbung auf ein Bild
  455. // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe
  456. // zu verändern
  457. // x: x position des ersten zeichens
  458. // y: y position des ersten zeichens
  459. // txt: Der Text, der gezeichnet werden soll
  460. // zRObj: Das Bild, auf das gezeichnet werden soll
  461. // cpos: Die position des Cursors im Text
  462. // cf: Die Farbe des Cursors
  463. // fbeg: Die Position des Zeichens im Text, wo die Einfärbung beginnen soll.
  464. // Der Text wird von dort bis zur Cursorposition eingefärbt ff: Die Hintergrund
  465. // Farbe des eingefärbten Textes f: Die Farbe, in der der Text gezeichnet
  466. // werden soll
  467. void TextRenderer::renderText(int x,
  468. int y,
  469. const char* txt,
  470. Bild& zRObj,
  471. int f,
  472. int cpos,
  473. int cf,
  474. int fbeg,
  475. int ff)
  476. {
  477. return renderText(
  478. x,
  479. y,
  480. txt,
  481. zRObj,
  482. [f](int a, int b, int c) { return f; },
  483. cpos,
  484. cf,
  485. fbeg,
  486. ff);
  487. }
  488. // Zeichnet einen Bestimmten Buchstaben mit einfärbung auf ein Bild
  489. // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe
  490. // zu verändern
  491. // x: x position des ersten zeichens
  492. // y: y position des ersten zeichens
  493. // txt: Der Text, der gezeichnet werden soll
  494. // zRObj: Das Bild, auf das gezeichnet werden soll
  495. // color: Die Farbe, in der der Text gezeichnet werden soll
  496. // underlined: 1, falls der Text unterstrichen sein soll
  497. // selected: 1, falls das zeichen eingefärbt sein soll
  498. // selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes
  499. void TextRenderer::renderChar(int& x,
  500. int y,
  501. char c,
  502. Bild& zRObj,
  503. int color,
  504. bool underlined,
  505. bool selected,
  506. int selectedBackgroundColor)
  507. {
  508. if (!s) return;
  509. Alphabet* a = s->zAlphabet(schriftSize);
  510. if (!a) return;
  511. Buchstabe* b = a->zBuchstabe(c);
  512. if (b)
  513. {
  514. if (x >= zRObj.getBreite()) return;
  515. if (zRObj.isAreaDrawable(x, y, getCharWidth(c), getCharHeight(c)))
  516. {
  517. if (selected)
  518. {
  519. int br = getCharWidth(c) + zeichenAbstand;
  520. zRObj.alphaRegion(
  521. x, y, br, getZeilenHeight(), selectedBackgroundColor);
  522. }
  523. if (b->getBuff())
  524. {
  525. const Punkt& zRObjGr = zRObj.getDrawGr();
  526. const Punkt& zRObjPos = zRObj.getDrawPos();
  527. const Punkt& zRObjOff = zRObj.getDrawOff();
  528. int xp = x + zRObjOff.x, yp = y + zRObjOff.y;
  529. int xs = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0,
  530. ys = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0;
  531. int br = b->getBreite();
  532. unsigned char a2 = (unsigned char)(255 - (color >> 24));
  533. color &= 0x00FFFFFF;
  534. float xoff = (float)b->getSchriftSize() / (float)schriftSize,
  535. yoff = (float)b->getSchriftSize() / (float)schriftSize;
  536. float x = (float)xs * xoff, y = (float)ys * yoff;
  537. int maxX = getCharWidth(c), maxY = getCharHeight(c);
  538. maxX = (xp + maxX) >= zRObjGr.x ? (zRObjGr.x - xp) : maxX;
  539. maxY = (yp + maxY) >= zRObjGr.y ? (zRObjGr.y - yp) : maxY;
  540. int a, dx, ygr, ygr2;
  541. if (zRObj.hasAlpha3D())
  542. {
  543. for (int dy = ys; dy < maxY; ++dy)
  544. {
  545. ygr2 = (yp + dy) * zRObj.getBreite() + xp;
  546. ygr = (int)y * br;
  547. for (dx = xs; dx < maxX; ++dx)
  548. {
  549. a = b->getBuff()[(int)x + ygr] - a2;
  550. zRObj.alphaPixel3D(dx + ygr2, color | (a << 24));
  551. x += xoff;
  552. }
  553. x = (float)xs;
  554. y += yoff;
  555. }
  556. }
  557. else
  558. {
  559. for (int dy = ys; dy < maxY; ++dy)
  560. {
  561. ygr2 = (yp + dy) * zRObj.getBreite() + xp;
  562. ygr = (int)y * br;
  563. for (dx = xs; dx < maxX; ++dx)
  564. {
  565. a = b->getBuff()[(int)x + ygr] - a2;
  566. zRObj.alphaPixel2D(dx + ygr2, color | (a << 24));
  567. x += xoff;
  568. }
  569. x = (float)xs;
  570. y += yoff;
  571. }
  572. }
  573. }
  574. if (underlined)
  575. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  576. y + getZeilenHeight() + getZeichenAbstand() / 2,
  577. getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5),
  578. 0xFF000000 | color);
  579. }
  580. x += getCharWidth(c) + zeichenAbstand;
  581. }
  582. else if (c == ' ')
  583. {
  584. if (selected)
  585. zRObj.alphaRegion(x,
  586. y,
  587. schriftSize / 2 + zeichenAbstand,
  588. getZeilenHeight(),
  589. selectedBackgroundColor);
  590. if (underlined)
  591. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  592. y + getZeilenHeight() + getZeichenAbstand() / 2,
  593. schriftSize / 2 + zeichenAbstand
  594. + (int)(zeichenAbstand / 2.0 + 0.5),
  595. 0xFF000000 | color);
  596. x += schriftSize / 2 + zeichenAbstand;
  597. }
  598. else if (c == '\t')
  599. {
  600. if (selected)
  601. zRObj.alphaRegion(x,
  602. y,
  603. schriftSize + zeichenAbstand,
  604. getZeilenHeight(),
  605. selectedBackgroundColor);
  606. if (underlined)
  607. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  608. y + getZeilenHeight() + getZeichenAbstand() / 2,
  609. schriftSize + zeichenAbstand
  610. + (int)(zeichenAbstand / 2.0 + 0.5),
  611. 0xFF000000 | color);
  612. x += schriftSize + zeichenAbstand;
  613. }
  614. }
  615. // Gibt die Schriftgröße zurück, die zum Zeichnen verwendet wird
  616. int TextRenderer::getSchriftSize() const
  617. {
  618. return schriftSize;
  619. }
  620. // Gibt den Abstand in Pixeln zum unteren Ende der darüber ligenden Zeile zurück
  621. int TextRenderer::getZeilenabstand() const
  622. {
  623. return zeilenAbstand;
  624. }
  625. // Gibt den Abstand in Pixeln zum zwischen zwei zeichen auf der x Achse zurück
  626. int TextRenderer::getZeichenAbstand() const
  627. {
  628. return zeichenAbstand;
  629. }
  630. // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text
  631. // vollständig darzustellen
  632. // txt: Der Text, von dem die Breite in Pixeln ermitelt werden soll
  633. int TextRenderer::getTextBreite(const char* txt) const
  634. {
  635. int ret = 0;
  636. int tmp = 0;
  637. int len = textLength(txt);
  638. for (int i = 0; i < len; ++i)
  639. {
  640. if (txt[i] == '\n')
  641. {
  642. if (tmp > ret) ret = tmp;
  643. tmp = 0;
  644. }
  645. else if (txt[i] == '\t')
  646. tmp += schriftSize + zeichenAbstand;
  647. else if (txt[i] == ' ')
  648. tmp += schriftSize / 2 + zeichenAbstand;
  649. else
  650. tmp += getCharWidth(txt[i]) + zeichenAbstand;
  651. }
  652. if (tmp > ret) ret = tmp;
  653. return ret;
  654. }
  655. // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text
  656. // vollständig darzustellen
  657. // txt: Der Text, von dem die Höhe in Pixeln ermitelt werden soll
  658. int TextRenderer::getTextHeight(const char* txt) const
  659. {
  660. int hi = getZeilenHeight();
  661. return hi + ((hi + zeilenAbstand) * Text(txt).anzahlVon('\n'));
  662. }
  663. // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Buchstaben
  664. // vollständig darzustellen
  665. // c: Der Buchstabe, von dem die Breite in Pixeln ermitelt werden soll
  666. int TextRenderer::getCharWidth(const char c) const
  667. {
  668. if (!s) return 0;
  669. Alphabet* a = s->zAlphabet(schriftSize);
  670. if (!a) return 0;
  671. Buchstabe* b = a->zBuchstabe(c);
  672. if (b)
  673. return (int)(((double)b->getBreite() / (double)b->getSchriftSize())
  674. * (double)schriftSize
  675. + 0.5);
  676. return 0;
  677. }
  678. // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text
  679. // vollständig darzustellen
  680. // c: Der Buchstabe, von dem die Höhe in Pixeln ermitelt werden soll
  681. int TextRenderer::getCharHeight(const char c) const
  682. {
  683. if (!s) return 0;
  684. Alphabet* a = s->zAlphabet(schriftSize);
  685. if (!a) return 0;
  686. Buchstabe* b = a->zBuchstabe(c);
  687. if (b)
  688. return (int)(((double)b->getHeight() / (double)b->getSchriftSize())
  689. * (double)schriftSize
  690. + 0.5);
  691. return 0;
  692. }
  693. // Gibt den Abstand in Pixeln zum unteren Ende der darüber ligenden Zeile zurück
  694. int TextRenderer::getZeilenAbstand() const
  695. {
  696. return zeilenAbstand;
  697. }
  698. // Gibt die skallierte Höhe zurück, die eine gezeichnete Zeile in Pixeln
  699. // benötigt
  700. int TextRenderer::getZeilenHeight() const
  701. {
  702. int zh = 0;
  703. for (int i = 0; i < 256; ++i)
  704. {
  705. zh = maxInt(getCharHeight((char)i), zh);
  706. }
  707. return zh;
  708. }
  709. // Ermittelt das Zeichen im Text, auf das die Maus zeigt
  710. // txt: Der Text, auf den die Maus Zeigt
  711. // mausX: Die X Position der Maus in Pixeln Relativ zur Position des ersten
  712. // Zeichens mausY: Die Y Position der Maus in Pixeln Relativ zur Position des
  713. // ersten Zeichens
  714. int TextRenderer::textPos(const char* txt, int mausX, int mausY) const
  715. {
  716. int tx = 0;
  717. int ty = 0;
  718. int sh = getZeilenHeight();
  719. if (mausX < 0 || mausY < 0) return -1;
  720. int len = textLength(txt);
  721. for (int i = 0; i < len; ++i)
  722. {
  723. if (txt[i] == '\n')
  724. {
  725. ty += sh + zeilenAbstand;
  726. tx = 0;
  727. if (mausY < ty) return i;
  728. }
  729. if (txt[i] == '\t') tx += schriftSize + zeichenAbstand;
  730. if (txt[i] == ' ') tx += schriftSize / 2 + zeichenAbstand;
  731. tx += getCharWidth(txt[i]);
  732. int txpl = getCharWidth(txt[i + 1]) / 2;
  733. if (mausX < tx - txpl && mausY < ty + sh + zeilenAbstand) return i;
  734. }
  735. if (mausY < ty + sh + zeilenAbstand) return textLength(txt);
  736. return -1;
  737. }
  738. GravurTextRenderer::GravurTextRenderer()
  739. : GravurTextRenderer(0)
  740. {}
  741. GravurTextRenderer::GravurTextRenderer(Schrift* schrift)
  742. : TextRenderer(schrift)
  743. {}
  744. GravurTextRenderer::~GravurTextRenderer() {}
  745. // Zeichnet einen Bestimmten Buchstaben mit einfärbung auf ein Bild
  746. // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe
  747. // zu verändern
  748. // x: x position des ersten zeichens
  749. // y: y position des ersten zeichens
  750. // txt: Der Text, der gezeichnet werden soll
  751. // zRObj: Das Bild, auf das gezeichnet werden soll
  752. // color: Die Farbe, in der der Text gezeichnet werden soll
  753. // underlined: 1, falls der Text unterstrichen sein soll
  754. // selected: 1, falls das zeichen eingefärbt sein soll
  755. // selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes
  756. void GravurTextRenderer::renderChar(int& x,
  757. int y,
  758. char c,
  759. Bild& zRObj,
  760. int color,
  761. bool underlined,
  762. bool selected,
  763. int selectedBackgroundColor)
  764. {
  765. if (!s) return;
  766. Alphabet* a = s->zAlphabet(schriftSize);
  767. Buchstabe* b = a->zBuchstabe(c);
  768. if (b)
  769. {
  770. if (x >= zRObj.getBreite()) return;
  771. if (zRObj.isAreaDrawable(x, y, getCharWidth(c), getCharHeight(c)))
  772. {
  773. if (selected)
  774. {
  775. int br = getCharWidth(c) + zeichenAbstand;
  776. zRObj.alphaRegion(
  777. x, y, br, getZeilenHeight(), selectedBackgroundColor);
  778. }
  779. if (b->getBuff())
  780. {
  781. const Punkt& zRObjGr = zRObj.getDrawGr();
  782. const Punkt& zRObjPos = zRObj.getDrawPos();
  783. const Punkt& zRObjOff = zRObj.getDrawOff();
  784. int xp = x + zRObjOff.x, yp = y + zRObjOff.y;
  785. int xs = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0,
  786. ys = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0;
  787. int br = b->getBreite(), h = b->getHeight();
  788. color &= 0x00FFFFFF;
  789. double xoff = (double)b->getSchriftSize() / (schriftSize * 2.0),
  790. yoff = (double)b->getSchriftSize() / (schriftSize * 2.0);
  791. double x = xs * xoff, y = ys * yoff;
  792. int maxX = getCharWidth(c), maxY = getCharHeight(c);
  793. maxX = (xp + maxX) >= zRObjGr.x ? (zRObjGr.x - xp) : maxX;
  794. maxY = (yp + maxY) >= zRObjGr.y ? (zRObjGr.y - yp) : maxY;
  795. int dx, ygr, ygr2;
  796. if (zRObj.hasAlpha3D())
  797. {
  798. for (int dy = ys; dy < maxY; ++dy)
  799. {
  800. ygr2 = (yp + dy) * zRObj.getBreite();
  801. ygr = (int)y * br;
  802. for (dx = xs; dx < maxX; ++dx)
  803. {
  804. int f = 0;
  805. if (b->getBuff()[(int)x + ygr])
  806. f = 0x50000000;
  807. else if (((int)(x + xoff) < br
  808. && b->getBuff()[(int)(x + xoff) + ygr])
  809. || ((int)(y - yoff) < h
  810. && b->getBuff()[(int)x
  811. + (int)(y - yoff) * br]
  812. > 0xF0))
  813. f = 0xA0000000;
  814. else if (((int)(x - xoff) < br
  815. && b->getBuff()[(int)(x - xoff) + ygr])
  816. || ((int)(y + yoff) < h
  817. && b->getBuff()[(int)x
  818. + (int)(y + yoff) * br]
  819. > 0xF0))
  820. {
  821. f = 0xA0FFFFFF;
  822. }
  823. zRObj.alphaPixel3D(xp + dx + ygr2, f);
  824. x += xoff;
  825. }
  826. x = xs;
  827. y += yoff;
  828. }
  829. }
  830. else
  831. {
  832. for (int dy = ys; dy < maxY; ++dy)
  833. {
  834. ygr2 = (yp + dy) * zRObj.getBreite();
  835. ygr = (int)y * br;
  836. for (dx = xs; dx < maxX; ++dx)
  837. {
  838. int f = 0;
  839. if (b->getBuff()[(int)x + ygr])
  840. f = 0x50000000;
  841. else if (((int)(x + xoff) < br
  842. && b->getBuff()[(int)(x + xoff) + ygr])
  843. || ((int)(y - yoff) < h
  844. && b->getBuff()[(int)x
  845. + (int)(y - yoff) * br]
  846. > 0xF0))
  847. f = 0xA0000000;
  848. else if (((int)(x - xoff) < br
  849. && b->getBuff()[(int)(x - xoff) + ygr])
  850. || ((int)(y + yoff) < h
  851. && b->getBuff()[(int)x
  852. + (int)(y + yoff) * br]
  853. > 0xF0))
  854. {
  855. f = 0xA0FFFFFF;
  856. }
  857. zRObj.alphaPixel2D(xp + dx + ygr2, f);
  858. x += xoff;
  859. }
  860. x = xs;
  861. y += yoff;
  862. }
  863. }
  864. }
  865. if (underlined)
  866. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  867. y + getZeilenHeight() + getZeichenAbstand() / 2,
  868. getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5),
  869. 0xFF000000 | color);
  870. }
  871. x += getCharWidth(c) + zeichenAbstand;
  872. }
  873. else if (c == ' ')
  874. {
  875. if (selected)
  876. zRObj.alphaRegion(x,
  877. y,
  878. schriftSize / 2 + zeichenAbstand,
  879. getZeilenHeight(),
  880. selectedBackgroundColor);
  881. if (underlined)
  882. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  883. y + getZeilenHeight() + getZeichenAbstand() / 2,
  884. schriftSize / 2 + zeichenAbstand
  885. + (int)(zeichenAbstand / 2.0 + 0.5),
  886. 0xFF000000 | color);
  887. x += schriftSize / 2 + zeichenAbstand;
  888. }
  889. else if (c == '\t')
  890. {
  891. if (selected)
  892. zRObj.alphaRegion(x,
  893. y,
  894. schriftSize + zeichenAbstand,
  895. getZeilenHeight(),
  896. selectedBackgroundColor);
  897. if (underlined)
  898. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  899. y + getZeilenHeight() + getZeichenAbstand() / 2,
  900. schriftSize + zeichenAbstand
  901. + (int)(zeichenAbstand / 2.0 + 0.5),
  902. 0xFF000000 | color);
  903. x += schriftSize + zeichenAbstand;
  904. }
  905. }
  906. // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Buchstaben
  907. // vollständig darzustellen
  908. // c: Der Buchstabe, von dem die Breite in Pixeln ermitelt werden soll
  909. int GravurTextRenderer::getCharWidth(const char c) const
  910. {
  911. if (!s) return 0;
  912. Alphabet* a = s->zAlphabet(schriftSize);
  913. Buchstabe* b = a->zBuchstabe(c);
  914. if (b)
  915. return (int)(((double)b->getBreite() / (double)b->getSchriftSize())
  916. * (double)schriftSize * 2
  917. + 0.5);
  918. return 0;
  919. }
  920. // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text
  921. // vollständig darzustellen
  922. // c: Der Buchstabe, von dem die Höhe in Pixeln ermitelt werden soll
  923. int GravurTextRenderer::getCharHeight(const char c) const
  924. {
  925. if (!s) return 0;
  926. Alphabet* a = s->zAlphabet(schriftSize);
  927. Buchstabe* b = a->zBuchstabe(c);
  928. if (b)
  929. return (int)(((double)b->getHeight() / (double)b->getSchriftSize())
  930. * (double)schriftSize * 2
  931. + 0.5);
  932. return 0;
  933. }
  934. KursivTextRenderer::KursivTextRenderer()
  935. : KursivTextRenderer(0)
  936. {}
  937. KursivTextRenderer::KursivTextRenderer(Schrift* schrift)
  938. : TextRenderer(schrift)
  939. {}
  940. KursivTextRenderer::~KursivTextRenderer() {}
  941. // Zeichnet einen Bestimmten Buchstaben mit einfärbung auf ein Bild
  942. // Nutze (setPosition) und (setDrawSchriftGröße) um die Position und die Größe
  943. // zu verändern
  944. // x: x position des ersten zeichens
  945. // y: y position des ersten zeichens
  946. // txt: Der Text, der gezeichnet werden soll
  947. // zRObj: Das Bild, auf das gezeichnet werden soll
  948. // color: Die Farbe, in der der Text gezeichnet werden soll
  949. // underlined: 1, falls der Text unterstrichen sein soll
  950. // selected: 1, falls das zeichen eingefärbt sein soll
  951. // selectedBackgroundColor: Die Hintergrund Farbe des eingefärbten Textes
  952. void KursivTextRenderer::renderChar(int& x,
  953. int y,
  954. char c,
  955. Bild& zRObj,
  956. int color,
  957. bool underlined,
  958. bool selected,
  959. int selectedBackgroundColor)
  960. {
  961. if (!s) return;
  962. Alphabet* a = s->zAlphabet(schriftSize);
  963. if (!a) return;
  964. Buchstabe* b = a->zBuchstabe(c);
  965. if (b)
  966. {
  967. if (x >= zRObj.getBreite()) return;
  968. if (zRObj.isAreaDrawable(x, y, getCharWidth(c), getCharHeight(c)))
  969. {
  970. if (selected)
  971. {
  972. int br = getCharWidth(c) + zeichenAbstand;
  973. zRObj.alphaRegion(
  974. x, y, br, getZeilenHeight(), selectedBackgroundColor);
  975. }
  976. if (b->getBuff())
  977. {
  978. const Punkt& zRObjGr = zRObj.getDrawGr();
  979. const Punkt& zRObjPos = zRObj.getDrawPos();
  980. const Punkt& zRObjOff = zRObj.getDrawOff();
  981. int xp = x + zRObjOff.x, yp = y + zRObjOff.y;
  982. int xStartBuffer = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0,
  983. yStartBuffer = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0;
  984. int bufferBreite = b->getBreite(),
  985. bufferHeight = b->getHeight();
  986. unsigned char colorAlpha = (unsigned char)(255 - (color >> 24));
  987. color &= 0x00FFFFFF;
  988. double xStepBuffer
  989. = (double)b->getSchriftSize() / (double)schriftSize,
  990. yStepBuffer
  991. = (double)b->getSchriftSize() / (double)schriftSize;
  992. double xBuffer = xStartBuffer * xStepBuffer,
  993. yBuffer = yStartBuffer * yStepBuffer;
  994. int charHeight = getCharHeight(c);
  995. int maxXBuffer = getCharWidth(c), maxYBuffer = charHeight;
  996. maxXBuffer = (xp + maxXBuffer) >= zRObjGr.x ? (zRObjGr.x - xp)
  997. : maxXBuffer;
  998. maxYBuffer = (yp + maxYBuffer) >= zRObjGr.y ? (zRObjGr.y - yp)
  999. : maxYBuffer;
  1000. std::function<int(int x, int y)> colorF = [charHeight,
  1001. bufferBreite,
  1002. bufferHeight,
  1003. colorAlpha,
  1004. b,
  1005. color](
  1006. int x, int y) {
  1007. x -= (int)((float)(charHeight - y) / 4.f + 0.5f);
  1008. if (x < 0 || x >= bufferBreite) return 0x00FFFFFF;
  1009. int a = b->getBuff()[y * bufferBreite + x] - colorAlpha;
  1010. return color | (a << 24);
  1011. };
  1012. if (zRObj.hasAlpha3D())
  1013. {
  1014. for (int yS = yStartBuffer; yS < maxYBuffer; ++yS)
  1015. {
  1016. int ygr2 = (yp + yS) * zRObj.getBreite();
  1017. for (int xS = xStartBuffer; xS < maxXBuffer; ++xS)
  1018. {
  1019. zRObj.alphaPixel3D(
  1020. xp + xS + ygr2, colorF((int)xS, (int)yS));
  1021. xBuffer += xStepBuffer;
  1022. }
  1023. xBuffer = xStartBuffer;
  1024. yBuffer += yStepBuffer;
  1025. }
  1026. }
  1027. else
  1028. {
  1029. for (int yS = yStartBuffer; yS < maxYBuffer; ++yS)
  1030. {
  1031. int ygr2 = (yp + yS) * zRObj.getBreite();
  1032. for (int xS = xStartBuffer; xS < maxXBuffer; ++xS)
  1033. {
  1034. zRObj.alphaPixel2D(
  1035. xp + xS + ygr2, colorF((int)xS, (int)yS));
  1036. xBuffer += xStepBuffer;
  1037. }
  1038. xBuffer = xStartBuffer;
  1039. yBuffer += yStepBuffer;
  1040. }
  1041. }
  1042. }
  1043. if (underlined)
  1044. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  1045. y + getZeilenHeight() + getZeichenAbstand() / 2,
  1046. getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5),
  1047. 0xFF000000 | color);
  1048. }
  1049. x += getCharWidth(c) + zeichenAbstand;
  1050. }
  1051. else if (c == ' ')
  1052. {
  1053. if (selected)
  1054. zRObj.alphaRegion(x,
  1055. y,
  1056. schriftSize / 2 + zeichenAbstand,
  1057. getZeilenHeight(),
  1058. selectedBackgroundColor);
  1059. if (underlined)
  1060. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  1061. y + getZeilenHeight() + getZeichenAbstand() / 2,
  1062. schriftSize / 2 + zeichenAbstand
  1063. + (int)(zeichenAbstand / 2.0 + 0.5),
  1064. 0xFF000000 | color);
  1065. x += schriftSize / 2 + zeichenAbstand;
  1066. }
  1067. else if (c == '\t')
  1068. {
  1069. if (selected)
  1070. zRObj.alphaRegion(x,
  1071. y,
  1072. schriftSize + zeichenAbstand,
  1073. getZeilenHeight(),
  1074. selectedBackgroundColor);
  1075. if (underlined)
  1076. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  1077. y + getZeilenHeight() + getZeichenAbstand() / 2,
  1078. schriftSize + zeichenAbstand
  1079. + (int)(zeichenAbstand / 2.0 + 0.5),
  1080. 0xFF000000 | color);
  1081. x += schriftSize + zeichenAbstand;
  1082. }
  1083. }
  1084. // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Buchstaben
  1085. // vollständig darzustellen
  1086. // c: Der Buchstabe, von dem die Breite in Pixeln ermitelt werden soll
  1087. int KursivTextRenderer::getCharWidth(const char c) const
  1088. {
  1089. if (!s) return 0;
  1090. Alphabet* a = s->zAlphabet(schriftSize);
  1091. Buchstabe* b = a->zBuchstabe(c);
  1092. if (b)
  1093. return (int)(((double)b->getBreite() / (double)b->getSchriftSize())
  1094. * (double)schriftSize
  1095. + getCharHeight(c) / 4.0 + 0.5);
  1096. return 0;
  1097. }
  1098. // Ermittelt, wie viele Pixel benötigt werden, um einen Bestimmten Text
  1099. // vollständig darzustellen
  1100. // c: Der Buchstabe, von dem die Höhe in Pixeln ermitelt werden soll
  1101. int KursivTextRenderer::getCharHeight(const char c) const
  1102. {
  1103. if (!s) return 0;
  1104. Alphabet* a = s->zAlphabet(schriftSize);
  1105. Buchstabe* b = a->zBuchstabe(c);
  1106. if (b)
  1107. return (int)(((double)b->getHeight() / (double)b->getSchriftSize())
  1108. * (double)schriftSize
  1109. + 0.5);
  1110. return 0;
  1111. }