Fspr1.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. #include "System.h"
  19. //********************************************
  20. //*** This file should be called "ToBMP1"
  21. //*** Currently, You can BLiT FSPR1 scaled and
  22. //*** unscaled into a BMP1.
  23. // ( support for FSRP8 NYI )
  24. //********************************************
  25. #ifdef PATHS_IN_INCLUDES
  26. #include "GREEN/BLiT/BLIT.H"
  27. #include "GREEN/BLiT/_BlitInt.H"
  28. #include "ORANGE/QuickMath/Fractions.h"
  29. #include "GREEN/Image/SpecialTyp.h"
  30. #else
  31. #include "BLIT.H"
  32. #include "_BlitInt.H"
  33. #include "Fractions.h"
  34. #include "specialtyp.h"
  35. #endif
  36. #include <string.h>
  37. //***************************************************************************
  38. // Mimicking the success of FSPR8, the newest FSPR1 is GREATLY simplified.
  39. // The result is that large images with runs above 254 will have worse
  40. // compression, and decode slower, but images with runs less than 255
  41. // will decode faster. Also, simplified encoding/decoding will enhance
  42. // portability. To monitor this inefficiency, it will return the number
  43. // of overruns.
  44. //***************************************************************************
  45. // THIS CHANGE REPRESENTS FSPR1 as of 9/23/96
  46. //***************************************************************************
  47. // FILE note... Mac compatibility seems to work using ASCII (printf/scanf)
  48. // provided the PC opens the file using "wb" and adds its own newlines.
  49. //***************************************************************************
  50. // FONT note: Font specific information will NOT be stored in the FSPR1
  51. // itself, but in the CFNT Letter description associated with the FSPR1.
  52. // UPDATE **** Some font info will be in there ...
  53. // The new conversion does NOT assume the method of lasso, so that you
  54. // can "capture" regions of a larger BMP (useful for fonts.) The default is
  55. // to convert the BMP REGION AS IS, including padding around the edges.
  56. //***************************************************************************
  57. // NOTE: Unlike FSPR8, the palette will NOT be copied or preserved.
  58. // This is based on the idea that since all the color information is
  59. // lost from the image, it isn't worth taking up space with the palette,
  60. // since the old image can't be restored.
  61. //---------------- Predeclare linklate functions ---------------------------
  62. short DeleteFSPR1(RImage* pImage);
  63. short ConvertToFSPR1(RImage* pImage);
  64. short ConvertFromFSPR1(RImage* pImage);
  65. short LoadFSPR1(RImage* pImage, RFile* pcf);
  66. short SaveFSPR1(RImage* pImage, RFile* pcf);
  67. //---------------- EXTRA Conversion Information ----------------------------
  68. typedef struct
  69. {
  70. U32 u32TransparentColor; // ConvertTo
  71. S16 sX,sY,sW,sH; // ConvertTo (-1 == don't use)
  72. RImage** ppimNew; // Create a separate CImage if not NULL!
  73. U32 u32ForeColor; // ConvertFrom
  74. U32 u32BackColor; // ConvertFrom (if s16Transparent==FALSE)
  75. S16 s16Transparent; // ConvertFrom (flag)
  76. S16 sOverRun; // Statistical info!
  77. } ConversionInfoFSPR1;
  78. ConversionInfoFSPR1 gFSPR1 =
  79. {
  80. (U32) 0,
  81. (S16) -1,
  82. (S16) -1,
  83. (S16) -1,
  84. (S16) -1,
  85. (RImage**) NULL,
  86. (U32) 0xffffff01, // And the color to the correct depth
  87. (U32) 0,
  88. (S16) TRUE
  89. }; // Defaults...
  90. void ResetFSPR1();
  91. void ResetFSPR1() // only traits DESIRABLE to reset between Converts
  92. {
  93. gFSPR1.sX=-1;
  94. gFSPR1.sY=-1;
  95. gFSPR1.sW=-1;
  96. gFSPR1.sH=-1;
  97. gFSPR1.ppimNew=NULL;
  98. }
  99. short GetOverRuns();
  100. short GetOverRuns() { return gFSPR1.sOverRun; }
  101. //---------------- Set Conversion Information ----------------
  102. void SetConvertToFSPR1
  103. (
  104. U32 u32TransparentColor,
  105. S16 sX, // Use (-1) to use default value
  106. S16 sY, // Use (-1) to use default value
  107. S16 sW, // Use (-1) to use default value
  108. S16 sH, // Use (-1) to use default value
  109. RImage** ppimCopy
  110. )
  111. {
  112. gFSPR1.u32TransparentColor = u32TransparentColor;
  113. gFSPR1.sX = sX;
  114. gFSPR1.sY = sY;
  115. gFSPR1.sW = sW;
  116. gFSPR1.sH = sH;
  117. gFSPR1.ppimNew = ppimCopy;
  118. }
  119. void SetConvertFromFSPR1
  120. (
  121. U32 u32ForeColor,
  122. S16 sTransparent,
  123. U32 u32BackColor // matters only if sTransparent = FALSE
  124. )
  125. {
  126. gFSPR1.u32ForeColor = u32ForeColor;
  127. gFSPR1.s16Transparent = sTransparent;
  128. gFSPR1.u32BackColor = u32BackColor;
  129. }
  130. //------------------- HOOK into the CImage world ------------------------
  131. IMAGELINKLATE(FSPR1,ConvertToFSPR1,ConvertFromFSPR1,
  132. LoadFSPR1,SaveFSPR1,NULL,DeleteFSPR1);
  133. short DeleteFSPR1(RImage* pImage) // from CImage ONLY
  134. {
  135. delete (RSpecialFSPR1*) pImage->m_pSpecialMem;
  136. return SUCCESS;
  137. }
  138. //------------------------------------------------------------------------
  139. // Assume that pImage is valid...
  140. //
  141. short ConvertToFSPR1(RImage* pImage)
  142. {
  143. #ifdef _DEBUG
  144. if (!ImageIsUncompressed(pImage->m_type))
  145. {
  146. TRACE("ConvertToFSPR1: Source must be uncompressed.\n");
  147. return RImage::NOT_SUPPORTED;
  148. }
  149. #endif
  150. //========================== Let's Rock! ========================
  151. // What should we snag here?
  152. short sX = 0, sY = 0, sW = pImage->m_sWidth,sH = pImage->m_sHeight;
  153. if (gFSPR1.sX != -1) sX = gFSPR1.sX;
  154. if (gFSPR1.sY != -1) sY = gFSPR1.sY;
  155. if (gFSPR1.sW != -1) sW = gFSPR1.sW;
  156. if (gFSPR1.sH != -1) sH = gFSPR1.sH;
  157. //----------------------------------- Autoclip:
  158. short sTemp;
  159. if (sX < 0) sX = 0;
  160. if (sY < 0) sY = 0;
  161. if ( (sTemp = sX + sW - pImage->m_sWidth) > 0) sW -= sTemp;
  162. if ( (sTemp = sY + sH - pImage->m_sHeight) > 0) sH -= sTemp;
  163. if ( (sW < 1) || (sH < 1) )
  164. {
  165. TRACE("ConvertToFSPR1: Bad region passed.\n");
  166. return RImage::NOT_SUPPORTED;
  167. }
  168. //----------------------------------- Begin Compressing:
  169. short sBlankLineCount = 0;
  170. short sCount = 0;
  171. // The fastest way is still to create a buffer of fixed size, then to
  172. // shrink it. This is risky, since there is no true max size for this
  173. // compression techique. If there are no over-runs, a checkerboard
  174. // pattern would need h * (w+1) + 2. This seems like a reasonable Max,
  175. // Since every run of 3 counteracts an overrun.
  176. long lMaxSize = (long)sW * (sH + 2) * 2 + sH;
  177. lMaxSize = (lMaxSize + 15) & ~15; // 128 bit alignment
  178. UCHAR* pCodeBuf = (UCHAR*) calloc(1,lMaxSize);
  179. if (pCodeBuf == NULL)
  180. {
  181. TRACE("ConvertToFSPR1: Out of memory ERROR!");
  182. ResetFSPR1();
  183. return RImage::NOT_SUPPORTED;
  184. }
  185. UCHAR* pCode = pCodeBuf;
  186. long lP = pImage->m_lPitch;
  187. UCHAR *pBuf,*pBufLine = pImage->m_pData + sX + lP*sY; // 8-bit for now!
  188. UCHAR ucTranCol = (UCHAR) (gFSPR1.u32TransparentColor & 0xff); // 8-bit for now!
  189. short sLineLen,sLineW = sW;
  190. short y;
  191. sBlankLineCount = 0;
  192. short sBlank;
  193. short sOverRun = 0; // For diagnostics!
  194. //-------------------- COMPRESS IT! --------------------
  195. for (y=0;y<sH;y++)
  196. {
  197. //********************* Do a line: *********************
  198. pBuf = pBufLine;
  199. sBlank = TRUE;
  200. sLineLen = sLineW;
  201. while (TRUE) // ENTER RUNS:
  202. {
  203. //---------- Skip Run:
  204. sCount = 0;
  205. while ((*pBuf == ucTranCol) && sLineLen)
  206. {
  207. pBuf++; sCount++; sLineLen--;
  208. }
  209. //************ CHECK for EOL in a skip run:
  210. if (!sLineLen) // EOL:
  211. {
  212. if (sBlank == TRUE) // nothing on this line, write nothing!
  213. sBlankLineCount++;// until we count them all!
  214. else
  215. *pCode++ = 255; // Cancel the skip, insert EOL!
  216. goto NEXT_Y; // begin the next line!
  217. }
  218. // ELSE... Not a blank line... enter skip line count and
  219. // then the clear run count!
  220. //************ FILL IN POSSIBLE SKIPPED BLANK LINES
  221. if (sBlankLineCount > 0) // Now add in the blank line skip code:
  222. {
  223. while (sBlankLineCount > 254)
  224. {
  225. *pCode++ = 255;
  226. *pCode++ = 254;
  227. sBlankLineCount -= 254;
  228. }
  229. *pCode++ = 255;
  230. *pCode++ = (UCHAR)sBlankLineCount;
  231. sBlankLineCount = 0;
  232. }
  233. //=========== Insert the skip run...
  234. while (sCount > 254) // overflow
  235. {
  236. sOverRun++; // for diagnostics!
  237. *pCode++ = 254; // Cycle through runs...
  238. *pCode++ = 0; // No skip
  239. sCount -= 254;
  240. }
  241. *pCode++ = (UCHAR)sCount; // Enter skip run..
  242. //---------- Opaque Run:
  243. sCount = 0;
  244. while ((*pBuf != ucTranCol) && sLineLen)
  245. {
  246. sBlank = FALSE; pBuf++; sCount++; sLineLen--;
  247. }
  248. //================= Insert the opaque run:
  249. while (sCount > 255) // overflow
  250. {
  251. sOverRun++; // for diagnostics!
  252. *pCode++ = 255; // Cycle through runs...
  253. *pCode++ = 0; // Next clear run
  254. sCount -= 255;
  255. }
  256. *pCode++ = (UCHAR)sCount; // Enter opaque run..
  257. }
  258. NEXT_Y:
  259. pBufLine += lP;
  260. }
  261. // ADD in final trailing line skipping:
  262. if (sBlankLineCount > 0) // Now add in the blank line skip code:
  263. {
  264. while (sBlankLineCount > 254)
  265. {
  266. *pCode++ = 255;
  267. *pCode++ = 254;
  268. sBlankLineCount -= 254;
  269. }
  270. *pCode++ = 255;
  271. *pCode++ = (UCHAR)sBlankLineCount;
  272. }
  273. // Final Code: (Safety cap)
  274. *pCode++ = 255;
  275. *pCode++ = 255;
  276. //****************** SHRINK THE BUFFER!
  277. long lCompressedSize = pCode - pCodeBuf + 1;
  278. long lAlignSize = (lCompressedSize + 15) & ~15;
  279. UCHAR* pNewCodeBuf = (UCHAR*) calloc(1,lAlignSize); //+ Free problem
  280. if (pNewCodeBuf == NULL)
  281. {
  282. TRACE("ConvertToFSPR1: Out of memory ERROR!");
  283. free(pCodeBuf);
  284. ResetFSPR1();
  285. return RImage::NOT_SUPPORTED;
  286. }
  287. memcpy(pNewCodeBuf,pCodeBuf,lCompressedSize);
  288. if (long(pCode - pCodeBuf + 1) > lMaxSize)
  289. {
  290. TRACE("ConvertToFSPR1: I overran my own buffer!\n");
  291. }
  292. free(pCodeBuf);
  293. gFSPR1.sOverRun = sOverRun; // for diagnostics
  294. //******************************************************************
  295. //------- Let's make a new Image!
  296. RImage* pimNew = new RImage;
  297. pimNew->m_type = RImage::FSPR1;
  298. RSpecialFSPR1* pSpecial = new RSpecialFSPR1; //+ Free problem
  299. pSpecial->m_OldType = pImage->m_type;
  300. pSpecial->m_pCode = pNewCodeBuf;
  301. pSpecial->m_lSize = lCompressedSize; // Set font specific stuff yourself!
  302. pSpecial->m_u16Width = USHORT(sW); // so the default kerning makes sense!
  303. pimNew->m_pSpecial = pimNew->m_pSpecialMem = (UCHAR*)pSpecial;
  304. pimNew->m_sWidth = sW;
  305. pimNew->m_sHeight = sH;
  306. pimNew->m_sWinWidth = sW;
  307. pimNew->m_sWinHeight = sH;
  308. pimNew->m_sWinX = 0;
  309. pimNew->m_sWinY = 0;
  310. pimNew->m_sDepth = (short)8;
  311. pimNew->m_lPitch = (long)pimNew->m_sWidth; // Pitch is meaningless here!
  312. //********************* should we transfer it over? **************
  313. if (gFSPR1.ppimNew != NULL) // make a copy:
  314. {
  315. *(gFSPR1.ppimNew) = pimNew;
  316. ResetFSPR1();
  317. return RImage::FSPR1;
  318. }
  319. //---------------- transfer to the original:
  320. pImage->m_pSpecial = pImage->m_pSpecialMem = pimNew->m_pSpecialMem;
  321. // WE MUST REMOVE THE OLD BUFFER:
  322. //pImage->DestroyData();
  323. void* pTempData = pImage->DetachData();
  324. RImage::DestroyDetachedData(&pTempData);
  325. pImage->DestroyPalette(); // Don't save the palette info!
  326. pImage->m_ulSize = 0; // BLiT needs to deal with copying, etc....
  327. pImage->m_type = RImage::FSPR1;
  328. // free the copy header:
  329. pimNew->m_pSpecialMem = NULL;
  330. delete pimNew; // it's gone!
  331. return RImage::FSPR1;
  332. }
  333. // Internal BLitting of FSPR1
  334. // Designed for use by rspBLiT, so assume all the input is validated, etc...
  335. //
  336. // DOES NOT CURRENTLY CLIP!!!!!
  337. // is currently 8-bit color!
  338. //
  339. void _rspBLiT(UCHAR ucColor,RImage* pimSrc,RImage* pimDst,
  340. short sDstX,short sDstY)
  341. {
  342. #ifdef _DEBUG
  343. if (pimSrc->m_pSpecialMem == NULL)
  344. {
  345. TRACE("_rspBLiT (FSPR1): corrupted source image!\n");
  346. return;
  347. }
  348. if ( (sDstX < 0) || (sDstY < 0) ||
  349. ( (sDstX + pimSrc->m_sWidth) > pimDst->m_sWidth) ||
  350. ( (sDstY + pimSrc->m_sHeight) > pimDst->m_sHeight) )
  351. {
  352. TRACE("_rspBLiT (FSPR1): Cannot yet clip the image!\n");
  353. return;
  354. }
  355. #endif
  356. long lP = pimDst->m_lPitch;
  357. UCHAR *pDst,*pDstLine = pimDst->m_pData + sDstX + lP*sDstY;
  358. UCHAR *pCode = ((RSpecialFSPR1*)pimSrc->m_pSpecialMem)->m_pCode;
  359. // Take advantage of the new FSPR1 EOS safety code:
  360. UCHAR ucCode,ucCount;
  361. while (TRUE) // loop through drawing lines:
  362. {
  363. // new line!
  364. pDst = pDstLine;
  365. if ((ucCode = *pCode++) == 255) // multiline skip:
  366. {
  367. if ((ucCount = *pCode++) == 255) break; // DONE DRAWING!!!!!!
  368. pDstLine += lP * ucCount; // Advance n lines
  369. continue; ///********** Start next scanline!
  370. }
  371. do { // Draw the scanline!
  372. pDst += ucCode;//HSKIP
  373. ucCount = *pCode++;
  374. while (ucCount--) *pDst++ = ucColor;//HRUN
  375. } while ((ucCode = *pCode++) != 255);
  376. pDstLine += lP;
  377. }
  378. }
  379. // Will convert back to the source 8-bit format.
  380. //
  381. short ConvertFromFSPR1(RImage* pImage)
  382. {
  383. // Here's the pattern: create the appropriate buffer, BLiT
  384. // pSpecial into it, then kill pSpecial!
  385. // MUST USE ConvertFrom Parameters...
  386. //
  387. RSpecialFSPR1* pHead = (RSpecialFSPR1*)pImage->m_pSpecialMem; // Got it!
  388. // Do it 8-bit for now...
  389. pImage->CreateImage(pImage->m_sWidth,pImage->m_sHeight,(RImage::Type)pHead->m_OldType);
  390. // color the background:
  391. if (gFSPR1.s16Transparent != TRUE)
  392. {
  393. rspRect(gFSPR1.u32BackColor,pImage,0,0,pImage->m_sWidth,
  394. pImage->m_sHeight);
  395. }
  396. // Blit it in:
  397. // Sadly, we must make a FAKE wrapper for the destination to use the same
  398. // rspBLiT... wait a sec...
  399. // This one should fool it! It only works in 8-bit color for now!
  400. //
  401. _rspBLiT((UCHAR)gFSPR1.u32ForeColor,pImage,pImage,(short)0,(short)0);
  402. // Now jettison the FSPR1 data:
  403. delete pHead;
  404. pImage->m_pSpecial = pImage->m_pSpecialMem = NULL;
  405. return (short)pImage->m_type;
  406. }
  407. // Assumes all of the FSPR1 has successfully been
  408. // loaded EXCEPT for pSpecial[Mem]
  409. //
  410. short LoadFSPR1(RImage* pImage, RFile* pcf)
  411. {
  412. long lBogus1 = pcf->Tell();
  413. //------------------
  414. // Initial Security:
  415. //------------------
  416. char szTemp[10];
  417. pcf->Read(&szTemp[0]);
  418. // Check type:
  419. if (strcmp(szTemp,"__FSPR1__")) // not equal
  420. {
  421. TRACE("Load FSPR1: Not correct file type!\n");
  422. return -1;
  423. }
  424. // Check Version:
  425. U16 u16Temp;
  426. pcf->Read(&u16Temp);
  427. if (u16Temp != ((3<<8) + 5) )
  428. {
  429. TRACE("Load FSPR1: This is an older FSPR1 format!\n");
  430. return -1;
  431. }
  432. //------------------
  433. // Info
  434. //------------------
  435. RSpecialFSPR1* pSpec = new RSpecialFSPR1;
  436. pImage->m_pSpecialMem = pImage->m_pSpecial = (UCHAR*)pSpec;
  437. pcf->Read((U32*)(&pSpec->m_OldType));
  438. pcf->Read(&pSpec->m_lSize);
  439. pcf->Read(&pSpec->m_u16ASCII);
  440. pcf->Read(&pSpec->m_s16KernL); // True type compatibilit
  441. pcf->Read(&pSpec->m_u16Width);
  442. pcf->Read(&pSpec->m_s16KernR);
  443. //------------------
  444. // Reserved Space
  445. //------------------
  446. // Reserved for future expansion:
  447. U32 u32Temp[4];
  448. pcf->Read(u32Temp,4); // 16 bytes reserved as of version 3.5
  449. //------------------
  450. // The Image Data
  451. //------------------
  452. // Now the actual data, which needs no alignment:
  453. pSpec->m_pCode = (U8*) malloc(pSpec->m_lSize); //+ Not freed!
  454. pcf->Read((U8*)(pSpec->m_pCode),pSpec->m_lSize);
  455. return SUCCESS;
  456. }
  457. // SAVES ONLY the pSpecial information!
  458. //
  459. short SaveFSPR1(RImage* pImage, RFile* pcf)
  460. {
  461. // Assume valid pImage and cnfile:
  462. RSpecialFSPR1* pSpec = (RSpecialFSPR1*) pImage->m_pSpecialMem;
  463. if (!pSpec)
  464. {
  465. TRACE("Save FSPR1: Bad FSPR1!\n");
  466. return -1;
  467. }
  468. //------------------
  469. // Initial Security:
  470. //------------------
  471. pcf->Write("__FSPR1__"); // image type
  472. U16 version = (U16)((3<<8) + 5); // Sprite incarnation 3, File Format 5
  473. pcf->Write(&version);
  474. //------------------
  475. // Info
  476. //------------------
  477. // NOTE: Some font info is stored here:
  478. pcf->Write((U32*)(&(pSpec->m_OldType)));
  479. pcf->Write(&(pSpec->m_lSize));
  480. pcf->Write(&(pSpec->m_u16ASCII));
  481. pcf->Write(&(pSpec->m_s16KernL)); // True type compatibilit
  482. pcf->Write(&(pSpec->m_u16Width));
  483. pcf->Write(&(pSpec->m_s16KernR));
  484. //------------------
  485. // Reserved Space
  486. //------------------
  487. // Reserved for future expansion
  488. U32 reserved[4] = {0,0,0,0};
  489. pcf->Write(reserved,4); // 16 bytes reserved as of version 3.5
  490. //------------------
  491. // The Image Data
  492. //------------------
  493. // Now the actual data, which needs no alignment:
  494. pcf->Write((U8*)pSpec->m_pCode,pSpec->m_lSize);
  495. return SUCCESS;
  496. }
  497. //************************************************************
  498. //***************** BLiTting onto BMP8's *******************
  499. //************************************************************
  500. //************************************************************
  501. //********************* NON-SCALING! ***********************
  502. //************************************************************
  503. // 8-bit color for now!
  504. // Doesn't clip...
  505. // This WILL draw (ulForeColor == 0) into the bitmap!
  506. // /* if (ulBackColor != 0) it will pre-rect it in. */
  507. // Let a higher level function do tha background rect!
  508. // Make s for an easier transition!
  509. //
  510. short rspBlit(
  511. ULONG ulForeColor,
  512. RImage* pimSrc,
  513. RImage* pimDst,
  514. short sDstX,
  515. short sDstY,
  516. const RRect* prDst
  517. )
  518. {
  519. #ifdef _DEBUG
  520. if ((pimSrc == NULL) || (pimDst == NULL))
  521. {
  522. TRACE("BLiT: null CImage* passed\n");
  523. return -1;
  524. }
  525. if (pimSrc->m_type != RImage::FSPR1)
  526. {
  527. TRACE("BLiT: This form of BLiT is designed for FSPR1 type images!\n");
  528. return -1;
  529. }
  530. if (pimDst->m_sDepth > 8)
  531. {
  532. TRACE("BLiT: TC sprites are not YET implemented for FSPR1.\n");
  533. return -1;
  534. }
  535. #endif
  536. // transfer colors:
  537. UCHAR ucForeColor = (UCHAR) ulForeColor;
  538. // Clip!
  539. short sClipL=0,sClipR=0,sClipT=0,sClipB=0;
  540. short sW = pimSrc->m_sWidth; // clippng parameters...
  541. short sH = pimSrc->m_sHeight; // clippng parameters...
  542. long lDstP = pimDst->m_lPitch;
  543. // For clipping, adjust the destination accordingly but keep the
  544. // source at the origin for decompressed skipping
  545. //
  546. if (prDst)
  547. {
  548. // clip against user values
  549. sClipL = prDst->sX - sDstX; // positive = clipped
  550. if (sClipL > 0) { sW -= sClipL; sDstX = prDst->sX; }
  551. sClipT = prDst->sY - sDstY; // positive = clipped
  552. if (sClipT > 0) { sH -= sClipT; sDstY = prDst->sY; }
  553. // The order here still works because BOTH sDstX AND sW changed!
  554. sClipR = sDstX + sW - prDst->sX - prDst->sW; // positive = clipped
  555. if (sClipR > 0) { sW -= sClipR; }
  556. sClipB = sDstY + sH - prDst->sY - prDst->sH; // positive = clipped
  557. if (sClipB > 0) { sH -= sClipB; }
  558. if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
  559. }
  560. else
  561. {
  562. // clip against full destination buffer
  563. sClipL = -sDstX;
  564. if (sClipL > 0) { sW -= sClipL; sDstX = 0; }
  565. sClipT = -sDstY;
  566. if (sClipR > 0) { sH -= sClipR; sDstY = 0; }
  567. // The order here still works because BOTH sDstX AND sW changed!
  568. sClipR = sDstX + sW - pimDst->m_sWidth; // positive = clipped
  569. if (sClipR > 0) sW -= sClipR; // positive = clipped
  570. sClipB = sDstY + sH - pimDst->m_sHeight; // positive = clipped
  571. if (sClipB > 0) sH -= sClipB; // positive = clipped
  572. if ((sW <= 0) || (sH <= 0)) return -1; // fully clipped
  573. }
  574. // Make positive:
  575. if (sClipL < 0) sClipL = 0;
  576. if (sClipR < 0) sClipR = 0;
  577. if (sClipT < 0) sClipT = 0;
  578. if (sClipB < 0) sClipB = 0;
  579. //************** INSERT BUFFER HOOKS HERE! ************************
  580. // do OS based copying!
  581. short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
  582. short sBlitTypeDst = 0;
  583. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  584. #ifndef _DEBUG
  585. //if (gsScreenLocked || gsBufferLocked) goto BLIT_PRELOCKED;
  586. #endif
  587. // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
  588. // must record which UNLOCK (if any) needs to be done AFTER the BLiT
  589. // has completed. (Lord help me if a blit gets interrupted)
  590. if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)((long)pimDst->m_pSpecial);
  591. switch (sBlitTypeDst) // 0 = normal image
  592. {
  593. case BUF_MEMORY: // image to system buffer
  594. /*
  595. // need to lock / unlock this one:
  596. if (rspLockBuffer()
  597. !=0)
  598. {
  599. TRACE("BLiT: Unable to lock the system buffer, failed!\n");
  600. return -1;
  601. }
  602. // Locked the system buffer, remember to unlock it:
  603. sNeedToUnlock = BUF_MEMORY;
  604. */
  605. break;
  606. case BUF_VRAM: // image to front screen
  607. /*
  608. // need to lock / unlock this one:
  609. if (rspLockScreen()
  610. !=0)
  611. {
  612. TRACE("BLiT: Unable to lock the OnScreen system buffer, failed!\n");
  613. return -1;
  614. }
  615. // Locked the front VRAM, remember to unlock it:
  616. sNeedToUnlock = BUF_VRAM;
  617. */
  618. break;
  619. case BUF_VRAM2: // image to back screen
  620. // need to lock / unlock this one:
  621. if (rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch))
  622. !=0)
  623. {
  624. TRACE("BLiT: Unable to lock the OffScreen system buffer, failed!\n");
  625. return -1;
  626. }
  627. // Locked the front VRAM, remember to unlock it:
  628. sNeedToUnlock = BUF_VRAM;
  629. break;
  630. case 0: // normal image
  631. sNeedToUnlock = 0;
  632. break;
  633. default:
  634. TRACE("BLiT: This type of copy is not yet supported.\n");
  635. return -1;
  636. }
  637. //BLIT_PRELOCKED:
  638. // Check for locking error:
  639. if (!pimDst->m_pData)
  640. {
  641. TRACE("BLiT: NULL data - possible locking error.\n");
  642. return FAILURE;
  643. }
  644. UCHAR *pDst,*pDstLine,*pCode,ucCount;
  645. pDstLine = pimDst->m_pData + lDstP * sDstY + sDstX;
  646. RSpecialFSPR1* pHead = (RSpecialFSPR1*)(pimSrc->m_pSpecialMem);
  647. pCode = pHead->m_pCode;
  648. const UCHAR FF = (UCHAR)255;
  649. //***********************************************************
  650. //***************** AT LAST! CODE! **********************
  651. //***********************************************************
  652. //
  653. //***********************************************************
  654. //********* No clip case!
  655. //***********************************************************
  656. if ( (sClipL|sClipR) != (UCHAR)0) // FULL clip case!
  657. {
  658. TRACE("BLiT: FSPR1=>BMP8, clipping NYI!\n");
  659. }
  660. else if ( (sClipT|sClipB) != (UCHAR)0) // VCLIP case!
  661. {
  662. TRACE("BLiT: FSPR1=>BMP8, clipping NYI!\n");
  663. /*
  664. while (TRUE)
  665. {
  666. if ((*pCode) == FF) // vertical run
  667. { // end of sprite?
  668. if ( (ucCount = *(++pCode)) == FF) break;
  669. pDstLine += lDstP * ucCount;
  670. pCode++; // open stack
  671. continue; // next line
  672. }
  673. pDst = pDstLine;
  674. while ( (ucCount = *(pCode++)) != FF) // EOL
  675. {
  676. pDst += ucCount;
  677. ucCount = *(pCode++);
  678. while (ucCount--) *(pDst++) = ucForeColor;
  679. }
  680. pDstLine += lDstP;
  681. }
  682. */
  683. }
  684. else // NO CLIP CASE!
  685. {
  686. while (TRUE)
  687. {
  688. if ((*pCode) == FF) // vertical run
  689. { // end of sprite?
  690. if ( (ucCount = *(++pCode)) == FF) break;
  691. pDstLine += lDstP * ucCount;
  692. pCode++; // open stack
  693. continue; // next line
  694. }
  695. pDst = pDstLine;
  696. while ( (ucCount = *(pCode++)) != FF) // EOL
  697. {
  698. pDst += ucCount;
  699. ucCount = *(pCode++);
  700. while (ucCount--) *(pDst++) = ucForeColor;
  701. }
  702. pDstLine += lDstP;
  703. }
  704. }
  705. //***********************************************************
  706. //*******************************************************************
  707. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  708. #ifndef _DEBUG
  709. //if (gsScreenLocked || gsBufferLocked) goto BLIT_DONTUNLOCK;
  710. #endif
  711. //********************
  712. // OS_SPECIFIC:
  713. //******************** UNLOCK WHATEVER YOU NEED TO
  714. switch (sNeedToUnlock)
  715. {
  716. case 0: // nothing to unlock
  717. break;
  718. case BUF_MEMORY:
  719. // rspUnlockBuffer();
  720. break;
  721. case BUF_VRAM:
  722. // rspUnlockScreen();
  723. break;
  724. case BUF_VRAM2:
  725. rspUnlockVideoFlipPage();
  726. break;
  727. default:
  728. TRACE("BLiT: Unlocking error!\n");
  729. }
  730. //BLIT_DONTUNLOCK:
  731. return 0;
  732. }
  733. //************************************************************
  734. //************************************************************
  735. //************************************************************
  736. //************************************************************
  737. //*********************** SCALING! *************************
  738. //************************************************************
  739. //************************************************************
  740. //************************************************************
  741. //************************************************************
  742. // 8-bit color for now!
  743. // Doesn't clip...
  744. // The WILL draw (ulForeColor == 0) into the bitmap!
  745. // /*if (ulBackColor != 0) it will pre-rect it in.*/
  746. // For transition reasons, coloring the background is
  747. // left up to a higher level.
  748. //
  749. short rspBlit(
  750. ULONG ulForeColor, // will draw color 0
  751. RImage* pimSrc,
  752. RImage* pimDst,
  753. short sDstX,
  754. short sDstY,
  755. short sDstW,
  756. short sDstH,
  757. const RRect* prDst
  758. )
  759. {
  760. #ifdef _DEBUG
  761. if ((pimSrc == NULL) || (pimDst == NULL))
  762. {
  763. TRACE("BLiT: null CImage* passed\n");
  764. return -1;
  765. }
  766. if (pimSrc->m_type != RImage::FSPR1)
  767. {
  768. TRACE("BLiT: This form of BLiT is designed for FSPR1 type images!\n");
  769. return -1;
  770. }
  771. if (pimDst->m_sDepth > 8)
  772. {
  773. TRACE("BLiT: TC sprites are not YET implemented for FSPR1.\n");
  774. return -1;
  775. }
  776. /*
  777. if ( (sDstH > pimSrc->lHeight) || (sDstW > pimSrc->lWidth))
  778. {
  779. //TRACE("BLiT: Magnifying an FSPR1 NYI.\n");
  780. return -1;
  781. }
  782. if ( (sDstW < 1) || (sDstH < 1) )
  783. {
  784. //TRACE("BLiT: Zero or negative area passed.\n");
  785. return -1;
  786. }
  787. */
  788. #endif
  789. if ( (pimSrc->m_sWidth == sDstW) && (pimSrc->m_sHeight == sDstH) )
  790. {
  791. return rspBlit(ulForeColor,pimSrc,pimDst,sDstX,sDstY,prDst);
  792. }
  793. // transfer colors:
  794. UCHAR ucForeColor = (UCHAR) ulForeColor;
  795. // Clip!
  796. short sClipL=0,sClipR=0,sClipT=0,sClipB=0;
  797. short sW = sDstW; // clippng parameters...
  798. short sH = sDstH; // clippng parameters...
  799. long lDstP = pimDst->m_lPitch;
  800. // For clipping, adjust the destination accordingly but keep the
  801. // source at the origin for decompressed skipping
  802. //
  803. if (prDst)
  804. {
  805. // clip against user values
  806. sClipL = prDst->sX - sDstX; // positive = clipped
  807. if (sClipL > 0) { sW -= sClipL; sDstX = prDst->sX; }
  808. sClipT = prDst->sY - sDstY; // positive = clipped
  809. if (sClipT > 0) { sH -= sClipT; sDstY = prDst->sY; }
  810. // The order here still works because BOTH sDstX AND sW changed!
  811. sClipR = sDstX + sW - prDst->sX - prDst->sW; // positive = clipped
  812. if (sClipR > 0) { sW -= sClipR; }
  813. sClipB = sDstY + sH - prDst->sY - prDst->sH; // positive = clipped
  814. if (sClipB > 0) { sH -= sClipB; }
  815. if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
  816. }
  817. else
  818. {
  819. // clip against full destination buffer
  820. sClipL = -sDstX;
  821. if (sClipL > 0) { sW -= sClipL; sDstX = 0; }
  822. sClipT = -sDstY;
  823. if (sClipR > 0) { sH -= sClipR; sDstY = 0; }
  824. // The order here still works because BOTH sDstX AND sW changed!
  825. sClipR = sDstX + sW - pimDst->m_sWidth; // positive = clipped
  826. if (sClipR > 0) sW -= sClipR; // positive = clipped
  827. sClipB = sDstY + sH - pimDst->m_sHeight; // positive = clipped
  828. if (sClipB > 0) sH -= sClipB; // positive = clipped
  829. if ((sW <= 0) || (sH <= 0)) return -1; // fully clipped
  830. }
  831. // Make positive:
  832. if (sClipL < 0) sClipL = 0;
  833. if (sClipR < 0) sClipR = 0;
  834. if (sClipT < 0) sClipT = 0;
  835. if (sClipB < 0) sClipB = 0;
  836. //************** INSERT BUFFER HOOKS HERE! ************************
  837. // do OS based copying!
  838. short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
  839. short sBlitTypeDst = 0;
  840. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  841. #ifndef _DEBUG
  842. //if (gsScreenLocked || gsBufferLocked) goto BLIT_PRELOCKED;
  843. #endif
  844. // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
  845. // must record which UNLOCK (if any) needs to be done AFTER the BLiT
  846. // has completed. (Lord help me if a blit gets interrupted)
  847. if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)((long)pimDst->m_pSpecial);
  848. switch (sBlitTypeDst) // 0 = normal image
  849. {
  850. case BUF_MEMORY: // image to system buffer
  851. /*
  852. // need to lock / unlock this one:
  853. if (rspLockBuffer()
  854. !=0)
  855. {
  856. TRACE("BLiT: Unable to lock the system buffer, failed!\n");
  857. return -1;
  858. }
  859. // Locked the system buffer, remember to unlock it:
  860. sNeedToUnlock = BUF_MEMORY;
  861. */
  862. break;
  863. case BUF_VRAM: // image to front screen
  864. /*
  865. // need to lock / unlock this one:
  866. if (rspLockScreen()
  867. !=0)
  868. {
  869. TRACE("BLiT: Unable to lock the OnScreen system buffer, failed!\n");
  870. return -1;
  871. }
  872. // Locked the front VRAM, remember to unlock it:
  873. sNeedToUnlock = BUF_VRAM;
  874. break;
  875. */
  876. case BUF_VRAM2: // image to back screen
  877. // need to lock / unlock this one:
  878. if (rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch))
  879. !=0)
  880. {
  881. TRACE("BLiT: Unable to lock the OffScreen system buffer, failed!\n");
  882. return -1;
  883. }
  884. // Locked the front VRAM, remember to unlock it:
  885. sNeedToUnlock = BUF_VRAM;
  886. break;
  887. case 0: // normal image
  888. sNeedToUnlock = 0;
  889. break;
  890. default:
  891. TRACE("BLiT: This type of copy is not yet supported.\n");
  892. return -1;
  893. }
  894. //BLIT_PRELOCKED:
  895. // Check for locking error:
  896. if (!pimDst->m_pData)
  897. {
  898. TRACE("BLiT: NULL data - possible locking error.\n");
  899. return FAILURE;
  900. }
  901. UCHAR *pDst,*pDstLine,*pCode,ucCount;
  902. pDstLine = pimDst->m_pData + lDstP * sDstY + sDstX;
  903. RSpecialFSPR1* pHead = (RSpecialFSPR1*)(pimSrc->m_pSpecial);
  904. pCode = pHead->m_pCode;
  905. const UCHAR FF = (UCHAR)255;
  906. // Let's scale it, baby! (pre-clipping)
  907. short sDenX = pimSrc->m_sWidth;
  908. short sDenY = pimSrc->m_sHeight;
  909. RFracU16 frX = {0};
  910. RFracU16 frOldX = {0};
  911. RFracU16 frOldY = {0},frY = {0};
  912. RFracU16 *afrSkipX=NULL,*afrSkipY=NULL;
  913. afrSkipX = rspfrU16Strafe256(sDstW,sDenX);
  914. afrSkipY = rspfrU16Strafe256(sDstH,sDenY);
  915. // Make magnification possible:
  916. short i;
  917. long *alDstSkip = (long*)calloc(sizeof(long),afrSkipY[1].mod + 2);
  918. for (i=1;i<(afrSkipY[1].mod + 2);i++)
  919. alDstSkip[i] = alDstSkip[i-1] + lDstP;
  920. //***********************************************************
  921. //***************** AT LAST! CODE! **********************
  922. //***********************************************************
  923. //
  924. short sCount; // to allow horizontal magnification > 255...
  925. //***********************************************************
  926. //********* No clip case!
  927. //***********************************************************
  928. if ( (sClipL|sClipR) != (UCHAR)0) // FULL clip case!
  929. {
  930. TRACE("BLiT: FSPR1=>BMP8 + SCALE, clipping NYI!\n");
  931. }
  932. else if ( (sClipT|sClipB) != (UCHAR)0) // VCLIP case!
  933. {
  934. TRACE("BLiT: FSPR1=>BMP8 + SCALE, clipping NYI!\n");
  935. }
  936. else // NO CLIP CASE!
  937. {
  938. while (TRUE)
  939. {
  940. if ((*pCode) == FF) // vertical run
  941. { // end of sprite?
  942. if ( (ucCount = *(++pCode)) == FF) break;
  943. rspfrAdd(frY,afrSkipY[ucCount],sDenY);
  944. pDstLine += lDstP * (frY.mod - frOldY.mod);
  945. pCode++; // open stack
  946. continue; // next line
  947. }
  948. if (frOldY.mod == frY.mod) // do a quick skip of a line:
  949. {
  950. while ( (*(pCode++)) != FF) ; // skip line!
  951. rspfrAdd(frY,afrSkipY[1],sDenY);
  952. pDstLine += alDstSkip[frY.mod - frOldY.mod];
  953. }
  954. else // actually draw it!
  955. {
  956. frOldY = frY;
  957. pDst = pDstLine;
  958. frX.set = 0; // start of line!
  959. while ( (ucCount = *(pCode++)) != FF) // EOL
  960. {
  961. frOldX = frX;
  962. rspfrAdd(frX,afrSkipX[ucCount],sDenX);
  963. pDst += (frX.mod - frOldX.mod); // skip
  964. ucCount = *(pCode++);
  965. frOldX = frX;
  966. rspfrAdd(frX,afrSkipX[ucCount],sDenX);
  967. // To allow magnification beyond 255:
  968. sCount = frX.mod - frOldX.mod;
  969. // Modify this to a rect for solid VMagnification.
  970. while (sCount--) *(pDst++) = ucForeColor;
  971. }
  972. rspfrAdd(frY,afrSkipY[1],sDenY);
  973. pDstLine += alDstSkip[frY.mod - frOldY.mod];
  974. }
  975. }
  976. }
  977. free(alDstSkip);
  978. free(afrSkipX);
  979. free(afrSkipY);
  980. //***********************************************************
  981. //*******************************************************************
  982. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  983. #ifndef _DEBUG
  984. //if (gsScreenLocked || gsBufferLocked) goto BLIT_DONTUNLOCK;
  985. #endif
  986. //********************
  987. // OS_SPECIFIC:
  988. //******************** UNLOCK WHATEVER YOU NEED TO
  989. switch (sNeedToUnlock)
  990. {
  991. case 0: // nothing to unlock
  992. break;
  993. case BUF_MEMORY:
  994. // rspUnlockBuffer();
  995. break;
  996. case BUF_VRAM:
  997. // rspUnlockScreen();
  998. break;
  999. case BUF_VRAM2:
  1000. rspUnlockVideoFlipPage();
  1001. break;
  1002. default:
  1003. TRACE("BLiT: Unlocking error!\n");
  1004. }
  1005. //BLIT_DONTUNLOCK:
  1006. return 0;
  1007. }
  1008. //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  1009. //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  1010. //XXXXXXXXXXXX Text Effects (no clipping!) XXXXXXXXXXXX
  1011. //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  1012. //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  1013. //************************************************************
  1014. //********************* NON-SCALING! ***********************
  1015. //************************************************************
  1016. // 8-bit color for now!
  1017. // Doesn't clip...
  1018. // This WILL draw (ulForeColor == 0) into the bitmap!
  1019. // /* if (ulBackColor != 0) it will pre-rect it in. */
  1020. // Let a higher level function do tha background rect!
  1021. // Make s for an easier transition!
  1022. //
  1023. short rspBlit(
  1024. ULONG ulForeColor,
  1025. RImage* pimSrc,
  1026. RImage* pimDst,
  1027. short sDstX,
  1028. short sDstY,
  1029. short* psLineOffset // Must be as long as the height!
  1030. )
  1031. {
  1032. #ifdef _DEBUG
  1033. if ((pimSrc == NULL) || (pimDst == NULL))
  1034. {
  1035. TRACE("BLiT: null CImage* passed\n");
  1036. return -1;
  1037. }
  1038. if (pimSrc->m_type != RImage::FSPR1)
  1039. {
  1040. TRACE("BLiT: This form of BLiT is designed for FSPR1 type images!\n");
  1041. return -1;
  1042. }
  1043. if (pimDst->m_sDepth > 8)
  1044. {
  1045. TRACE("BLiT: TC sprites are not YET implemented for FSPR1.\n");
  1046. return -1;
  1047. }
  1048. #endif
  1049. // transfer colors:
  1050. UCHAR ucForeColor = (UCHAR) ulForeColor;
  1051. long lDstP = pimDst->m_lPitch;
  1052. //************** INSERT BUFFER HOOKS HERE! ************************
  1053. // do OS based copying!
  1054. short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
  1055. short sBlitTypeDst = 0;
  1056. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  1057. #ifndef _DEBUG
  1058. //if (gsScreenLocked || gsBufferLocked) goto BLIT_PRELOCKED;
  1059. #endif
  1060. // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
  1061. // must record which UNLOCK (if any) needs to be done AFTER the BLiT
  1062. // has completed. (Lord help me if a blit gets interrupted)
  1063. if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)((long)pimDst->m_pSpecial);
  1064. switch (sBlitTypeDst) // 0 = normal image
  1065. {
  1066. case BUF_MEMORY: // image to system buffer
  1067. /*
  1068. // need to lock / unlock this one:
  1069. if (rspLockBuffer()
  1070. !=0)
  1071. {
  1072. TRACE("BLiT: Unable to lock the system buffer, failed!\n");
  1073. return -1;
  1074. }
  1075. // Locked the system buffer, remember to unlock it:
  1076. sNeedToUnlock = BUF_MEMORY;
  1077. */
  1078. break;
  1079. case BUF_VRAM: // image to front screen
  1080. /*
  1081. // need to lock / unlock this one:
  1082. if (rspLockScreen()
  1083. !=0)
  1084. {
  1085. TRACE("BLiT: Unable to lock the OnScreen system buffer, failed!\n");
  1086. return -1;
  1087. }
  1088. // Locked the front VRAM, remember to unlock it:
  1089. sNeedToUnlock = BUF_VRAM;
  1090. */
  1091. break;
  1092. case BUF_VRAM2: // image to back screen
  1093. // need to lock / unlock this one:
  1094. if (rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch))
  1095. !=0)
  1096. {
  1097. TRACE("BLiT: Unable to lock the OffScreen system buffer, failed!\n");
  1098. return -1;
  1099. }
  1100. // Locked the front VRAM, remember to unlock it:
  1101. sNeedToUnlock = BUF_VRAM;
  1102. break;
  1103. case 0: // normal image
  1104. sNeedToUnlock = 0;
  1105. break;
  1106. default:
  1107. TRACE("BLiT: This type of copy is not yet supported.\n");
  1108. return -1;
  1109. }
  1110. //BLIT_PRELOCKED:
  1111. // check for locking error:
  1112. if (!pimDst->m_pData)
  1113. {
  1114. TRACE("Blit: NULL data - possible locking error.\n");
  1115. return FAILURE;
  1116. }
  1117. UCHAR *pDst,*pDstLine,*pCode,ucCount;
  1118. pDstLine = pimDst->m_pData + lDstP * sDstY + sDstX;
  1119. RSpecialFSPR1* pHead = (RSpecialFSPR1*)(pimSrc->m_pSpecialMem);
  1120. pCode = pHead->m_pCode;
  1121. const UCHAR FF = (UCHAR)255;
  1122. //***********************************************************
  1123. //***************** AT LAST! CODE! **********************
  1124. //***********************************************************
  1125. //
  1126. //***********************************************************
  1127. //********* No clip case!
  1128. //***********************************************************
  1129. // Add Italics ability:
  1130. short* psOffX = psLineOffset;
  1131. while (TRUE)
  1132. {
  1133. if ((*pCode) == FF) // vertical run
  1134. { // end of sprite?
  1135. if ( (ucCount = *(++pCode)) == FF) break;
  1136. pDstLine += lDstP * ucCount;
  1137. psOffX += ucCount; // Italics
  1138. pCode++; // open stack
  1139. continue; // next line
  1140. }
  1141. pDst = pDstLine + *psOffX; // Italics
  1142. while ( (ucCount = *(pCode++)) != FF) // EOL
  1143. {
  1144. pDst += ucCount;
  1145. ucCount = *(pCode++);
  1146. while (ucCount--) *(pDst++) = ucForeColor;
  1147. }
  1148. pDstLine += lDstP;
  1149. psOffX++;
  1150. }
  1151. //***********************************************************
  1152. //*******************************************************************
  1153. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  1154. #ifndef _DEBUG
  1155. //if (gsScreenLocked || gsBufferLocked) goto BLIT_DONTUNLOCK;
  1156. #endif
  1157. //********************
  1158. // OS_SPECIFIC:
  1159. //******************** UNLOCK WHATEVER YOU NEED TO
  1160. switch (sNeedToUnlock)
  1161. {
  1162. case 0: // nothing to unlock
  1163. break;
  1164. case BUF_MEMORY:
  1165. // rspUnlockBuffer();
  1166. break;
  1167. case BUF_VRAM:
  1168. // rspUnlockScreen();
  1169. break;
  1170. case BUF_VRAM2:
  1171. rspUnlockVideoFlipPage();
  1172. break;
  1173. default:
  1174. TRACE("BLiT: Unlocking error!\n");
  1175. }
  1176. //BLIT_DONTUNLOCK:
  1177. return 0;
  1178. }
  1179. //************************************************************
  1180. //************************************************************
  1181. //************************************************************
  1182. //************************************************************
  1183. //*********************** SCALING! *************************
  1184. //************************************************************
  1185. //************************************************************
  1186. //************************************************************
  1187. //************************************************************
  1188. // 8-bit color for now!
  1189. // Doesn't clip...
  1190. // The WILL draw (ulForeColor == 0) into the bitmap!
  1191. // /*if (ulBackColor != 0) it will pre-rect it in.*/
  1192. // For transition reasons, coloring the background is
  1193. // left up to a higher level.
  1194. //
  1195. short rspBlit(
  1196. ULONG ulForeColor, // will draw color 0
  1197. RImage* pimSrc,
  1198. RImage* pimDst,
  1199. short sDstX,
  1200. short sDstY,
  1201. short sDstW,
  1202. short sDstH,
  1203. short* psLineOffset // Must be as long as the height!
  1204. )
  1205. {
  1206. #ifdef _DEBUG
  1207. if ((pimSrc == NULL) || (pimDst == NULL))
  1208. {
  1209. TRACE("BLiT: null CImage* passed\n");
  1210. return -1;
  1211. }
  1212. if (pimSrc->m_type != RImage::FSPR1)
  1213. {
  1214. TRACE("BLiT: This form of BLiT is designed for FSPR1 type images!\n");
  1215. return -1;
  1216. }
  1217. if (pimDst->m_sDepth > 8)
  1218. {
  1219. TRACE("BLiT: TC sprites are not YET implemented for FSPR1.\n");
  1220. return -1;
  1221. }
  1222. #endif
  1223. if ( (sDstW < 1) || (sDstH < 1) )
  1224. {
  1225. //TRACE("BLiT: Zero or negative area passed.\n");
  1226. return -1;
  1227. }
  1228. // transfer colors:
  1229. UCHAR ucForeColor = (UCHAR) ulForeColor;
  1230. short sW = sDstW; // clippng parameters...
  1231. short sH = sDstH; // clippng parameters...
  1232. long lDstP = pimDst->m_lPitch;
  1233. //************** INSERT BUFFER HOOKS HERE! ************************
  1234. // do OS based copying!
  1235. short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
  1236. short sBlitTypeDst = 0;
  1237. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  1238. #ifndef _DEBUG
  1239. //if (gsScreenLocked || gsBufferLocked) goto BLIT_PRELOCKED;
  1240. #endif
  1241. // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
  1242. // must record which UNLOCK (if any) needs to be done AFTER the BLiT
  1243. // has completed. (Lord help me if a blit gets interrupted)
  1244. if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)((long)pimDst->m_pSpecial);
  1245. switch (sBlitTypeDst) // 0 = normal image
  1246. {
  1247. case BUF_MEMORY: // image to system buffer
  1248. // need to lock / unlock this one:
  1249. /*
  1250. if (rspLockBuffer()
  1251. !=0)
  1252. {
  1253. TRACE("BLiT: Unable to lock the system buffer, failed!\n");
  1254. return -1;
  1255. }
  1256. // Locked the system buffer, remember to unlock it:
  1257. sNeedToUnlock = BUF_MEMORY;
  1258. */
  1259. break;
  1260. case BUF_VRAM: // image to front screen
  1261. /*
  1262. // need to lock / unlock this one:
  1263. if (rspLockScreen()
  1264. !=0)
  1265. {
  1266. TRACE("BLiT: Unable to lock the OnScreen system buffer, failed!\n");
  1267. return -1;
  1268. }
  1269. // Locked the front VRAM, remember to unlock it:
  1270. sNeedToUnlock = BUF_VRAM;
  1271. */
  1272. break;
  1273. case BUF_VRAM2: // image to back screen
  1274. // need to lock / unlock this one:
  1275. if (rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch))
  1276. !=0)
  1277. {
  1278. TRACE("BLiT: Unable to lock the OffScreen system buffer, failed!\n");
  1279. return -1;
  1280. }
  1281. // Locked the front VRAM, remember to unlock it:
  1282. sNeedToUnlock = BUF_VRAM;
  1283. break;
  1284. case 0: // normal image
  1285. sNeedToUnlock = 0;
  1286. break;
  1287. default:
  1288. TRACE("BLiT: This type of copy is not yet supported.\n");
  1289. return -1;
  1290. }
  1291. //BLIT_PRELOCKED:
  1292. // Check for locking error:
  1293. if (!pimDst->m_pData)
  1294. {
  1295. TRACE("BLiT: NULL data - possible locking error.\n");
  1296. return FAILURE;
  1297. }
  1298. UCHAR *pDst,*pDstLine,*pCode,ucCount;
  1299. pDstLine = pimDst->m_pData + lDstP * sDstY + sDstX;
  1300. RSpecialFSPR1* pHead = (RSpecialFSPR1*)(pimSrc->m_pSpecial);
  1301. pCode = pHead->m_pCode;
  1302. const UCHAR FF = (UCHAR)255;
  1303. // Let's scale it, baby! (pre-clipping)
  1304. short sDenX = pimSrc->m_sWidth;
  1305. short sDenY = pimSrc->m_sHeight;
  1306. RFracU16 frX = {0};
  1307. RFracU16 frOldX = {0};
  1308. RFracU16 frOldY = {0},frY = {0};
  1309. RFracU16 *afrSkipX=NULL,*afrSkipY=NULL;
  1310. afrSkipX = rspfrU16Strafe256(sDstW,sDenX);
  1311. afrSkipY = rspfrU16Strafe256(sDstH,sDenY);
  1312. // Make magnification possible:
  1313. short i;
  1314. long *alDstSkip = (long*)calloc(sizeof(long),afrSkipY[1].mod + 2);
  1315. for (i=1;i<(afrSkipY[1].mod + 2);i++)
  1316. alDstSkip[i] = alDstSkip[i-1] + lDstP;
  1317. //***********************************************************
  1318. //***************** AT LAST! CODE! **********************
  1319. //***********************************************************
  1320. //
  1321. //***********************************************************
  1322. //********* No clip case!
  1323. //***********************************************************
  1324. // Add Italics ability:
  1325. short* psOffX = psLineOffset;
  1326. short sCount; // Allows magnified runs > 255...
  1327. while (TRUE)
  1328. {
  1329. if ((*pCode) == FF) // vertical run
  1330. { // end of sprite?
  1331. if ( (ucCount = *(++pCode)) == FF) break;
  1332. rspfrAdd(frY,afrSkipY[ucCount],sDenY);
  1333. pDstLine += lDstP * (frY.mod - frOldY.mod);
  1334. psOffX += (frY.mod - frOldY.mod); // Italics
  1335. pCode++; // open stack
  1336. continue; // next line
  1337. }
  1338. if (frOldY.mod == frY.mod) // do a quick skip of a line:
  1339. {
  1340. while ( (*(pCode++)) != FF) ; // skip line!
  1341. rspfrAdd(frY,afrSkipY[1],sDenY);
  1342. pDstLine += alDstSkip[frY.mod - frOldY.mod];
  1343. psOffX += frY.mod - frOldY.mod;
  1344. }
  1345. else // actually draw it!
  1346. {
  1347. frOldY = frY;
  1348. pDst = pDstLine + *psOffX; // Italics
  1349. frX.set = 0; // start of line!
  1350. while ( (ucCount = *(pCode++)) != FF) // EOL
  1351. {
  1352. frOldX = frX;
  1353. rspfrAdd(frX,afrSkipX[ucCount],sDenX);
  1354. pDst += (frX.mod - frOldX.mod); // skip
  1355. ucCount = *(pCode++);
  1356. frOldX = frX;
  1357. rspfrAdd(frX,afrSkipX[ucCount],sDenX);
  1358. // This is to allow magnified runs > 255:
  1359. sCount = frX.mod - frOldX.mod;
  1360. // Modify this to a rect for solid VMagnification.
  1361. while (sCount--) *(pDst++) = ucForeColor;
  1362. }
  1363. rspfrAdd(frY,afrSkipY[1],sDenY);
  1364. pDstLine += alDstSkip[frY.mod - frOldY.mod];
  1365. psOffX += frY.mod - frOldY.mod;
  1366. }
  1367. }
  1368. free(alDstSkip);
  1369. free(afrSkipX);
  1370. free(afrSkipY);
  1371. //***********************************************************
  1372. //*******************************************************************
  1373. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  1374. #ifndef _DEBUG
  1375. //if (gsScreenLocked || gsBufferLocked) goto BLIT_DONTUNLOCK;
  1376. #endif
  1377. //********************
  1378. // OS_SPECIFIC:
  1379. //******************** UNLOCK WHATEVER YOU NEED TO
  1380. switch (sNeedToUnlock)
  1381. {
  1382. case 0: // nothing to unlock
  1383. break;
  1384. case BUF_MEMORY:
  1385. // rspUnlockBuffer();
  1386. break;
  1387. case BUF_VRAM:
  1388. // rspUnlockScreen();
  1389. break;
  1390. case BUF_VRAM2:
  1391. rspUnlockVideoFlipPage();
  1392. break;
  1393. default:
  1394. TRACE("BLiT: Unlocking error!\n");
  1395. }
  1396. //BLIT_DONTUNLOCK:
  1397. return 0;
  1398. }