font.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Fonts
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. class FontImpl : public IEngineFont {
  8. private:
  9. //////////////////////////////////////////////////////////////////////////////
  10. //
  11. // Types
  12. //
  13. //////////////////////////////////////////////////////////////////////////////
  14. class CharData {
  15. public:
  16. WinPoint m_size;
  17. int m_offset;
  18. };
  19. //////////////////////////////////////////////////////////////////////////////
  20. //
  21. // Data members
  22. //
  23. //////////////////////////////////////////////////////////////////////////////
  24. int m_height;
  25. int m_width;
  26. CharData m_data[256];
  27. BYTE* m_pdata;
  28. int m_dataSize;
  29. //////////////////////////////////////////////////////////////////////////////
  30. //
  31. // Private members
  32. //
  33. //////////////////////////////////////////////////////////////////////////////
  34. void FillFontData(HFONT hfont)
  35. {
  36. int length = 0;
  37. int index;
  38. //
  39. // figure out the total data size
  40. //
  41. for (index = 0; index < 256; index++) {
  42. int xsize = m_data[index].m_size.X();
  43. int ysize = m_data[index].m_size.Y();
  44. m_data[index].m_offset = length;
  45. length += ((xsize + 7) / 8) * ysize;
  46. }
  47. //
  48. // Allocate the data
  49. //
  50. m_dataSize = (length + 3) & (~3);
  51. m_pdata = new BYTE[m_dataSize];
  52. //
  53. // Create a dib section to get the characters with
  54. //
  55. class MyHeader {
  56. public:
  57. BITMAPINFOHEADER bmih;
  58. RGBQUAD colors[256];
  59. } bmih;
  60. bmih.bmih.biSize = sizeof(BITMAPINFOHEADER);
  61. bmih.bmih.biWidth = m_width;
  62. bmih.bmih.biHeight = -m_height;
  63. bmih.bmih.biPlanes = 1;
  64. bmih.bmih.biBitCount = 8;
  65. bmih.bmih.biCompression = BI_RGB;
  66. bmih.bmih.biSizeImage = 0;
  67. bmih.bmih.biXPelsPerMeter = 0;
  68. bmih.bmih.biYPelsPerMeter = 0;
  69. bmih.bmih.biClrUsed = 0;
  70. bmih.bmih.biClrImportant = 0;
  71. for (index = 0; index < 256; index++) {
  72. bmih.colors[index].rgbBlue = index;
  73. bmih.colors[index].rgbGreen = index;
  74. bmih.colors[index].rgbRed = index;
  75. bmih.colors[index].rgbReserved = 0;
  76. }
  77. BYTE* pbits;
  78. HBITMAP hbitmap =
  79. ::CreateDIBSection(
  80. NULL,
  81. (BITMAPINFO*)&bmih,
  82. DIB_RGB_COLORS,
  83. (void**)&pbits,
  84. NULL,
  85. 0
  86. );
  87. ZAssert(hbitmap != NULL);
  88. HDC hdcBitmap = ::CreateCompatibleDC(NULL);
  89. ZAssert(hdcBitmap != NULL);
  90. HBITMAP hbitmapOld = (HBITMAP)::SelectObject(hdcBitmap, hbitmap);
  91. ZAssert(hbitmapOld != NULL);
  92. HFONT hfontOld = (HFONT)::SelectObject(hdcBitmap, hfont);
  93. ZVerify(hfontOld != NULL);
  94. ZVerify(::SetBkMode(hdcBitmap, TRANSPARENT));
  95. ZVerify(::SetTextColor(hdcBitmap, Color::White().MakeCOLORREF()) != CLR_INVALID);
  96. ZVerify(::SetBkColor (hdcBitmap, Color::Black().MakeCOLORREF()) != CLR_INVALID);
  97. //
  98. // Get the character bitmaps
  99. //
  100. BYTE* pdata = m_pdata;
  101. int scanBytes = ((m_width + 3) / 4) * 4;
  102. for (index = 0; index < 256; index++) {
  103. int xsize = m_data[index].m_size.X();
  104. int ysize = m_data[index].m_size.Y();
  105. unsigned char ch = index;
  106. ZVerify(::FillRect(
  107. hdcBitmap,
  108. &(RECT)WinRect(0, 0, m_width, m_height),
  109. (HBRUSH)::GetStockObject(BLACK_BRUSH)
  110. ));
  111. ZVerify(::TextOut(hdcBitmap, 0, 0, (PCC)&ch, 1));
  112. //
  113. // pull out the data
  114. //
  115. int xbytes = (xsize + 7) / 8;
  116. for (int yindex = 0; yindex < ysize; yindex++) {
  117. for (int xbyte = 0; xbyte < xbytes; xbyte++) {
  118. WORD word = 0;
  119. for (int xbit = 0; xbit < 8; xbit++) {
  120. if (pbits[yindex * scanBytes + xbyte * 8 + xbit] == 0xff) {
  121. word |= 0x100;
  122. }
  123. word >>= 1;
  124. }
  125. *pdata = (BYTE)word;
  126. pdata++;
  127. }
  128. }
  129. }
  130. ZAssert(pdata == m_pdata + length);
  131. //
  132. // Release the DC we created
  133. //
  134. ZVerify(::SelectObject(hdcBitmap, hfontOld));
  135. ZVerify(::SelectObject(hdcBitmap, hbitmapOld));
  136. ZVerify(::DeleteDC(hdcBitmap));
  137. ZVerify(::DeleteObject(hbitmap));
  138. }
  139. //////////////////////////////////////////////////////////////////////////////
  140. //
  141. //
  142. //
  143. //////////////////////////////////////////////////////////////////////////////
  144. void GetSizes(HFONT hfont)
  145. {
  146. HDC hdc = ::GetDC(NULL);
  147. ZVerify(hdc != NULL);
  148. HFONT hfontOld = (HFONT)::SelectObject(hdc, hfont);
  149. ZVerify(hfontOld != NULL);
  150. //
  151. // Get the character widths, offsets
  152. //
  153. m_height = 0;
  154. m_width = 0;
  155. int index;
  156. for (index = 0; index < 256; index++) {
  157. SIZE size;
  158. unsigned char ch = index;
  159. ZVerify(::GetTextExtentPoint(
  160. hdc,
  161. (PCC)&ch,
  162. 1,
  163. &size
  164. ));
  165. m_data[index].m_size = WinPoint(size.cx, size.cy);
  166. m_height = max(m_height, size.cy);
  167. m_width = max(m_width, size.cx);
  168. }
  169. //
  170. // release the hdc
  171. //
  172. ZVerify(::SelectObject(hdc, hfontOld));
  173. ZVerify(::ReleaseDC(NULL, hdc));
  174. //
  175. // Make that all of the value GDI returned to us are good
  176. //
  177. for (index = 0; index < 256; index++) {
  178. ZAssert(m_data[index].m_size.X() > 0 );
  179. ZAssert(m_data[index].m_size.X() < m_height * 4);
  180. ZAssert(m_data[index].m_size.Y() == m_height );
  181. }
  182. }
  183. //////////////////////////////////////////////////////////////////////////////
  184. //
  185. //
  186. //
  187. //////////////////////////////////////////////////////////////////////////////
  188. public:
  189. FontImpl(HFONT hfont) :
  190. m_pdata(NULL)
  191. {
  192. GetSizes(hfont);
  193. FillFontData(hfont);
  194. ZVerify(::DeleteObject(hfont));
  195. }
  196. FontImpl(IBinaryReaderSite* psite)
  197. {
  198. m_height = psite->GetDWORD();
  199. m_width = psite->GetDWORD();
  200. m_dataSize = psite->GetDWORD();
  201. memcpy(m_data, psite->GetPointer(), sizeof(m_data));
  202. psite->MovePointer(sizeof(m_data));
  203. m_pdata = new BYTE[m_dataSize];
  204. memcpy(m_pdata, psite->GetPointer(), m_dataSize);
  205. psite->MovePointer(m_dataSize);
  206. }
  207. ~FontImpl()
  208. {
  209. if (m_pdata) {
  210. delete m_pdata;
  211. }
  212. }
  213. //////////////////////////////////////////////////////////////////////////////
  214. //
  215. // members
  216. //
  217. //////////////////////////////////////////////////////////////////////////////
  218. void Write(IMDLBinaryFile* pmdlFile)
  219. {
  220. pmdlFile->WriteReference("ImportFont");
  221. TRef<ZFile> pfile = pmdlFile->WriteBinary();
  222. pfile->Write(m_height);
  223. pfile->Write(m_width);
  224. pfile->Write(m_dataSize);
  225. pfile->Write(m_data, sizeof(m_data));
  226. pfile->Write(m_pdata, m_dataSize);
  227. }
  228. //////////////////////////////////////////////////////////////////////////////
  229. //
  230. // IEngineFont members
  231. //
  232. //////////////////////////////////////////////////////////////////////////////
  233. int GetHeight()
  234. {
  235. return m_height;
  236. }
  237. WinPoint GetTextExtent(const ZString& str)
  238. {
  239. int count = str.GetLength();
  240. int width = 0;
  241. for (int index = 0; index < count; index++) {
  242. if (str[index] == START_COLOR_CODE)
  243. index += 10 - 1;
  244. else if (str[index] == END_COLOR_CODE)
  245. index += 2 - 1;
  246. else
  247. width += m_data[(BYTE)str[index]].m_size.X();
  248. }
  249. return WinPoint(width, m_height);
  250. }
  251. WinPoint GetTextExtent(const char* sz)
  252. {
  253. int count = strlen(sz);
  254. int width = 0;
  255. for (int index = 0; index < count; index++) {
  256. if (sz[index] == START_COLOR_CODE)
  257. index += 10 - 1;
  258. else if (sz[index] == END_COLOR_CODE)
  259. index += 2 - 1;
  260. else
  261. width += m_data[(BYTE)sz[index]].m_size.X();
  262. }
  263. return WinPoint(width, m_height);
  264. }
  265. int GetMaxTextLength(const ZString& str, int maxWidth, bool bLeft)
  266. {
  267. int count = str.GetLength();
  268. int width = 0;
  269. for (int index = 0; index < count; index++) {
  270. int ichar = bLeft ? index : count - (index + 1);
  271. // note that this method is not adjusted to account for colored text, since it
  272. // may work backwards across the string, resulting in a difficult case that I
  273. // don't think is causing problems right now, ergo no need to fix it.
  274. width += m_data[(BYTE)str[ichar]].m_size.X();
  275. if (width > maxWidth)
  276. return index;
  277. }
  278. return count;
  279. }
  280. void DrawClippedChar(
  281. const WinRect& rectClip,
  282. byte ch,
  283. int ytop,
  284. int ysize,
  285. int x, BYTE*
  286. pdestTop,
  287. WORD pixel,
  288. int pitchDest
  289. ) {
  290. const CharData& charData = m_data[ch];
  291. int xsizeChar = charData.m_size.X();
  292. //
  293. // figure out the left and right clipping
  294. //
  295. int xleft;
  296. if (x < rectClip.XMin()) {
  297. xleft = rectClip.XMin() - x;
  298. } else {
  299. xleft = 0;
  300. }
  301. int xright;
  302. if (x + xsizeChar > rectClip.XMax()) {
  303. xright = rectClip.XMax() - x;
  304. } else {
  305. xright = xsizeChar;
  306. }
  307. //
  308. // pointers
  309. //
  310. int bytesSource = (xsizeChar + 7) / 8;
  311. BYTE* psourceStart =
  312. m_pdata
  313. + charData.m_offset
  314. + bytesSource * ytop;
  315. BYTE* pdestStart = pdestTop + (x + xleft) * 2;
  316. //
  317. // copy bits between xleft and xright
  318. //
  319. for (int scans = ysize; scans > 0; scans--) {
  320. BYTE* psource = psourceStart;
  321. BYTE* pdest = pdestStart;
  322. int ibit = 0;
  323. BYTE byte = *psource;
  324. psource++;
  325. //
  326. // skip clipped left bits
  327. //
  328. while (ibit < xleft) {
  329. byte = byte >> 1;
  330. ibit++;
  331. if (ibit & 0x7 == 0) {
  332. byte = *psource;
  333. psource++;
  334. }
  335. }
  336. //
  337. // render bits between xleft and xright
  338. //
  339. while (ibit < xright) {
  340. if (byte & 1) {
  341. *(WORD*)pdest = pixel;
  342. }
  343. pdest += 2;
  344. byte = byte >> 1;
  345. ibit += 1;
  346. if (ibit & 0x7 == 0) {
  347. byte = *psource;
  348. psource++;
  349. }
  350. }
  351. psourceStart += bytesSource;
  352. pdestStart += pitchDest;
  353. }
  354. }
  355. void DrawString(
  356. Surface* psurface,
  357. const WinPoint& point,
  358. const WinRect& rectClip,
  359. const ZString& str,
  360. const Color& color
  361. ) {
  362. if (str.GetLength() == 0) {
  363. return;
  364. }
  365. //
  366. // are we clipped in the y direction?
  367. //
  368. int ytop = 0;
  369. int ybottom = m_height;
  370. //
  371. // is the top clipped?
  372. //
  373. if (point.Y() < rectClip.YMin()) {
  374. ytop = rectClip.YMin() - point.Y();
  375. }
  376. //
  377. // is the bottom clipped?
  378. //
  379. if (point.Y() + m_height > rectClip.YMax()) {
  380. ybottom = rectClip.YMax() - point.Y();
  381. }
  382. //
  383. // figure out the total number of scan lines to draw
  384. //
  385. int ysize = ybottom - ytop;
  386. if (ysize <= 0) {
  387. //
  388. // clipped in y, nothing to draw
  389. //
  390. return;
  391. }
  392. //
  393. // Get a pointer to the destination memory
  394. //
  395. BYTE* pdestTop =
  396. psurface->GetWritablePointer()
  397. + (point.Y() + ytop) * psurface->GetPitch();
  398. //
  399. // All access to the surface needs to be inside an exception handler
  400. //
  401. __try {
  402. int ichar = 0;
  403. int x = point.X ();
  404. DrawStringHandled(
  405. psurface,
  406. x,
  407. rectClip,
  408. str,
  409. color,
  410. pdestTop,
  411. ytop,
  412. ybottom,
  413. ysize,
  414. ichar
  415. );
  416. } __except (true) {
  417. //
  418. // DDraw took away our access to some video memory. Ignore the exception
  419. // and continue.
  420. //
  421. }
  422. psurface->ReleasePointer();
  423. }
  424. int HexDigitToInt (int hexDigit)
  425. {
  426. if (isdigit (hexDigit))
  427. return hexDigit - '0';
  428. else if (isxdigit (hexDigit))
  429. return (tolower (hexDigit) - 'a') + 10;
  430. else
  431. return -1;
  432. }
  433. int ReadHexPair (const ZString& str, int& ichar)
  434. {
  435. int highNibble = HexDigitToInt (str[ichar++]);
  436. int lowNibble = HexDigitToInt (str[ichar++]);
  437. assert ((highNibble >= 0) && (lowNibble >= 0));
  438. return ((highNibble << 4) | lowNibble);
  439. }
  440. Color ReadColor (const ZString& str, int& ichar)
  441. {
  442. float red = ReadHexPair (str, ichar) / 255.0f;
  443. float green = ReadHexPair (str, ichar) / 255.0f;
  444. float blue = ReadHexPair (str, ichar) / 255.0f;
  445. float alpha = ReadHexPair (str, ichar) / 255.0f;
  446. return Color (red, green, blue, alpha);
  447. }
  448. void DrawColorCodedString(
  449. Surface* psurface,
  450. int& x,
  451. const WinRect& rectClip,
  452. const ZString& str,
  453. BYTE* pdestTop,
  454. int ytop,
  455. int ybottom,
  456. int ysize,
  457. int& ichar
  458. )
  459. {
  460. // we started here because we encountered a color code,
  461. // so the first thing is to skip over the color code and
  462. // the required following character
  463. ichar += 2;
  464. // next we need to read the color, in the form rrggbbaa,
  465. // where each pair of digits is
  466. Color nextColor = ReadColor (str, ichar);
  467. DrawStringHandled (psurface, x, rectClip, str, nextColor, pdestTop, ytop, ybottom, ysize, ichar);
  468. }
  469. void DrawStringHandled(
  470. Surface* psurface,
  471. int& x,
  472. const WinRect& rectClip,
  473. const ZString& str,
  474. const Color& color,
  475. BYTE* pdestTop,
  476. int ytop,
  477. int ybottom,
  478. int ysize,
  479. int& ichar
  480. ) {
  481. int length = str.GetLength();
  482. //
  483. // get all the surface info
  484. //
  485. PixelFormat* ppf = psurface->GetPixelFormat();
  486. int pixelBytes = ppf->PixelBytes();
  487. WinPoint sizeDest = psurface->GetSize();
  488. int pitchDest = psurface->GetPitch();
  489. WORD pixel = (WORD)(ppf->MakePixel(color).Value());
  490. ZAssert(pixelBytes == 2);
  491. //
  492. // loop through characters that are clipped on the left
  493. //
  494. bool loop = true;
  495. while (loop)
  496. {
  497. BYTE ch = str[ichar];
  498. switch (ch)
  499. {
  500. case START_COLOR_CODE:
  501. DrawColorCodedString (psurface, x, rectClip, str, pdestTop, ytop, ybottom, ysize, ichar);
  502. if (ichar >= length)
  503. return;
  504. break;
  505. case END_COLOR_CODE:
  506. ichar += 2;
  507. return;
  508. default:
  509. {
  510. const CharData& charData = m_data[ch];
  511. int xsizeChar = charData.m_size.X();
  512. if ((x + xsizeChar) > rectClip.XMin())
  513. {
  514. loop = false;
  515. break;
  516. }
  517. if (++ichar >= length)
  518. return;
  519. x += xsizeChar;
  520. }
  521. break;
  522. }
  523. }
  524. //
  525. // there can be one character clipped on the left
  526. //
  527. if (x < rectClip.XMin())
  528. {
  529. DrawClippedChar(rectClip, str[ichar], ytop, ysize, x, pdestTop, pixel, pitchDest);
  530. if (++ichar >= length)
  531. return;
  532. x += m_data[(BYTE)str[ichar]].m_size.X();
  533. }
  534. //
  535. // loop through unclipped characters
  536. //
  537. loop = true;
  538. while (loop)
  539. {
  540. BYTE ch = str[ichar];
  541. switch (ch)
  542. {
  543. case START_COLOR_CODE:
  544. DrawColorCodedString (psurface, x, rectClip, str, pdestTop, ytop, ybottom, ysize, ichar);
  545. if (ichar >= length)
  546. return;
  547. break;
  548. case END_COLOR_CODE:
  549. ichar += 2;
  550. return;
  551. default:
  552. {
  553. const CharData& charData = m_data[ch];
  554. int xsizeChar = charData.m_size.X();
  555. if ((x + xsizeChar) > rectClip.XMax())
  556. {
  557. loop = false;
  558. break;
  559. }
  560. int scans = ysize;
  561. int bytesSource = (xsizeChar + 7) / 8;
  562. BYTE* psource = m_pdata + charData.m_offset + (bytesSource * ytop);
  563. BYTE* pdest = pdestTop + x * 2;
  564. //
  565. // transparent blt 1bpp -> 16bpp
  566. //
  567. _asm {
  568. mov esi, psource
  569. mov ax, pixel
  570. mov ecx, pdest
  571. yloop:
  572. mov edi, ecx
  573. mov ebx, [bytesSource]
  574. byteLoop:
  575. mov dl, [esi]
  576. inc esi
  577. shr dl, 1
  578. jnc skipbit1
  579. mov [edi + 0], ax
  580. skipbit1:
  581. shr dl, 1
  582. jnc skipbit2
  583. mov [edi + 2], ax
  584. skipbit2:
  585. shr dl, 1
  586. jnc skipbit3
  587. mov [edi + 4], ax
  588. skipbit3:
  589. shr dl, 1
  590. jnc skipbit4
  591. mov [edi + 6], ax
  592. skipbit4:
  593. shr dl, 1
  594. jnc skipbit5
  595. mov [edi + 8], ax
  596. skipbit5:
  597. shr dl, 1
  598. jnc skipbit6
  599. mov [edi + 10], ax
  600. skipbit6:
  601. shr dl, 1
  602. jnc skipbit7
  603. mov [edi + 12], ax
  604. skipbit7:
  605. shr dl, 1
  606. jnc skipbit8
  607. mov [edi + 14], ax
  608. skipbit8:
  609. add edi, 16
  610. dec ebx
  611. jne byteLoop
  612. add ecx, [pitchDest]
  613. dec [scans]
  614. jne yloop
  615. }
  616. if (++ichar >= length)
  617. return;
  618. x += xsizeChar;
  619. }
  620. break;
  621. }
  622. }
  623. //
  624. // one character can be clipped on the right
  625. //
  626. if (x < rectClip.XMax())
  627. DrawClippedChar(rectClip, str[ichar], ytop, ysize, x, pdestTop, pixel, pitchDest);
  628. }
  629. };
  630. TRef<IEngineFont> CreateEngineFont(HFONT hfont)
  631. {
  632. return new FontImpl(hfont);
  633. }
  634. TRef<IEngineFont> CreateEngineFont(IBinaryReaderSite* psite)
  635. {
  636. return new FontImpl(psite);
  637. }
  638. //////////////////////////////////////////////////////////////////////////////
  639. //
  640. // Color code utility function
  641. //
  642. //////////////////////////////////////////////////////////////////////////////
  643. ZString ConvertColorToString (const Color& color)
  644. {
  645. char buffer[9] = {0};
  646. sprintf (buffer, "%02x%02x%02x%02x",
  647. int (color.R () * 255.0f),
  648. int (color.G () * 255.0f),
  649. int (color.B () * 255.0f),
  650. int (color.A () * 255.0f)
  651. );
  652. return ZString (buffer);
  653. }
  654. //////////////////////////////////////////////////////////////////////////////
  655. //
  656. // Fonts
  657. //
  658. //////////////////////////////////////////////////////////////////////////////
  659. ZString GetString(int indent, TRef<IEngineFont> pfont)
  660. {
  661. ZUnimplemented();
  662. return "font";
  663. }
  664. void Write(IMDLBinaryFile* pmdlFile, TRef<IEngineFont> pfont)
  665. {
  666. FontImpl* pimpl; CastTo(pimpl, pfont);
  667. pimpl->Write(pmdlFile);
  668. }
  669. ZString GetFunctionName(const TRef<IEngineFont>& value)
  670. {
  671. return "ImportFont";
  672. }
  673. //////////////////////////////////////////////////////////////////////////////
  674. //
  675. // Alternate blting implementations
  676. //
  677. //////////////////////////////////////////////////////////////////////////////
  678. /* version 1
  679. _asm {
  680. mov edi, pdest
  681. mov esi, psource
  682. mov ax, pixel
  683. yloop:
  684. mov ebx, bytesSource
  685. and ebx, ebx
  686. je extraLoop
  687. byteLoop:
  688. mov dl, [esi]
  689. inc esi
  690. mov ecx, 8
  691. bitloop1:
  692. shr dl, 1
  693. jnc bitloop1Skip
  694. mov [edi], ax
  695. bitloop1Skip:
  696. add edi, 2
  697. dec ecx
  698. jne bitloop1
  699. dec ebx
  700. jne byteLoop
  701. extraLoop:
  702. mov ecx, extraSource
  703. and ecx, ecx
  704. je end
  705. mov dl, [esi]
  706. inc esi
  707. bitloop2:
  708. shr dl, 1
  709. jnc bitloop2Skip
  710. mov [edi], ax
  711. bitloop2Skip:
  712. add edi, 2
  713. dec ecx
  714. jne bitloop2
  715. end:
  716. add edi, [scanDeltaDest]
  717. dec [ysizeSource]
  718. jne yloop
  719. }
  720. */
  721. /* this doesn't work yet. Try to use a jump table dependant on the number of bits
  722. static void* bitJumps[8] = {
  723. bits8,
  724. bits1,
  725. bits2,
  726. bits3,
  727. bits4,
  728. bits5,
  729. bits6,
  730. bits7
  731. };
  732. _asm {
  733. mov esi, psource
  734. mov ax, pixel
  735. mov ecx, pdest
  736. ayloop:
  737. mov edi, ecx
  738. //
  739. // eax pixel
  740. // ebx temporary
  741. // ecx pdestScanLine
  742. // dl bits
  743. // edi destination
  744. // esi source
  745. // ebp
  746. //
  747. byteLoop:
  748. mov dl, [esi]
  749. inc esi
  750. mov ebx, [xsize]
  751. cmp ebx, 8
  752. jg bits8
  753. and ebx, 0x7
  754. jmp [bitJumps + ecx]
  755. bits8:
  756. shl dl, 1
  757. jnc bits7
  758. mov [edi + 14], ax
  759. bits7:
  760. shl dl, 1
  761. jnc bits6
  762. mov [edi + 12], ax
  763. bits6:
  764. shl dl, 1
  765. jnc bits5
  766. mov [edi + 10], ax
  767. bits5:
  768. shl dl, 1
  769. jnc bits4
  770. mov [edi + 8], ax
  771. bits4:
  772. shl dl, 1
  773. jnc bits3
  774. mov [edi + 6], ax
  775. bits3:
  776. shl dl, 1
  777. jnc bits2
  778. mov [edi + 4], ax
  779. bits2:
  780. shl dl, 1
  781. jnc bits1
  782. mov [edi + 2], ax
  783. bits1:
  784. shl dl, 1
  785. jnc bits1
  786. mov [edi + 0], ax
  787. add edi, 16
  788. dec [xsize]
  789. jne byteLoop
  790. add ecx, [pitchDest]
  791. dec [ysizeSource]
  792. jne ayloop
  793. }
  794. */
  795. /*
  796. do {
  797. //
  798. // Copy the byte sized chunks
  799. //
  800. {
  801. for (int iBytes = bytesSource; iBytes > 0; iBytes--) {
  802. BYTE byte = *psource;
  803. psource++;
  804. for (int index = 8; index > 0; index--) {
  805. if (byte & 1) {
  806. *(WORD*)pdest = pixel;
  807. }
  808. byte >>= 1;
  809. pdest += 2;
  810. }
  811. }
  812. }
  813. //
  814. // Copy the last few bits
  815. //
  816. if (extraSource != 0) {
  817. BYTE byte = *psource;
  818. psource++;
  819. for (int index = extraSource; index > 0; index--) {
  820. if (byte & 1) {
  821. *(WORD*)pdest = pixel;
  822. }
  823. byte >>= 1;
  824. pdest += 2;
  825. }
  826. }
  827. //
  828. // Next scan line
  829. //
  830. pdest += scanDeltaDest;
  831. psource += scanDeltaSource;
  832. ysizeSource -= 1;
  833. } while (ysizeSource > 0);
  834. */