Schrift.cpp 37 KB

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