Font.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  1. #include "Font.h"
  2. #include "Image.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. // Contents of the Buchstabe class from Font.h
  12. // Constructor
  13. Buchstabe::Buchstabe()
  14. : ReferenceCounter(),
  15. size(0, 0),
  16. alpha(0),
  17. schriftSize(0)
  18. {}
  19. // Destructor
  20. Buchstabe::~Buchstabe()
  21. {
  22. if (alpha) delete[] alpha;
  23. }
  24. // non-constant
  25. void Buchstabe::NeuBuchstabe(Punkt& size) // Initialization
  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) // sets the alpha value of the pixel
  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) // sets the font size of the character
  46. {
  47. schriftSize = sg;
  48. }
  49. int Buchstabe::getSchriftSize() const
  50. {
  51. return schriftSize;
  52. }
  53. // constant
  54. const Punkt& Buchstabe::getSize() const // returns the character image size
  55. {
  56. return size;
  57. }
  58. int Buchstabe::getBreite() const // character width
  59. {
  60. return size.x;
  61. }
  62. int Buchstabe::getHeight() const // character height
  63. {
  64. return size.y;
  65. }
  66. unsigned char* Buchstabe::getBuff() const // returns the alpha buffer
  67. {
  68. return alpha;
  69. }
  70. // Contents of the Alphabet class from Font.h
  71. // Constructor
  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. // Destructor
  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. // non-constant
  90. void Alphabet::NeuAlphabet() // Initialization
  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) // sets a character
  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) // sets the font size
  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 // returns a character
  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 // returns the font size
  133. {
  134. return schriftSize;
  135. }
  136. // Contents of the AlphabetArray class from Font.h
  137. // Constructor
  138. AlphabetArray::AlphabetArray()
  139. {
  140. memset(alphabets, 0, sizeof(Alphabet*) * 256);
  141. }
  142. // non-constant
  143. bool AlphabetArray::addAlphabet(Alphabet* alphabet) // Adds an alphabet
  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) // removes an 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 // returns getThis of an alphabet
  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 // returns an alphabet
  172. {
  173. return alphabets[sg];
  174. }
  175. // Contents of the Schrift class from Font.h
  176. // Constructor
  177. Schrift::Schrift()
  178. : ReferenceCounter(),
  179. alphabetAnzahl(0),
  180. alphabet(new AlphabetArray())
  181. {}
  182. // Destructor
  183. Schrift::~Schrift()
  184. {
  185. delete alphabet;
  186. }
  187. bool Schrift::addAlphabet(
  188. Alphabet* alphabet) // Adds an alphabet to the font
  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) // Removes an 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 // returns the number of alphabets contained in the font
  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. // Sets the font size to draw with. The font automatically selects the
  313. // appropriate alphabet for drawing
  314. // sg: The font size
  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. // Sets the line spacing to use for drawing
  349. // za: The line spacing to the bottom of the line above in pixels
  350. void TextRenderer::setZeilenAbstand(int za)
  351. {
  352. zeilenAbstand = za;
  353. }
  354. // Sets the character spacing to use for drawing
  355. // za: The character spacing in pixels
  356. void TextRenderer::setZeichenAbstand(int za)
  357. {
  358. zeichenAbstand = za;
  359. }
  360. // Inserts line breaks into the text so it is fully displayed at a given width
  361. // zText: The text to insert line breaks into
  362. // maxBreite: The width in pixels at which the text should be fully displayed
  363. void TextRenderer::textFormatieren(Text* zTxt, int maxBreite)
  364. {
  365. int lastPos = -1;
  366. int x = 0;
  367. const char* txt = zTxt->getText();
  368. Text result = txt;
  369. int len = zTxt->getLength();
  370. for (int i = 0; i < len; ++i)
  371. {
  372. if (txt[i] == ' ')
  373. {
  374. lastPos = i;
  375. x += schriftSize / 2 + zeichenAbstand;
  376. continue;
  377. }
  378. if (txt[i] == '\t')
  379. {
  380. lastPos = i;
  381. x += schriftSize + zeichenAbstand;
  382. continue;
  383. }
  384. if (txt[i] == '\n')
  385. {
  386. x = 0;
  387. lastPos = -1;
  388. continue;
  389. }
  390. x += getCharWidth(txt[i]) + zeichenAbstand;
  391. if (x > maxBreite && lastPos > -1)
  392. {
  393. result.ersetzen(lastPos, lastPos + 1, "\n");
  394. x = 0;
  395. i = lastPos;
  396. lastPos = -1;
  397. }
  398. }
  399. zTxt->setText(result);
  400. }
  401. // Draws a specific text with cursor and coloring onto an image
  402. // Use (setPosition) and (setDrawSchriftGroesse) to change position and size
  403. // x: x position of the first character
  404. // y: y position of the first character
  405. // txt: The text to draw
  406. // zRObj: The image to draw on
  407. // cpos: The position of the cursor in the text
  408. // cf: The color of the cursor
  409. // fbeg: The position of the character in the text where coloring should begin.
  410. // The text is colored from there to the cursor position
  411. // ff: The background color of the colored text
  412. // f: A function called for each character that returns its color
  413. void TextRenderer::renderText(int x,
  414. int y,
  415. const char* txt,
  416. Bild& zRObj,
  417. std::function<int(int, int, int)> f,
  418. int cpos,
  419. int cf,
  420. int fbeg,
  421. int ff)
  422. {
  423. if (!s) return;
  424. if (fbeg == -1) fbeg = cpos;
  425. int zRObjBr = zRObj.getBreite();
  426. int zRObjHi = zRObj.getHeight();
  427. const Punkt& zRObjOff = zRObj.getDrawOff();
  428. int beginX = x;
  429. int zh = getZeilenHeight();
  430. if (y + (zh + zeilenAbstand) * Text(txt).anzahlVon('\n') + zh + zRObjOff.y
  431. < 0
  432. || x + zRObjOff.x >= zRObjBr || y + zRObjOff.y >= zRObjHi)
  433. return;
  434. bool faerb = 0;
  435. int len = textLength(txt);
  436. for (int i = 0; i < len; ++i)
  437. {
  438. if (i == fbeg) faerb = !faerb;
  439. if (i == cpos)
  440. {
  441. zRObj.drawLinieVAlpha(x, y, zh, cf);
  442. faerb = !faerb;
  443. }
  444. if (txt[i] == ' ')
  445. {
  446. if (faerb)
  447. zRObj.alphaRegion(
  448. x, y, schriftSize / 2 + zeichenAbstand, zh, ff);
  449. x += schriftSize / 2 + zeichenAbstand;
  450. continue;
  451. }
  452. if (txt[i] == '\t')
  453. {
  454. if (faerb)
  455. zRObj.alphaRegion(x, y, schriftSize + zeichenAbstand, zh, ff);
  456. x += schriftSize + zeichenAbstand;
  457. continue;
  458. }
  459. if (txt[i] == '\n')
  460. {
  461. y += zh + zeilenAbstand;
  462. x = beginX;
  463. continue;
  464. }
  465. renderChar(x, y, txt[i], zRObj, f(x, y, i), 0, faerb, ff);
  466. }
  467. if (textLength(txt) == cpos) zRObj.drawLinieVAlpha(x, y, zh, cf);
  468. }
  469. // Draws a specific text with cursor and coloring onto an image
  470. // Use (setPosition) and (setDrawSchriftGroesse) to change position and size
  471. // x: x position of the first character
  472. // y: y position of the first character
  473. // txt: The text to draw
  474. // zRObj: The image to draw on
  475. // cpos: The position of the cursor in the text
  476. // cf: The color of the cursor
  477. // fbeg: The position of the character in the text where coloring should begin.
  478. // The text is colored from there to the cursor position
  479. // ff: The background color of the colored text
  480. // f: The color in which the text should be drawn
  481. void TextRenderer::renderText(int x,
  482. int y,
  483. const char* txt,
  484. Bild& zRObj,
  485. int f,
  486. int cpos,
  487. int cf,
  488. int fbeg,
  489. int ff)
  490. {
  491. return renderText(
  492. x,
  493. y,
  494. txt,
  495. zRObj,
  496. [f](int a, int b, int c) { return f; },
  497. cpos,
  498. cf,
  499. fbeg,
  500. ff);
  501. }
  502. // Draws a specific character with coloring onto an image
  503. // Use (setPosition) and (setDrawSchriftGroesse) to change position and size
  504. // x: x position of the first character
  505. // y: y position of the first character
  506. // txt: The text to draw
  507. // zRObj: The image to draw on
  508. // color: The color in which the text should be drawn
  509. // underlined: 1 if the text should be underlined
  510. // selected: 1 if the character should be colored
  511. // selectedBackgroundColor: The background color of the colored text
  512. void TextRenderer::renderChar(int& x,
  513. int y,
  514. char c,
  515. Bild& zRObj,
  516. int color,
  517. bool underlined,
  518. bool selected,
  519. int selectedBackgroundColor)
  520. {
  521. if (!s) return;
  522. Alphabet* a = s->zAlphabet((unsigned char)schriftSize);
  523. if (!a) return;
  524. Buchstabe* b = a->zBuchstabe(c);
  525. if (b)
  526. {
  527. if (x >= zRObj.getBreite()) return;
  528. if (zRObj.isAreaDrawable(x, y, getCharWidth(c), getCharHeight(c)))
  529. {
  530. if (selected)
  531. {
  532. int br = getCharWidth(c) + zeichenAbstand;
  533. zRObj.alphaRegion(x,
  534. y,
  535. br,
  536. getZeilenHeight() + zeilenAbstand,
  537. selectedBackgroundColor);
  538. }
  539. if (b->getBuff())
  540. {
  541. const Punkt& zRObjGr = zRObj.getDrawGr();
  542. const Punkt& zRObjPos = zRObj.getDrawPos();
  543. const Punkt& zRObjOff = zRObj.getDrawOff();
  544. int xp = x + zRObjOff.x, yp = y + zRObjOff.y;
  545. int xs = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0,
  546. ys = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0;
  547. int br = b->getBreite();
  548. unsigned char a2 = (unsigned char)(255 - (color >> 24));
  549. color &= 0x00FFFFFF;
  550. float xoff = (float)b->getSchriftSize() / (float)schriftSize,
  551. yoff = (float)b->getSchriftSize() / (float)schriftSize;
  552. float x = (float)xs * xoff, y = (float)ys * yoff;
  553. int maxX = getCharWidth(c), maxY = getCharHeight(c);
  554. maxX = (xp + maxX) >= zRObjGr.x ? (zRObjGr.x - xp) : maxX;
  555. maxY = (yp + maxY) >= zRObjGr.y ? (zRObjGr.y - yp) : maxY;
  556. int a, dx, ygr, ygr2;
  557. if (zRObj.hasAlpha3D())
  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.alphaPixel3D(dx + ygr2, color | (a << 24));
  567. x += xoff;
  568. }
  569. x = (float)xs;
  570. y += yoff;
  571. }
  572. }
  573. else
  574. {
  575. for (int dy = ys; dy < maxY; ++dy)
  576. {
  577. ygr2 = (yp + dy) * zRObj.getBreite() + xp;
  578. ygr = (int)y * br;
  579. for (dx = xs; dx < maxX; ++dx)
  580. {
  581. a = b->getBuff()[(int)x + ygr] - a2;
  582. zRObj.alphaPixel2D(dx + ygr2, color | (a << 24));
  583. x += xoff;
  584. }
  585. x = (float)xs;
  586. y += yoff;
  587. }
  588. }
  589. }
  590. if (underlined)
  591. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  592. y + getZeilenHeight() + getZeichenAbstand() / 2,
  593. getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5),
  594. 0xFF000000 | color);
  595. }
  596. x += getCharWidth(c) + zeichenAbstand;
  597. }
  598. else if (c == ' ')
  599. {
  600. if (selected)
  601. zRObj.alphaRegion(x,
  602. y,
  603. schriftSize / 2 + zeichenAbstand,
  604. getZeilenHeight() + zeilenAbstand,
  605. selectedBackgroundColor);
  606. if (underlined)
  607. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  608. y + getZeilenHeight() + getZeichenAbstand() / 2,
  609. schriftSize / 2 + zeichenAbstand
  610. + (int)(zeichenAbstand / 2.0 + 0.5),
  611. 0xFF000000 | color);
  612. x += schriftSize / 2 + zeichenAbstand;
  613. }
  614. else if (c == '\t')
  615. {
  616. if (selected)
  617. zRObj.alphaRegion(x,
  618. y,
  619. schriftSize + zeichenAbstand,
  620. getZeilenHeight() + zeilenAbstand,
  621. selectedBackgroundColor);
  622. if (underlined)
  623. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  624. y + getZeilenHeight() + getZeichenAbstand() / 2,
  625. schriftSize + zeichenAbstand
  626. + (int)(zeichenAbstand / 2.0 + 0.5),
  627. 0xFF000000 | color);
  628. x += schriftSize + zeichenAbstand;
  629. }
  630. }
  631. // Returns the font size used for drawing
  632. int TextRenderer::getSchriftSize() const
  633. {
  634. return schriftSize;
  635. }
  636. // Returns the character spacing in pixels on the x axis
  637. int TextRenderer::getZeichenAbstand() const
  638. {
  639. return zeichenAbstand;
  640. }
  641. // Determines how many pixels are needed to fully display a specific text
  642. // txt: The text whose width in pixels should be determined
  643. int TextRenderer::getTextBreite(const char* txt) const
  644. {
  645. int ret = 0;
  646. int tmp = 0;
  647. int len = textLength(txt);
  648. for (int i = 0; i < len; ++i)
  649. {
  650. if (txt[i] == '\n')
  651. {
  652. if (tmp > ret) ret = tmp;
  653. tmp = 0;
  654. }
  655. else
  656. tmp += getCharWidth(txt[i]) + zeichenAbstand;
  657. }
  658. if (tmp > ret) ret = tmp;
  659. return ret;
  660. }
  661. // Determines how many pixels are needed to fully display a specific text
  662. // txt: The text whose height in pixels should be determined
  663. int TextRenderer::getTextHeight(const char* txt) const
  664. {
  665. int hi = getZeilenHeight();
  666. return hi + ((hi + zeilenAbstand) * Text(txt).anzahlVon('\n'));
  667. }
  668. // Determines how many pixels are needed to fully display a specific character
  669. // c: The character whose width in pixels should be determined
  670. int TextRenderer::getCharWidth(const char c) const
  671. {
  672. if (c == '\t')
  673. return schriftSize;
  674. else if (c == ' ')
  675. return schriftSize / 2;
  676. else
  677. return charWidths[(unsigned char)c];
  678. }
  679. int Framework::TextRenderer::getMaxCharWidth() const
  680. {
  681. int result = 0;
  682. for (int i = 0; i < 256; i++)
  683. {
  684. result = MAX(result, getCharWidth((char)i));
  685. }
  686. return result;
  687. }
  688. // Determines how many pixels are needed to fully display a specific character
  689. // c: The character whose height in pixels should be determined
  690. int TextRenderer::getCharHeight(const char c) const
  691. {
  692. return charHeights[(unsigned char)c];
  693. }
  694. // Returns the line spacing in pixels to the bottom of the line above
  695. int TextRenderer::getZeilenAbstand() const
  696. {
  697. return zeilenAbstand;
  698. }
  699. // Returns the scaled height needed by a drawn line in pixels
  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. // Determines the character in the text that the mouse points to
  710. // txt: The text the mouse points to
  711. // mausX: The X position of the mouse in pixels relative to the position of
  712. // the first character
  713. // mausY: The Y position of the mouse in pixels relative to the position of
  714. // the first character
  715. int TextRenderer::textPos(const char* txt, int mausX, int mausY) const
  716. {
  717. int tx = 0;
  718. int ty = 0;
  719. int sh = getZeilenHeight();
  720. if (mausX < 0 || mausY < 0) return -1;
  721. int len = textLength(txt);
  722. for (int i = 0; i < len; ++i)
  723. {
  724. if (txt[i] == '\n')
  725. {
  726. ty += sh + zeilenAbstand;
  727. tx = 0;
  728. if (mausY < ty) return i;
  729. }
  730. if (txt[i] == '\t')
  731. {
  732. tx += schriftSize + zeichenAbstand;
  733. }
  734. else if (txt[i] == ' ')
  735. {
  736. tx += schriftSize / 2 + zeichenAbstand;
  737. }
  738. else
  739. {
  740. tx += getCharWidth(txt[i]) + zeichenAbstand;
  741. }
  742. int txpl = getCharWidth(txt[i]) / 2;
  743. if (mausX < tx - txpl && mausY < ty + sh + zeilenAbstand) return i;
  744. }
  745. if (mausY < ty + sh + zeilenAbstand) return textLength(txt);
  746. return -1;
  747. }
  748. GravurTextRenderer::GravurTextRenderer()
  749. : GravurTextRenderer(0)
  750. {}
  751. GravurTextRenderer::GravurTextRenderer(Schrift* schrift)
  752. : TextRenderer(schrift)
  753. {}
  754. GravurTextRenderer::~GravurTextRenderer() {}
  755. // Draws a specific character with coloring onto an image
  756. // Use (setPosition) and (setDrawSchriftGroesse) to change position and size
  757. // x: x position of the first character
  758. // y: y position of the first character
  759. // txt: The text to draw
  760. // zRObj: The image to draw on
  761. // color: The color in which the text should be drawn
  762. // underlined: 1 if the text should be underlined
  763. // selected: 1 if the character should be colored
  764. // selectedBackgroundColor: The background color of the colored text
  765. void GravurTextRenderer::renderChar(int& x,
  766. int y,
  767. char c,
  768. Bild& zRObj,
  769. int color,
  770. bool underlined,
  771. bool selected,
  772. int selectedBackgroundColor)
  773. {
  774. if (!s) return;
  775. Alphabet* a = s->zAlphabet((unsigned char)schriftSize);
  776. Buchstabe* b = a->zBuchstabe(c);
  777. if (b)
  778. {
  779. if (x >= zRObj.getBreite()) return;
  780. if (zRObj.isAreaDrawable(x, y, getCharWidth(c), getCharHeight(c)))
  781. {
  782. if (selected)
  783. {
  784. int br = getCharWidth(c) + zeichenAbstand;
  785. zRObj.alphaRegion(x,
  786. y,
  787. br,
  788. getZeilenHeight() + zeilenAbstand,
  789. selectedBackgroundColor);
  790. }
  791. if (b->getBuff())
  792. {
  793. const Punkt& zRObjGr = zRObj.getDrawGr();
  794. const Punkt& zRObjPos = zRObj.getDrawPos();
  795. const Punkt& zRObjOff = zRObj.getDrawOff();
  796. int xp = x + zRObjOff.x, yp = y + zRObjOff.y;
  797. int xs = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0,
  798. ys = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0;
  799. int br = b->getBreite(), h = b->getHeight();
  800. color &= 0x00FFFFFF;
  801. double xoff = (double)b->getSchriftSize() / (schriftSize * 2.0),
  802. yoff = (double)b->getSchriftSize() / (schriftSize * 2.0);
  803. double x = xs * xoff, y = ys * yoff;
  804. int maxX = getCharWidth(c), maxY = getCharHeight(c);
  805. maxX = (xp + maxX) >= zRObjGr.x ? (zRObjGr.x - xp) : maxX;
  806. maxY = (yp + maxY) >= zRObjGr.y ? (zRObjGr.y - yp) : maxY;
  807. int dx, ygr, ygr2;
  808. if (zRObj.hasAlpha3D())
  809. {
  810. for (int dy = ys; dy < maxY; ++dy)
  811. {
  812. ygr2 = (yp + dy) * zRObj.getBreite();
  813. ygr = (int)y * br;
  814. for (dx = xs; dx < maxX; ++dx)
  815. {
  816. int f = 0;
  817. if (b->getBuff()[(int)x + ygr])
  818. f = 0x50000000;
  819. else if (((int)(x + xoff) < br
  820. && b->getBuff()[(int)(x + xoff) + ygr])
  821. || ((int)(y - yoff) < h
  822. && b->getBuff()[(int)x
  823. + (int)(y - yoff) * br]
  824. > 0xF0))
  825. f = 0xA0000000;
  826. else if (((int)(x - xoff) < br
  827. && b->getBuff()[(int)(x - xoff) + ygr])
  828. || ((int)(y + yoff) < h
  829. && b->getBuff()[(int)x
  830. + (int)(y + yoff) * br]
  831. > 0xF0))
  832. {
  833. f = 0xA0FFFFFF;
  834. }
  835. zRObj.alphaPixel3D(xp + dx + ygr2, f);
  836. x += xoff;
  837. }
  838. x = xs;
  839. y += yoff;
  840. }
  841. }
  842. else
  843. {
  844. for (int dy = ys; dy < maxY; ++dy)
  845. {
  846. ygr2 = (yp + dy) * zRObj.getBreite();
  847. ygr = (int)y * br;
  848. for (dx = xs; dx < maxX; ++dx)
  849. {
  850. int f = 0;
  851. if (b->getBuff()[(int)x + ygr])
  852. f = 0x50000000;
  853. else if (((int)(x + xoff) < br
  854. && b->getBuff()[(int)(x + xoff) + ygr])
  855. || ((int)(y - yoff) < h
  856. && b->getBuff()[(int)x
  857. + (int)(y - yoff) * br]
  858. > 0xF0))
  859. f = 0xA0000000;
  860. else if (((int)(x - xoff) < br
  861. && b->getBuff()[(int)(x - xoff) + ygr])
  862. || ((int)(y + yoff) < h
  863. && b->getBuff()[(int)x
  864. + (int)(y + yoff) * br]
  865. > 0xF0))
  866. {
  867. f = 0xA0FFFFFF;
  868. }
  869. zRObj.alphaPixel2D(xp + dx + ygr2, f);
  870. x += xoff;
  871. }
  872. x = xs;
  873. y += yoff;
  874. }
  875. }
  876. }
  877. if (underlined)
  878. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  879. y + getZeilenHeight() + getZeichenAbstand() / 2,
  880. getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5),
  881. 0xFF000000 | color);
  882. }
  883. x += getCharWidth(c) + zeichenAbstand;
  884. }
  885. else if (c == ' ')
  886. {
  887. if (selected)
  888. zRObj.alphaRegion(x,
  889. y,
  890. schriftSize / 2 + zeichenAbstand,
  891. getZeilenHeight() + zeilenAbstand,
  892. selectedBackgroundColor);
  893. if (underlined)
  894. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  895. y + getZeilenHeight() + getZeichenAbstand() / 2,
  896. schriftSize / 2 + zeichenAbstand
  897. + (int)(zeichenAbstand / 2.0 + 0.5),
  898. 0xFF000000 | color);
  899. x += schriftSize / 2 + zeichenAbstand;
  900. }
  901. else if (c == '\t')
  902. {
  903. if (selected)
  904. zRObj.alphaRegion(x,
  905. y,
  906. schriftSize + zeichenAbstand,
  907. getZeilenHeight() + zeilenAbstand,
  908. selectedBackgroundColor);
  909. if (underlined)
  910. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  911. y + getZeilenHeight() + getZeichenAbstand() / 2,
  912. schriftSize + zeichenAbstand
  913. + (int)(zeichenAbstand / 2.0 + 0.5),
  914. 0xFF000000 | color);
  915. x += schriftSize + zeichenAbstand;
  916. }
  917. }
  918. // Determines how many pixels are needed to fully display a specific character
  919. // c: The character whose width in pixels should be determined
  920. int GravurTextRenderer::getCharWidth(const char c) const
  921. {
  922. if (c == '\t')
  923. return schriftSize;
  924. else if (c == ' ')
  925. return schriftSize / 2;
  926. else
  927. return TextRenderer::getCharWidth(c) * 2;
  928. }
  929. // Determines how many pixels are needed to fully display a specific character
  930. // c: The character whose height in pixels should be determined
  931. int GravurTextRenderer::getCharHeight(const char c) const
  932. {
  933. return TextRenderer::getCharHeight(c) * 2;
  934. }
  935. KursivTextRenderer::KursivTextRenderer()
  936. : KursivTextRenderer(0)
  937. {}
  938. KursivTextRenderer::KursivTextRenderer(Schrift* schrift)
  939. : TextRenderer(schrift)
  940. {}
  941. KursivTextRenderer::~KursivTextRenderer() {}
  942. // Draws a specific character with coloring onto an image
  943. // Use (setPosition) and (setDrawSchriftGroesse) to change position and size
  944. // x: x position of the first character
  945. // y: y position of the first character
  946. // txt: The text to draw
  947. // zRObj: The image to draw on
  948. // color: The color in which the text should be drawn
  949. // underlined: 1 if the text should be underlined
  950. // selected: 1 if the character should be colored
  951. // selectedBackgroundColor: The background color of the colored text
  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((unsigned char)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(x,
  974. y,
  975. br,
  976. getZeilenHeight() + zeilenAbstand,
  977. selectedBackgroundColor);
  978. }
  979. if (b->getBuff())
  980. {
  981. const Punkt& zRObjGr = zRObj.getDrawGr();
  982. const Punkt& zRObjPos = zRObj.getDrawPos();
  983. const Punkt& zRObjOff = zRObj.getDrawOff();
  984. int xp = x + zRObjOff.x, yp = y + zRObjOff.y;
  985. int xStartBuffer = xp < zRObjPos.x ? (zRObjPos.x - xp) : 0,
  986. yStartBuffer = yp < zRObjPos.y ? (zRObjPos.y - yp) : 0;
  987. int bufferBreite = b->getBreite(),
  988. bufferHeight = b->getHeight();
  989. unsigned char colorAlpha = (unsigned char)(255 - (color >> 24));
  990. color &= 0x00FFFFFF;
  991. double xStepBuffer
  992. = (double)b->getSchriftSize() / (double)schriftSize,
  993. yStepBuffer
  994. = (double)b->getSchriftSize() / (double)schriftSize;
  995. double xBuffer = xStartBuffer * xStepBuffer,
  996. yBuffer = yStartBuffer * yStepBuffer;
  997. int charHeight = getCharHeight(c);
  998. int maxXBuffer = getCharWidth(c), maxYBuffer = charHeight;
  999. maxXBuffer = (xp + maxXBuffer) >= zRObjGr.x ? (zRObjGr.x - xp)
  1000. : maxXBuffer;
  1001. maxYBuffer = (yp + maxYBuffer) >= zRObjGr.y ? (zRObjGr.y - yp)
  1002. : maxYBuffer;
  1003. std::function<int(int x, int y)> colorF = [charHeight,
  1004. bufferBreite,
  1005. bufferHeight,
  1006. colorAlpha,
  1007. b,
  1008. color](
  1009. int xx, int yy) {
  1010. xx -= (int)((float)(charHeight - yy) / 4.f + 0.5f);
  1011. if (xx < 0 || xx >= bufferBreite) return 0x00FFFFFF;
  1012. int a = b->getBuff()[yy * bufferBreite + xx] - colorAlpha;
  1013. return color | (a << 24);
  1014. };
  1015. if (zRObj.hasAlpha3D())
  1016. {
  1017. for (int yS = yStartBuffer; yS < maxYBuffer; ++yS)
  1018. {
  1019. int ygr2 = (yp + yS) * zRObj.getBreite();
  1020. for (int xS = xStartBuffer; xS < maxXBuffer; ++xS)
  1021. {
  1022. zRObj.alphaPixel3D(
  1023. xp + xS + ygr2, colorF((int)xS, (int)yS));
  1024. xBuffer += xStepBuffer;
  1025. }
  1026. xBuffer = xStartBuffer;
  1027. yBuffer += yStepBuffer;
  1028. }
  1029. }
  1030. else
  1031. {
  1032. for (int yS = yStartBuffer; yS < maxYBuffer; ++yS)
  1033. {
  1034. int ygr2 = (yp + yS) * zRObj.getBreite();
  1035. for (int xS = xStartBuffer; xS < maxXBuffer; ++xS)
  1036. {
  1037. zRObj.alphaPixel2D(
  1038. xp + xS + ygr2, colorF((int)xS, (int)yS));
  1039. xBuffer += xStepBuffer;
  1040. }
  1041. xBuffer = xStartBuffer;
  1042. yBuffer += yStepBuffer;
  1043. }
  1044. }
  1045. }
  1046. if (underlined)
  1047. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  1048. y + getZeilenHeight() + getZeichenAbstand() / 2,
  1049. getCharWidth(c) + (int)(zeichenAbstand / 2.0 + 0.5),
  1050. 0xFF000000 | color);
  1051. }
  1052. x += getCharWidth(c) + zeichenAbstand;
  1053. }
  1054. else if (c == ' ')
  1055. {
  1056. if (selected)
  1057. zRObj.alphaRegion(x,
  1058. y,
  1059. schriftSize / 2 + zeichenAbstand,
  1060. getZeilenHeight() + zeilenAbstand,
  1061. selectedBackgroundColor);
  1062. if (underlined)
  1063. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  1064. y + getZeilenHeight() + getZeichenAbstand() / 2,
  1065. schriftSize / 2 + zeichenAbstand
  1066. + (int)(zeichenAbstand / 2.0 + 0.5),
  1067. 0xFF000000 | color);
  1068. x += schriftSize / 2 + zeichenAbstand;
  1069. }
  1070. else if (c == '\t')
  1071. {
  1072. if (selected)
  1073. zRObj.alphaRegion(x,
  1074. y,
  1075. schriftSize + zeichenAbstand,
  1076. getZeilenHeight() + zeilenAbstand,
  1077. selectedBackgroundColor);
  1078. if (underlined)
  1079. zRObj.drawLinieHAlpha(x - (int)(zeichenAbstand / 2.0 + 0.5),
  1080. y + getZeilenHeight() + getZeichenAbstand() / 2,
  1081. schriftSize + zeichenAbstand
  1082. + (int)(zeichenAbstand / 2.0 + 0.5),
  1083. 0xFF000000 | color);
  1084. x += schriftSize + zeichenAbstand;
  1085. }
  1086. }
  1087. // Determines how many pixels are needed to fully display a specific character
  1088. // c: The character whose width in pixels should be determined
  1089. int KursivTextRenderer::getCharWidth(const char c) const
  1090. {
  1091. if (c == '\t')
  1092. return schriftSize;
  1093. else if (c == ' ')
  1094. return schriftSize / 2;
  1095. else
  1096. return (
  1097. int)(TextRenderer::getCharWidth(c) + getCharHeight(c) / 4.0 + 0.5);
  1098. }