Schrift.cpp 36 KB

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