PageRenderTime 82ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/src/FreeImage/Source/LibMNG/libmng_display.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1418 lines | 951 code | 148 blank | 319 comment | 202 complexity | 0db316acf17863ec734bc3a61aa9cc6c MD5 | raw file
Possible License(s): LGPL-3.0, BSD-3-Clause, CPL-1.0, Unlicense, GPL-2.0, GPL-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, BSD-2-Clause, LGPL-2.1
  1. /* ************************************************************************** */
  2. /* * For conditions of distribution and use, * */
  3. /* * see copyright notice in libmng.h * */
  4. /* ************************************************************************** */
  5. /* * * */
  6. /* * project : libmng * */
  7. /* * file : libmng_display.c copyright (c) 2000-2007 G.Juyn * */
  8. /* * version : 1.0.10 * */
  9. /* * * */
  10. /* * purpose : Display management (implementation) * */
  11. /* * * */
  12. /* * author : G.Juyn * */
  13. /* * * */
  14. /* * comment : implementation of the display management routines * */
  15. /* * * */
  16. /* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
  17. /* * - changed strict-ANSI stuff * */
  18. /* * 0.5.1 - 05/11/2000 - G.Juyn * */
  19. /* * - added callback error-reporting support * */
  20. /* * - fixed frame_delay misalignment * */
  21. /* * 0.5.1 - 05/12/2000 - G.Juyn * */
  22. /* * - added sanity check for frozen status * */
  23. /* * - changed trace to macro for callback error-reporting * */
  24. /* * 0.5.1 - 05/13/2000 - G.Juyn * */
  25. /* * - changed display_mend to reset state to initial or SAVE * */
  26. /* * - added eMNGma hack (will be removed in 1.0.0 !!!) * */
  27. /* * - added TERM animation object pointer (easier reference) * */
  28. /* * - added process_save & process_seek routines * */
  29. /* * 0.5.1 - 05/14/2000 - G.Juyn * */
  30. /* * - added save_state and restore_state for SAVE/SEEK/TERM * */
  31. /* * processing * */
  32. /* * * */
  33. /* * 0.5.2 - 05/20/2000 - G.Juyn * */
  34. /* * - added JNG support (JHDR/JDAT) * */
  35. /* * 0.5.2 - 05/23/2000 - G.Juyn * */
  36. /* * - fixed problem with DEFI clipping * */
  37. /* * 0.5.2 - 05/30/2000 - G.Juyn * */
  38. /* * - added delta-image support (DHDR,PROM,IPNG,IJNG) * */
  39. /* * 0.5.2 - 05/31/2000 - G.Juyn * */
  40. /* * - fixed pointer confusion (contributed by Tim Rowley) * */
  41. /* * 0.5.2 - 06/03/2000 - G.Juyn * */
  42. /* * - fixed makeup for Linux gcc compile * */
  43. /* * 0.5.2 - 06/05/2000 - G.Juyn * */
  44. /* * - added support for RGB8_A8 canvasstyle * */
  45. /* * 0.5.2 - 06/09/2000 - G.Juyn * */
  46. /* * - fixed timer-handling to run with Mozilla (Tim Rowley) * */
  47. /* * 0.5.2 - 06/10/2000 - G.Juyn * */
  48. /* * - fixed some compilation-warnings (contrib Jason Morris) * */
  49. /* * * */
  50. /* * 0.5.3 - 06/12/2000 - G.Juyn * */
  51. /* * - fixed display of stored JNG images * */
  52. /* * 0.5.3 - 06/13/2000 - G.Juyn * */
  53. /* * - fixed problem with BASI-IEND as object 0 * */
  54. /* * 0.5.3 - 06/16/2000 - G.Juyn * */
  55. /* * - changed progressive-display processing * */
  56. /* * 0.5.3 - 06/17/2000 - G.Juyn * */
  57. /* * - changed delta-image processing * */
  58. /* * 0.5.3 - 06/20/2000 - G.Juyn * */
  59. /* * - fixed some minor stuff * */
  60. /* * 0.5.3 - 06/21/2000 - G.Juyn * */
  61. /* * - added speed-modifier to timing routine * */
  62. /* * 0.5.3 - 06/22/2000 - G.Juyn * */
  63. /* * - added support for PPLT chunk processing * */
  64. /* * 0.5.3 - 06/29/2000 - G.Juyn * */
  65. /* * - swapped refresh parameters * */
  66. /* * * */
  67. /* * 0.9.0 - 06/30/2000 - G.Juyn * */
  68. /* * - changed refresh parameters to 'x,y,width,height' * */
  69. /* * * */
  70. /* * 0.9.1 - 07/07/2000 - G.Juyn * */
  71. /* * - implemented support for freeze/reset/resume & go_xxxx * */
  72. /* * 0.9.1 - 07/08/2000 - G.Juyn * */
  73. /* * - added support for improved timing * */
  74. /* * 0.9.1 - 07/14/2000 - G.Juyn * */
  75. /* * - changed EOF processing behavior * */
  76. /* * - fixed TERM delay processing * */
  77. /* * 0.9.1 - 07/15/2000 - G.Juyn * */
  78. /* * - fixed freeze & reset processing * */
  79. /* * 0.9.1 - 07/16/2000 - G.Juyn * */
  80. /* * - fixed storage of images during mng_read() * */
  81. /* * - fixed support for mng_display() after mng_read() * */
  82. /* * 0.9.1 - 07/24/2000 - G.Juyn * */
  83. /* * - fixed reading of still-images * */
  84. /* * * */
  85. /* * 0.9.2 - 08/05/2000 - G.Juyn * */
  86. /* * - changed file-prefixes * */
  87. /* * * */
  88. /* * 0.9.3 - 08/07/2000 - G.Juyn * */
  89. /* * - B111300 - fixup for improved portability * */
  90. /* * 0.9.3 - 08/21/2000 - G.Juyn * */
  91. /* * - fixed TERM processing delay of 0 msecs * */
  92. /* * 0.9.3 - 08/26/2000 - G.Juyn * */
  93. /* * - added MAGN chunk * */
  94. /* * 0.9.3 - 09/10/2000 - G.Juyn * */
  95. /* * - fixed problem with no refresh after TERM * */
  96. /* * - fixed DEFI behavior * */
  97. /* * 0.9.3 - 09/16/2000 - G.Juyn * */
  98. /* * - fixed timing & refresh behavior for single PNG/JNG * */
  99. /* * 0.9.3 - 09/19/2000 - G.Juyn * */
  100. /* * - refixed timing & refresh behavior for single PNG/JNG * */
  101. /* * 0.9.3 - 10/02/2000 - G.Juyn * */
  102. /* * - fixed timing again (this is getting boring...) * */
  103. /* * - refixed problem with no refresh after TERM * */
  104. /* * 0.9.3 - 10/16/2000 - G.Juyn * */
  105. /* * - added JDAA chunk * */
  106. /* * 0.9.3 - 10/17/2000 - G.Juyn * */
  107. /* * - fixed support for bKGD * */
  108. /* * 0.9.3 - 10/18/2000 - G.Juyn * */
  109. /* * - fixed delta-processing behavior * */
  110. /* * 0.9.3 - 10/19/2000 - G.Juyn * */
  111. /* * - added storage for pixel-/alpha-sampledepth for delta's * */
  112. /* * 0.9.3 - 10/27/2000 - G.Juyn * */
  113. /* * - fixed separate read() & display() processing * */
  114. /* * * */
  115. /* * 0.9.4 - 10/31/2000 - G.Juyn * */
  116. /* * - fixed possible loop in display_resume() (Thanks Vova!) * */
  117. /* * 0.9.4 - 11/20/2000 - G.Juyn * */
  118. /* * - fixed unwanted repetition in mng_readdisplay() * */
  119. /* * 0.9.4 - 11/24/2000 - G.Juyn * */
  120. /* * - moved restore of object 0 to libmng_display * */
  121. /* * - added restore of object 0 to TERM processing !!! * */
  122. /* * - fixed TERM delay processing * */
  123. /* * - fixed TERM end processing (count = 0) * */
  124. /* * 0.9.4 - 12/16/2000 - G.Juyn * */
  125. /* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */
  126. /* * 0.9.4 - 1/18/2001 - G.Juyn * */
  127. /* * - removed test filter-methods 1 & 65 * */
  128. /* * - set default level-set for filtertype=64 to all zeroes * */
  129. /* * * */
  130. /* * 0.9.5 - 1/20/2001 - G.Juyn * */
  131. /* * - fixed compiler-warnings Mozilla (thanks Tim) * */
  132. /* * 0.9.5 - 1/23/2001 - G.Juyn * */
  133. /* * - fixed timing-problem with switching framing_modes * */
  134. /* * * */
  135. /* * 1.0.1 - 02/08/2001 - G.Juyn * */
  136. /* * - added MEND processing callback * */
  137. /* * 1.0.1 - 02/13/2001 - G.Juyn * */
  138. /* * - fixed first FRAM_MODE=4 timing problem * */
  139. /* * 1.0.1 - 04/21/2001 - G.Juyn * */
  140. /* * - fixed memory-leak for JNGs with alpha (Thanks Gregg!) * */
  141. /* * - added BGRA8 canvas with premultiplied alpha * */
  142. /* * * */
  143. /* * 1.0.2 - 06/25/2001 - G.Juyn * */
  144. /* * - fixed memory-leak with delta-images (Thanks Michael!) * */
  145. /* * * */
  146. /* * 1.0.5 - 08/15/2002 - G.Juyn * */
  147. /* * - completed PROM support * */
  148. /* * - completed delta-image support * */
  149. /* * 1.0.5 - 08/19/2002 - G.Juyn * */
  150. /* * - B597134 - libmng pollutes the linker namespace * */
  151. /* * 1.0.5 - 09/13/2002 - G.Juyn * */
  152. /* * - fixed read/write of MAGN chunk * */
  153. /* * 1.0.5 - 09/15/2002 - G.Juyn * */
  154. /* * - fixed LOOP iteration=0 special case * */
  155. /* * 1.0.5 - 09/19/2002 - G.Juyn * */
  156. /* * - fixed color-correction for restore-background handling * */
  157. /* * - optimized restore-background for bKGD cases * */
  158. /* * - cleaned up some old stuff * */
  159. /* * 1.0.5 - 09/20/2002 - G.Juyn * */
  160. /* * - finished support for BACK image & tiling * */
  161. /* * - added support for PAST * */
  162. /* * 1.0.5 - 09/22/2002 - G.Juyn * */
  163. /* * - added bgrx8 canvas (filler byte) * */
  164. /* * 1.0.5 - 10/05/2002 - G.Juyn * */
  165. /* * - fixed dropping mix of frozen/unfrozen objects * */
  166. /* * 1.0.5 - 10/07/2002 - G.Juyn * */
  167. /* * - added proposed change in handling of TERM- & if-delay * */
  168. /* * - added another fix for misplaced TERM chunk * */
  169. /* * - completed support for condition=2 in TERM chunk * */
  170. /* * 1.0.5 - 10/18/2002 - G.Juyn * */
  171. /* * - fixed clipping-problem with BACK tiling (Thanks Sakura!) * */
  172. /* * 1.0.5 - 10/20/2002 - G.Juyn * */
  173. /* * - fixed processing for multiple objects in MAGN * */
  174. /* * - fixed display of visible target of PAST operation * */
  175. /* * 1.0.5 - 10/30/2002 - G.Juyn * */
  176. /* * - modified TERM/MEND processing for max(1, TERM_delay, * */
  177. /* * interframe_delay) * */
  178. /* * 1.0.5 - 11/04/2002 - G.Juyn * */
  179. /* * - fixed layer- & frame-counting during read() * */
  180. /* * - fixed goframe/golayer/gotime processing * */
  181. /* * 1.0.5 - 01/19/2003 - G.Juyn * */
  182. /* * - B654627 - fixed SEGV when no gettickcount callback * */
  183. /* * - B664383 - fixed typo * */
  184. /* * - finalized changes in TERM/final_delay to elected proposal* */
  185. /* * * */
  186. /* * 1.0.6 - 05/11/2003 - G. Juyn * */
  187. /* * - added conditionals around canvas update routines * */
  188. /* * 1.0.6 - 05/25/2003 - G.R-P * */
  189. /* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
  190. /* * 1.0.6 - 07/07/2003 - G.R-P * */
  191. /* * - added conditionals around some JNG-supporting code * */
  192. /* * - added conditionals around 16-bit supporting code * */
  193. /* * - reversed some loops to use decrementing counter * */
  194. /* * - combined init functions into one function * */
  195. /* * 1.0.6 - 07/10/2003 - G.R-P * */
  196. /* * - replaced nested switches with simple init setup function * */
  197. /* * 1.0.6 - 07/29/2003 - G.R-P * */
  198. /* * - added conditionals around PAST chunk support * */
  199. /* * 1.0.6 - 08/17/2003 - G.R-P * */
  200. /* * - added conditionals around non-VLC chunk support * */
  201. /* * * */
  202. /* * 1.0.7 - 11/27/2003 - R.A * */
  203. /* * - added CANVAS_RGB565 and CANVAS_BGR565 * */
  204. /* * 1.0.7 - 12/06/2003 - R.A * */
  205. /* * - added CANVAS_RGBA565 and CANVAS_BGRA565 * */
  206. /* * 1.0.7 - 01/25/2004 - J.S * */
  207. /* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
  208. /* * * */
  209. /* * 1.0.8 - 03/31/2004 - G.Juyn * */
  210. /* * - fixed problem with PAST usage where source > dest * */
  211. /* * 1.0.8 - 05/04/2004 - G.R-P. * */
  212. /* * - fixed misplaced 16-bit conditionals * */
  213. /* * * */
  214. /* * 1.0.9 - 09/18/2004 - G.R-P. * */
  215. /* * - revised some SKIPCHUNK conditionals * */
  216. /* * 1.0.9 - 10/10/2004 - G.R-P. * */
  217. /* * - added MNG_NO_1_2_4BIT_SUPPORT * */
  218. /* * 1.0.9 - 10/14/2004 - G.Juyn * */
  219. /* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */
  220. /* * 1.0.9 - 12/11/2004 - G.Juyn * */
  221. /* * - added conditional MNG_OPTIMIZE_DISPLAYCALLS * */
  222. /* * 1.0.9 - 12/20/2004 - G.Juyn * */
  223. /* * - cleaned up macro-invocations (thanks to D. Airlie) * */
  224. /* * * */
  225. /* * 1.0.10 - 07/06/2005 - G.R-P. * */
  226. /* * - added more SKIPCHUNK conditionals * */
  227. /* * 1.0.10 - 12/28/2005 - G.R-P. * */
  228. /* * - added missing SKIPCHUNK_MAGN conditional * */
  229. /* * 1.0.10 - 03/07/2006 - (thanks to W. Manthey) * */
  230. /* * - added CANVAS_RGB555 and CANVAS_BGR555 * */
  231. /* * 1.0.10 - 04/08/2007 - G.Juyn * */
  232. /* * - fixed several compiler warnings * */
  233. /* * 1.0.10 - 04/08/2007 - G.Juyn * */
  234. /* * - added support for mPNG proposal * */
  235. /* * 1.0.10 - 04/12/2007 - G.Juyn * */
  236. /* * - added support for ANG proposal * */
  237. /* * * */
  238. /* ************************************************************************** */
  239. #include "libmng.h"
  240. #include "libmng_data.h"
  241. #include "libmng_error.h"
  242. #include "libmng_trace.h"
  243. #ifdef __BORLANDC__
  244. #pragma hdrstop
  245. #endif
  246. #include "libmng_chunks.h"
  247. #include "libmng_objects.h"
  248. #include "libmng_object_prc.h"
  249. #include "libmng_memory.h"
  250. #include "libmng_zlib.h"
  251. #include "libmng_jpeg.h"
  252. #include "libmng_cms.h"
  253. #include "libmng_pixels.h"
  254. #include "libmng_display.h"
  255. #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
  256. #pragma option -A /* force ANSI-C */
  257. #endif
  258. /* ************************************************************************** */
  259. #ifdef MNG_INCLUDE_DISPLAY_PROCS
  260. /* ************************************************************************** */
  261. MNG_LOCAL mng_retcode set_delay (mng_datap pData,
  262. mng_uint32 iInterval)
  263. {
  264. if (!iInterval) /* at least 1 msec please! */
  265. iInterval = 1;
  266. if (pData->bRunning) /* only when really displaying */
  267. if (!pData->fSettimer ((mng_handle)pData, iInterval))
  268. MNG_ERROR (pData, MNG_APPTIMERERROR);
  269. #ifdef MNG_SUPPORT_DYNAMICMNG
  270. if ((!pData->bDynamic) || (pData->bRunning))
  271. #else
  272. if (pData->bRunning)
  273. #endif
  274. pData->bTimerset = MNG_TRUE; /* and indicate so */
  275. return MNG_NOERROR;
  276. }
  277. /* ************************************************************************** */
  278. MNG_LOCAL mng_uint32 calculate_delay (mng_datap pData,
  279. mng_uint32 iDelay)
  280. {
  281. mng_uint32 iTicks = pData->iTicks;
  282. mng_uint32 iWaitfor = 1; /* default non-MNG delay */
  283. if (!iTicks) /* tick_count not specified ? */
  284. if (pData->eImagetype == mng_it_mng)
  285. iTicks = 1000;
  286. if (iTicks)
  287. {
  288. switch (pData->iSpeed) /* honor speed modifier */
  289. {
  290. case mng_st_fast :
  291. {
  292. iWaitfor = (mng_uint32)(( 500 * iDelay) / iTicks);
  293. break;
  294. }
  295. case mng_st_slow :
  296. {
  297. iWaitfor = (mng_uint32)((3000 * iDelay) / iTicks);
  298. break;
  299. }
  300. case mng_st_slowest :
  301. {
  302. iWaitfor = (mng_uint32)((8000 * iDelay) / iTicks);
  303. break;
  304. }
  305. default :
  306. {
  307. iWaitfor = (mng_uint32)((1000 * iDelay) / iTicks);
  308. }
  309. }
  310. }
  311. return iWaitfor;
  312. }
  313. /* ************************************************************************** */
  314. /* * * */
  315. /* * Progressive display refresh - does the call to the refresh callback * */
  316. /* * and sets the timer to allow the app to perform the actual refresh to * */
  317. /* * the screen (eg. process its main message-loop) * */
  318. /* * * */
  319. /* ************************************************************************** */
  320. mng_retcode mng_display_progressive_refresh (mng_datap pData,
  321. mng_uint32 iInterval)
  322. {
  323. { /* let the app refresh first ? */
  324. if ((pData->bRunning) && (!pData->bSkipping) &&
  325. (pData->iUpdatetop < pData->iUpdatebottom) && (pData->iUpdateleft < pData->iUpdateright))
  326. {
  327. if (!pData->fRefresh (((mng_handle)pData),
  328. pData->iUpdateleft, pData->iUpdatetop,
  329. pData->iUpdateright - pData->iUpdateleft,
  330. pData->iUpdatebottom - pData->iUpdatetop))
  331. MNG_ERROR (pData, MNG_APPMISCERROR);
  332. pData->iUpdateleft = 0; /* reset update-region */
  333. pData->iUpdateright = 0;
  334. pData->iUpdatetop = 0;
  335. pData->iUpdatebottom = 0; /* reset refreshneeded indicator */
  336. pData->bNeedrefresh = MNG_FALSE;
  337. /* interval requested ? */
  338. if ((!pData->bFreezing) && (iInterval))
  339. { /* setup the timer */
  340. mng_retcode iRetcode = set_delay (pData, iInterval);
  341. if (iRetcode) /* on error bail out */
  342. return iRetcode;
  343. }
  344. }
  345. }
  346. return MNG_NOERROR;
  347. }
  348. /* ************************************************************************** */
  349. /* * * */
  350. /* * Generic display routines * */
  351. /* * * */
  352. /* ************************************************************************** */
  353. MNG_LOCAL mng_retcode interframe_delay (mng_datap pData)
  354. {
  355. mng_uint32 iWaitfor = 0;
  356. mng_uint32 iInterval;
  357. mng_uint32 iRuninterval;
  358. mng_retcode iRetcode;
  359. #ifdef MNG_SUPPORT_TRACE
  360. MNG_TRACE (pData, MNG_FN_INTERFRAME_DELAY, MNG_LC_START);
  361. #endif
  362. {
  363. #ifndef MNG_SKIPCHUNK_FRAM
  364. if (pData->iFramedelay > 0) /* real delay ? */
  365. { /* let the app refresh first ? */
  366. if ((pData->bRunning) && (!pData->bSkipping) &&
  367. (pData->iUpdatetop < pData->iUpdatebottom) && (pData->iUpdateleft < pData->iUpdateright))
  368. if (!pData->fRefresh (((mng_handle)pData),
  369. pData->iUpdateleft, pData->iUpdatetop,
  370. pData->iUpdateright - pData->iUpdateleft,
  371. pData->iUpdatebottom - pData->iUpdatetop))
  372. MNG_ERROR (pData, MNG_APPMISCERROR);
  373. pData->iUpdateleft = 0; /* reset update-region */
  374. pData->iUpdateright = 0;
  375. pData->iUpdatetop = 0;
  376. pData->iUpdatebottom = 0; /* reset refreshneeded indicator */
  377. pData->bNeedrefresh = MNG_FALSE;
  378. #ifndef MNG_SKIPCHUNK_TERM
  379. if (pData->bOnlyfirstframe) /* only processing first frame after TERM ? */
  380. {
  381. pData->iFramesafterTERM++;
  382. /* did we do a frame yet ? */
  383. if (pData->iFramesafterTERM > 1)
  384. { /* then that's it; just stop right here ! */
  385. pData->pCurraniobj = MNG_NULL;
  386. pData->bRunning = MNG_FALSE;
  387. return MNG_NOERROR;
  388. }
  389. }
  390. #endif
  391. if (pData->fGettickcount)
  392. { /* get current tickcount */
  393. pData->iRuntime = pData->fGettickcount ((mng_handle)pData);
  394. /* calculate interval since last sync-point */
  395. if (pData->iRuntime < pData->iSynctime)
  396. iRuninterval = pData->iRuntime + ~pData->iSynctime + 1;
  397. else
  398. iRuninterval = pData->iRuntime - pData->iSynctime;
  399. /* calculate actual run-time */
  400. if (pData->iRuntime < pData->iStarttime)
  401. pData->iRuntime = pData->iRuntime + ~pData->iStarttime + 1;
  402. else
  403. pData->iRuntime = pData->iRuntime - pData->iStarttime;
  404. }
  405. else
  406. {
  407. iRuninterval = 0;
  408. }
  409. iWaitfor = calculate_delay (pData, pData->iFramedelay);
  410. if (iWaitfor > iRuninterval) /* delay necessary ? */
  411. iInterval = iWaitfor - iRuninterval;
  412. else
  413. iInterval = 1; /* force app to process messageloop */
  414. /* set the timer ? */
  415. if (((pData->bRunning) || (pData->bSearching) || (pData->bReading)) &&
  416. (!pData->bSkipping))
  417. {
  418. iRetcode = set_delay (pData, iInterval);
  419. if (iRetcode) /* on error bail out */
  420. return iRetcode;
  421. }
  422. }
  423. if (!pData->bSkipping) /* increase frametime in advance */
  424. pData->iFrametime = pData->iFrametime + iWaitfor;
  425. /* setup for next delay */
  426. pData->iFramedelay = pData->iNextdelay;
  427. #endif
  428. }
  429. #ifdef MNG_SUPPORT_TRACE
  430. MNG_TRACE (pData, MNG_FN_INTERFRAME_DELAY, MNG_LC_END);
  431. #endif
  432. return MNG_NOERROR;
  433. }
  434. /* ************************************************************************** */
  435. MNG_LOCAL void set_display_routine (mng_datap pData)
  436. { /* actively running ? */
  437. if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
  438. {
  439. switch (pData->iCanvasstyle) /* determine display routine */
  440. {
  441. #ifndef MNG_SKIPCANVAS_RGB8
  442. case MNG_CANVAS_RGB8 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb8; break; }
  443. #endif
  444. #ifndef MNG_SKIPCANVAS_RGBA8
  445. case MNG_CANVAS_RGBA8 : { pData->fDisplayrow = (mng_fptr)mng_display_rgba8; break; }
  446. #endif
  447. #ifndef MNG_SKIPCANVAS_RGBA8_PM
  448. case MNG_CANVAS_RGBA8_PM: { pData->fDisplayrow = (mng_fptr)mng_display_rgba8_pm; break; }
  449. #endif
  450. #ifndef MNG_SKIPCANVAS_ARGB8
  451. case MNG_CANVAS_ARGB8 : { pData->fDisplayrow = (mng_fptr)mng_display_argb8; break; }
  452. #endif
  453. #ifndef MNG_SKIPCANVAS_ARGB8_PM
  454. case MNG_CANVAS_ARGB8_PM: { pData->fDisplayrow = (mng_fptr)mng_display_argb8_pm; break; }
  455. #endif
  456. #ifndef MNG_SKIPCANVAS_RGB8_A8
  457. case MNG_CANVAS_RGB8_A8 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb8_a8; break; }
  458. #endif
  459. #ifndef MNG_SKIPCANVAS_BGR8
  460. case MNG_CANVAS_BGR8 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr8; break; }
  461. #endif
  462. #ifndef MNG_SKIPCANVAS_BGRX8
  463. case MNG_CANVAS_BGRX8 : { pData->fDisplayrow = (mng_fptr)mng_display_bgrx8; break; }
  464. #endif
  465. #ifndef MNG_SKIPCANVAS_BGRA8
  466. case MNG_CANVAS_BGRA8 : { pData->fDisplayrow = (mng_fptr)mng_display_bgra8; break; }
  467. #endif
  468. #ifndef MNG_SKIPCANVAS_BGRA8_PM
  469. case MNG_CANVAS_BGRA8_PM: { pData->fDisplayrow = (mng_fptr)mng_display_bgra8_pm; break; }
  470. #endif
  471. #ifndef MNG_SKIPCANVAS_ABGR8
  472. case MNG_CANVAS_ABGR8 : { pData->fDisplayrow = (mng_fptr)mng_display_abgr8; break; }
  473. #endif
  474. #ifndef MNG_SKIPCANVAS_ABGR8_PM
  475. case MNG_CANVAS_ABGR8_PM: { pData->fDisplayrow = (mng_fptr)mng_display_abgr8_pm; break; }
  476. #endif
  477. #ifndef MNG_SKIPCANVAS_RGB565
  478. case MNG_CANVAS_RGB565 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb565; break; }
  479. #endif
  480. #ifndef MNG_SKIPCANVAS_RGBA565
  481. case MNG_CANVAS_RGBA565 : { pData->fDisplayrow = (mng_fptr)mng_display_rgba565; break; }
  482. #endif
  483. #ifndef MNG_SKIPCANVAS_BGR565
  484. case MNG_CANVAS_BGR565 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr565; break; }
  485. #endif
  486. #ifndef MNG_SKIPCANVAS_BGRA565
  487. case MNG_CANVAS_BGRA565 : { pData->fDisplayrow = (mng_fptr)mng_display_bgra565; break; }
  488. #endif
  489. #ifndef MNG_SKIPCANVAS_BGR565_A8
  490. case MNG_CANVAS_BGR565_A8 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr565_a8; break; }
  491. #endif
  492. #ifndef MNG_SKIPCANVAS_RGB555
  493. case MNG_CANVAS_RGB555 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb555; break; }
  494. #endif
  495. #ifndef MNG_SKIPCANVAS_BGR555
  496. case MNG_CANVAS_BGR555 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr555; break; }
  497. #endif
  498. #ifndef MNG_NO_16BIT_SUPPORT
  499. /* case MNG_CANVAS_RGB16 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb16; break; } */
  500. /* case MNG_CANVAS_RGBA16 : { pData->fDisplayrow = (mng_fptr)mng_display_rgba16; break; } */
  501. /* case MNG_CANVAS_ARGB16 : { pData->fDisplayrow = (mng_fptr)mng_display_argb16; break; } */
  502. /* case MNG_CANVAS_BGR16 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr16; break; } */
  503. /* case MNG_CANVAS_BGRA16 : { pData->fDisplayrow = (mng_fptr)mng_display_bgra16; break; } */
  504. /* case MNG_CANVAS_ABGR16 : { pData->fDisplayrow = (mng_fptr)mng_display_abgr16; break; } */
  505. #endif
  506. /* case MNG_CANVAS_INDEX8 : { pData->fDisplayrow = (mng_fptr)mng_display_index8; break; } */
  507. /* case MNG_CANVAS_INDEXA8 : { pData->fDisplayrow = (mng_fptr)mng_display_indexa8; break; } */
  508. /* case MNG_CANVAS_AINDEX8 : { pData->fDisplayrow = (mng_fptr)mng_display_aindex8; break; } */
  509. /* case MNG_CANVAS_GRAY8 : { pData->fDisplayrow = (mng_fptr)mng_display_gray8; break; } */
  510. /* case MNG_CANVAS_AGRAY8 : { pData->fDisplayrow = (mng_fptr)mng_display_agray8; break; } */
  511. /* case MNG_CANVAS_GRAYA8 : { pData->fDisplayrow = (mng_fptr)mng_display_graya8; break; } */
  512. #ifndef MNG_NO_16BIT_SUPPORT
  513. /* case MNG_CANVAS_GRAY16 : { pData->fDisplayrow = (mng_fptr)mng_display_gray16; break; } */
  514. /* case MNG_CANVAS_GRAYA16 : { pData->fDisplayrow = (mng_fptr)mng_display_graya16; break; } */
  515. /* case MNG_CANVAS_AGRAY16 : { pData->fDisplayrow = (mng_fptr)mng_display_agray16; break; } */
  516. #endif
  517. /* case MNG_CANVAS_DX15 : { pData->fDisplayrow = (mng_fptr)mng_display_dx15; break; } */
  518. /* case MNG_CANVAS_DX16 : { pData->fDisplayrow = (mng_fptr)mng_display_dx16; break; } */
  519. }
  520. }
  521. return;
  522. }
  523. /* ************************************************************************** */
  524. MNG_LOCAL mng_retcode load_bkgdlayer (mng_datap pData)
  525. {
  526. #ifdef MNG_SUPPORT_TRACE
  527. MNG_TRACE (pData, MNG_FN_LOAD_BKGDLAYER, MNG_LC_START);
  528. #endif
  529. /* actively running ? */
  530. if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
  531. {
  532. mng_int32 iY;
  533. mng_retcode iRetcode;
  534. mng_bool bColorcorr = MNG_FALSE;
  535. /* save values */
  536. mng_int32 iDestl = pData->iDestl;
  537. mng_int32 iDestr = pData->iDestr;
  538. mng_int32 iDestt = pData->iDestt;
  539. mng_int32 iDestb = pData->iDestb;
  540. mng_int32 iSourcel = pData->iSourcel;
  541. mng_int32 iSourcer = pData->iSourcer;
  542. mng_int32 iSourcet = pData->iSourcet;
  543. mng_int32 iSourceb = pData->iSourceb;
  544. mng_int8 iPass = pData->iPass;
  545. mng_int32 iRow = pData->iRow;
  546. mng_int32 iRowinc = pData->iRowinc;
  547. mng_int32 iCol = pData->iCol;
  548. mng_int32 iColinc = pData->iColinc;
  549. mng_int32 iRowsamples = pData->iRowsamples;
  550. mng_int32 iRowsize = pData->iRowsize;
  551. mng_uint8p pPrevrow = pData->pPrevrow;
  552. mng_uint8p pRGBArow = pData->pRGBArow;
  553. mng_bool bIsRGBA16 = pData->bIsRGBA16;
  554. mng_bool bIsOpaque = pData->bIsOpaque;
  555. mng_fptr fCorrectrow = pData->fCorrectrow;
  556. mng_fptr fDisplayrow = pData->fDisplayrow;
  557. mng_fptr fRetrieverow = pData->fRetrieverow;
  558. mng_objectp pCurrentobj = pData->pCurrentobj;
  559. mng_objectp pRetrieveobj = pData->pRetrieveobj;
  560. pData->iDestl = 0; /* determine clipping region */
  561. pData->iDestt = 0;
  562. pData->iDestr = pData->iWidth;
  563. pData->iDestb = pData->iHeight;
  564. #ifndef MNG_SKIPCHUNK_FRAM
  565. if (pData->bFrameclipping) /* frame clipping specified ? */
  566. {
  567. pData->iDestl = MAX_COORD (pData->iDestl, pData->iFrameclipl);
  568. pData->iDestt = MAX_COORD (pData->iDestt, pData->iFrameclipt);
  569. pData->iDestr = MIN_COORD (pData->iDestr, pData->iFrameclipr);
  570. pData->iDestb = MIN_COORD (pData->iDestb, pData->iFrameclipb);
  571. }
  572. #endif
  573. /* anything to clear ? */
  574. if ((pData->iDestr >= pData->iDestl) && (pData->iDestb >= pData->iDestt))
  575. {
  576. pData->iPass = -1; /* these are the object's dimensions now */
  577. pData->iRow = 0;
  578. pData->iRowinc = 1;
  579. pData->iCol = 0;
  580. pData->iColinc = 1;
  581. pData->iRowsamples = pData->iWidth;
  582. pData->iRowsize = pData->iRowsamples << 2;
  583. pData->bIsRGBA16 = MNG_FALSE; /* let's keep it simple ! */
  584. pData->bIsOpaque = MNG_TRUE;
  585. pData->iSourcel = 0; /* source relative to destination */
  586. pData->iSourcer = pData->iDestr - pData->iDestl;
  587. pData->iSourcet = 0;
  588. pData->iSourceb = pData->iDestb - pData->iDestt;
  589. set_display_routine (pData); /* determine display routine */
  590. /* default restore using preset BG color */
  591. pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgcolor;
  592. #ifndef MNG_SKIPCHUNK_bKGD
  593. if (((pData->eImagetype == mng_it_png) || (pData->eImagetype == mng_it_jng)) &&
  594. (pData->bUseBKGD))
  595. { /* prefer bKGD in PNG/JNG */
  596. if (!pData->pCurrentobj)
  597. pData->pCurrentobj = pData->pObjzero;
  598. if (((mng_imagep)pData->pCurrentobj)->pImgbuf->bHasBKGD)
  599. {
  600. pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bkgd;
  601. bColorcorr = MNG_TRUE;
  602. }
  603. }
  604. #endif
  605. if (pData->fGetbkgdline) /* background-canvas-access callback set ? */
  606. {
  607. switch (pData->iBkgdstyle)
  608. {
  609. #ifndef MNG_SKIPCANVAS_RGB8
  610. case MNG_CANVAS_RGB8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_rgb8; break; }
  611. #endif
  612. #ifndef MNG_SKIPCANVAS_BGR8
  613. case MNG_CANVAS_BGR8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgr8; break; }
  614. #endif
  615. #ifndef MNG_SKIPCANVAS_BGRX8
  616. case MNG_CANVAS_BGRX8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgrx8; break; }
  617. #endif
  618. #ifndef MNG_SKIPCANVAS_BGR565
  619. case MNG_CANVAS_BGR565 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgr565; break; }
  620. #endif
  621. #ifndef MNG_SKIPCANVAS_RGB565
  622. case MNG_CANVAS_RGB565 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_rgb565; break; }
  623. #endif
  624. #ifndef MNG_NO_16BIT_SUPPORT
  625. /* case MNG_CANVAS_RGB16 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_rgb16; break; } */
  626. /* case MNG_CANVAS_BGR16 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgr16; break; } */
  627. #endif
  628. /* case MNG_CANVAS_INDEX8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_index8; break; } */
  629. /* case MNG_CANVAS_GRAY8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_gray8; break; } */
  630. #ifndef MNG_NO_16BIT_SUPPORT
  631. /* case MNG_CANVAS_GRAY16 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_gray16; break; } */
  632. #endif
  633. /* case MNG_CANVAS_DX15 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_dx15; break; } */
  634. /* case MNG_CANVAS_DX16 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_dx16; break; } */
  635. }
  636. }
  637. #ifndef MNG_SKIPCHUNK_BACK
  638. if (pData->bHasBACK)
  639. { /* background image ? */
  640. if ((pData->iBACKmandatory & 0x02) && (pData->iBACKimageid))
  641. {
  642. pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_backcolor;
  643. bColorcorr = MNG_TRUE;
  644. }
  645. else /* background color ? */
  646. if (pData->iBACKmandatory & 0x01)
  647. {
  648. pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_backcolor;
  649. bColorcorr = MNG_TRUE;
  650. }
  651. }
  652. #endif
  653. pData->fCorrectrow = MNG_NULL; /* default no color-correction */
  654. if (bColorcorr) /* do we have to do color-correction ? */
  655. {
  656. #ifdef MNG_NO_CMS
  657. iRetcode = MNG_NOERROR;
  658. #else
  659. #if defined(MNG_FULL_CMS) /* determine color-management routine */
  660. iRetcode = mng_init_full_cms (pData, MNG_TRUE, MNG_FALSE, MNG_FALSE);
  661. #elif defined(MNG_GAMMA_ONLY)
  662. iRetcode = mng_init_gamma_only (pData, MNG_TRUE, MNG_FALSE, MNG_FALSE);
  663. #elif defined(MNG_APP_CMS)
  664. iRetcode = mng_init_app_cms (pData, MNG_TRUE, MNG_FALSE, MNG_FALSE);
  665. #endif
  666. if (iRetcode) /* on error bail out */
  667. return iRetcode;
  668. #endif /* MNG_NO_CMS */
  669. }
  670. /* get a temporary row-buffer */
  671. MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize);
  672. iY = pData->iDestt; /* this is where we start */
  673. iRetcode = MNG_NOERROR; /* so far, so good */
  674. while ((!iRetcode) && (iY < pData->iDestb))
  675. { /* restore a background row */
  676. iRetcode = ((mng_restbkgdrow)pData->fRestbkgdrow) (pData);
  677. /* color correction ? */
  678. if ((!iRetcode) && (pData->fCorrectrow))
  679. iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
  680. if (!iRetcode) /* so... display it */
  681. iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
  682. if (!iRetcode)
  683. iRetcode = mng_next_row (pData);
  684. iY++; /* and next line */
  685. }
  686. /* drop the temporary row-buffer */
  687. MNG_FREE (pData, pData->pRGBArow, pData->iRowsize);
  688. if (iRetcode) /* on error bail out */
  689. return iRetcode;
  690. #if defined(MNG_FULL_CMS) /* cleanup cms stuff */
  691. if (bColorcorr) /* did we do color-correction ? */
  692. {
  693. iRetcode = mng_clear_cms (pData);
  694. if (iRetcode) /* on error bail out */
  695. return iRetcode;
  696. }
  697. #endif
  698. #ifndef MNG_SKIPCHUNK_BACK
  699. /* background image ? */
  700. if ((pData->bHasBACK) && (pData->iBACKmandatory & 0x02) && (pData->iBACKimageid))
  701. {
  702. mng_imagep pImage;
  703. /* let's find that object then */
  704. pData->pRetrieveobj = mng_find_imageobject (pData, pData->iBACKimageid);
  705. pImage = (mng_imagep)pData->pRetrieveobj;
  706. /* exists, viewable and visible ? */
  707. if ((pImage) && (pImage->bViewable) && (pImage->bVisible))
  708. { /* will it fall within the target region ? */
  709. if ((pImage->iPosx < pData->iDestr) && (pImage->iPosy < pData->iDestb) &&
  710. ((pData->iBACKtile) ||
  711. ((pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth >= pData->iDestl) &&
  712. (pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight >= pData->iDestt) )) &&
  713. ((!pImage->bClipped) ||
  714. ((pImage->iClipl <= pImage->iClipr) && (pImage->iClipt <= pImage->iClipb) &&
  715. (pImage->iClipl < pData->iDestr) && (pImage->iClipr >= pData->iDestl) &&
  716. (pImage->iClipt < pData->iDestb) && (pImage->iClipb >= pData->iDestt) )))
  717. { /* right; we've got ourselves something to do */
  718. if (pImage->bClipped) /* clip output region with image's clipping region ? */
  719. {
  720. if (pImage->iClipl > pData->iDestl)
  721. pData->iDestl = pImage->iClipl;
  722. if (pImage->iClipr < pData->iDestr)
  723. pData->iDestr = pImage->iClipr;
  724. if (pImage->iClipt > pData->iDestt)
  725. pData->iDestt = pImage->iClipt;
  726. if (pImage->iClipb < pData->iDestb)
  727. pData->iDestb = pImage->iClipb;
  728. }
  729. /* image offset does some extra clipping too ! */
  730. if (pImage->iPosx > pData->iDestl)
  731. pData->iDestl = pImage->iPosx;
  732. if (pImage->iPosy > pData->iDestt)
  733. pData->iDestt = pImage->iPosy;
  734. if (!pData->iBACKtile) /* without tiling further clipping is needed */
  735. {
  736. if (pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth < pData->iDestr)
  737. pData->iDestr = pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth;
  738. if (pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight < pData->iDestb)
  739. pData->iDestb = pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight;
  740. }
  741. pData->iSourcel = 0; /* source relative to destination */
  742. pData->iSourcer = pData->iDestr - pData->iDestl;
  743. pData->iSourcet = 0;
  744. pData->iSourceb = pData->iDestb - pData->iDestt;
  745. /* 16-bit background ? */
  746. #ifdef MNG_NO_16BIT_SUPPORT
  747. pData->bIsRGBA16 = MNG_FALSE;
  748. #else
  749. pData->bIsRGBA16 = (mng_bool)(pImage->pImgbuf->iBitdepth > 8);
  750. #endif
  751. /* let restore routine know the offsets !!! */
  752. pData->iBackimgoffsx = pImage->iPosx;
  753. pData->iBackimgoffsy = pImage->iPosy;
  754. pData->iBackimgwidth = pImage->pImgbuf->iWidth;
  755. pData->iBackimgheight = pImage->pImgbuf->iHeight;
  756. pData->iRow = 0; /* start at the top again !! */
  757. /* determine background object retrieval routine */
  758. switch (pImage->pImgbuf->iColortype)
  759. {
  760. case 0 : {
  761. #ifndef MNG_NO_16BIT_SUPPORT
  762. if (pImage->pImgbuf->iBitdepth > 8)
  763. pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
  764. else
  765. #endif
  766. pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
  767. pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
  768. break;
  769. }
  770. case 2 : {
  771. #ifndef MNG_NO_16BIT_SUPPORT
  772. if (pImage->pImgbuf->iBitdepth > 8)
  773. pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb16;
  774. else
  775. #endif
  776. pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
  777. pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
  778. break;
  779. }
  780. case 3 : { pData->fRetrieverow = (mng_fptr)mng_retrieve_idx8;
  781. pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
  782. break;
  783. }
  784. case 4 : {
  785. #ifndef MNG_NO_16BIT_SUPPORT
  786. if (pImage->pImgbuf->iBitdepth > 8)
  787. pData->fRetrieverow = (mng_fptr)mng_retrieve_ga16;
  788. else
  789. #endif
  790. pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
  791. pData->bIsOpaque = MNG_FALSE;
  792. break;
  793. }
  794. case 6 : {
  795. #ifndef MNG_NO_16BIT_SUPPORT
  796. if (pImage->pImgbuf->iBitdepth > 8)
  797. pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
  798. else
  799. #endif
  800. pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
  801. pData->bIsOpaque = MNG_FALSE;
  802. break;
  803. }
  804. case 8 : {
  805. #ifndef MNG_NO_16BIT_SUPPORT
  806. if (pImage->pImgbuf->iBitdepth > 8)
  807. pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
  808. else
  809. #endif
  810. pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
  811. pData->bIsOpaque = MNG_TRUE;
  812. break;
  813. }
  814. case 10 : {
  815. #ifndef MNG_NO_16BIT_SUPPORT
  816. if (pImage->pImgbuf->iBitdepth > 8)
  817. pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb16;
  818. else
  819. #endif
  820. pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
  821. pData->bIsOpaque = MNG_TRUE;
  822. break;
  823. }
  824. case 12 : {
  825. #ifndef MNG_NO_16BIT_SUPPORT
  826. if (pImage->pImgbuf->iBitdepth > 8)
  827. pData->fRetrieverow = (mng_fptr)mng_retrieve_ga16;
  828. else
  829. #endif
  830. pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
  831. pData->bIsOpaque = MNG_FALSE;
  832. break;
  833. }
  834. case 14 : {
  835. #ifndef MNG_NO_16BIT_SUPPORT
  836. if (pImage->pImgbuf->iBitdepth > 8)
  837. pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
  838. else
  839. #endif
  840. pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
  841. pData->bIsOpaque = MNG_FALSE;
  842. break;
  843. }
  844. }
  845. #ifdef MNG_NO_CMS
  846. iRetcode = MNG_NOERROR;
  847. #else
  848. #if defined(MNG_FULL_CMS) /* determine color-management routine */
  849. iRetcode = mng_init_full_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
  850. #elif defined(MNG_GAMMA_ONLY)
  851. iRetcode = mng_init_gamma_only (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
  852. #elif defined(MNG_APP_CMS)
  853. iRetcode = mng_init_app_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
  854. #endif
  855. if (iRetcode) /* on error bail out */
  856. return iRetcode;
  857. #endif /* MNG_NO_CMS */
  858. /* get temporary row-buffers */
  859. MNG_ALLOC (pData, pData->pPrevrow, pData->iRowsize);
  860. MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize);
  861. iY = pData->iDestt; /* this is where we start */
  862. iRetcode = MNG_NOERROR; /* so far, so good */
  863. while ((!iRetcode) && (iY < pData->iDestb))
  864. { /* restore a background row */
  865. iRetcode = mng_restore_bkgd_backimage (pData);
  866. /* color correction ? */
  867. if ((!iRetcode) && (pData->fCorrectrow))
  868. iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
  869. if (!iRetcode) /* so... display it */
  870. iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
  871. if (!iRetcode)
  872. iRetcode = mng_next_row (pData);
  873. iY++; /* and next line */
  874. }
  875. /* drop temporary row-buffers */
  876. MNG_FREE (pData, pData->pRGBArow, pData->iRowsize);
  877. MNG_FREE (pData, pData->pPrevrow, pData->iRowsize);
  878. if (iRetcode) /* on error bail out */
  879. return iRetcode;
  880. #if defined(MNG_FULL_CMS) /* cleanup cms stuff */
  881. iRetcode = mng_clear_cms (pData);
  882. if (iRetcode) /* on error bail out */
  883. return iRetcode;
  884. #endif
  885. }
  886. }
  887. }
  888. #endif
  889. }
  890. pData->iDestl = iDestl; /* restore values */
  891. pData->iDestr = iDestr;
  892. pData->iDestt = iDestt;
  893. pData->iDestb = iDestb;
  894. pData->iSourcel = iSourcel;
  895. pData->iSourcer = iSourcer;
  896. pData->iSourcet = iSourcet;
  897. pData->iSourceb = iSourceb;
  898. pData->iPass = iPass;
  899. pData->iRow = iRow;
  900. pData->iRowinc = iRowinc;
  901. pData->iCol = iCol;
  902. pData->iColinc = iColinc;
  903. pData->iRowsamples = iRowsamples;
  904. pData->iRowsize = iRowsize;
  905. pData->pPrevrow = pPrevrow;
  906. pData->pRGBArow = pRGBArow;
  907. pData->bIsRGBA16 = bIsRGBA16;
  908. pData->bIsOpaque = bIsOpaque;
  909. pData->fCorrectrow = fCorrectrow;
  910. pData->fDisplayrow = fDisplayrow;
  911. pData->fRetrieverow = fRetrieverow;
  912. pData->pCurrentobj = pCurrentobj;
  913. pData->pRetrieveobj = pRetrieveobj;
  914. }
  915. #ifdef MNG_SUPPORT_TRACE
  916. MNG_TRACE (pData, MNG_FN_LOAD_BKGDLAYER, MNG_LC_END);
  917. #endif
  918. return MNG_NOERROR;
  919. }
  920. /* ************************************************************************** */
  921. MNG_LOCAL mng_retcode clear_canvas (mng_datap pData)
  922. {
  923. mng_int32 iY;
  924. mng_retcode iRetcode;
  925. #ifdef MNG_SUPPORT_TRACE
  926. MNG_TRACE (pData, MNG_FN_CLEAR_CANVAS, MNG_LC_START);
  927. #endif
  928. pData->iDestl = 0; /* clipping region is full canvas! */
  929. pData->iDestt = 0;
  930. pData->iDestr = pData->iWidth;
  931. pData->iDestb = pData->iHeight;
  932. pData->iSourcel = 0; /* source is same as destination */
  933. pData->iSourcer = pData->iWidth;
  934. pData->iSourcet = 0;
  935. pData->iSourceb = pData->iHeight;
  936. pData->iPass = -1; /* these are the object's dimensions now */
  937. pData->iRow = 0;
  938. pData->iRowinc = 1;
  939. pData->iCol = 0;
  940. pData->iColinc = 1;
  941. pData->iRowsamples = pData->iWidth;
  942. pData->iRowsize = pData->iRowsamples << 2;
  943. pData->bIsRGBA16 = MNG_FALSE; /* let's keep it simple ! */
  944. pData->bIsOpaque = MNG_TRUE;
  945. set_display_routine (pData); /* determine display routine */
  946. /* get a temporary row-buffer */
  947. /* it's transparent black by default!! */
  948. MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize);
  949. iY = pData->iDestt; /* this is where we start */
  950. iRetcode = MNG_NOERROR; /* so far, so good */
  951. while ((!iRetcode) && (iY < pData->iDestb))
  952. { /* clear a row then */
  953. iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
  954. if (!iRetcode)
  955. iRetcode = mng_next_row (pData); /* adjust variables for next row */
  956. iY++; /* and next line */
  957. }
  958. /* drop the temporary row-buffer */
  959. MNG_FREE (pData, pData->pRGBArow, pData->iRowsize);
  960. if (iRetcode) /* on error bail out */
  961. return iRetcode;
  962. #ifdef MNG_SUPPORT_TRACE
  963. MNG_TRACE (pData, MNG_FN_CLEAR_CANVAS, MNG_LC_END);
  964. #endif
  965. return MNG_NOERROR;
  966. }
  967. /* ************************************************************************** */
  968. MNG_LOCAL mng_retcode next_frame (mng_datap pData,
  969. mng_uint8 iFramemode,
  970. mng_uint8 iChangedelay,
  971. mng_uint32 iDelay,
  972. mng_uint8 iChangetimeout,
  973. mng_uint32 iTimeout,
  974. mng_uint8 iChangeclipping,
  975. mng_uint8 iCliptype,
  976. mng_int32 iClipl,
  977. mng_int32 iClipr,
  978. mng_int32 iClipt,
  979. mng_int32 iClipb)
  980. {
  981. mng_retcode iRetcode = MNG_NOERROR;
  982. #ifdef MNG_SUPPORT_TRACE
  983. MNG_TRACE (pData, MNG_FN_NEXT_FRAME, MNG_LC_START);
  984. #endif
  985. if (!pData->iBreakpoint) /* no previous break here ? */
  986. {
  987. #ifndef MNG_SKIPCHUNK_FRAM
  988. mng_uint8 iOldmode = pData->iFramemode;
  989. /* interframe delay required ? */
  990. if ((iOldmode == 2) || (iOldmode == 4))
  991. {
  992. if ((pData->iFrameseq) && (iFramemode != 1) && (iFramemode != 3))
  993. iRetcode = interframe_delay (pData);
  994. else
  995. pData->iFramedelay = pData->iNextdelay;
  996. }
  997. else
  998. { /* delay before inserting background layer? */
  999. if ((pData->bFramedone) && (iFramemode == 4))
  1000. iRetcode = interframe_delay (pData);
  1001. }
  1002. if (iRetcode) /* on error bail out */
  1003. return iRetcode;
  1004. /* now we'll assume we're in the next frame! */
  1005. if (iFramemode) /* save the new framing mode ? */
  1006. {
  1007. pData->iFRAMmode = iFramemode;
  1008. pData->iFramemode = iFramemode;
  1009. }
  1010. else /* reload default */
  1011. pData->iFramemode = pData->iFRAMmode;
  1012. if (iChangedelay) /* delay changed ? */
  1013. {
  1014. pData->iNextdelay = iDelay; /* for *after* next subframe */
  1015. if ((iOldmode == 2) || (iOldmode == 4))
  1016. pData->iFramedelay = pData->iFRAMdelay;
  1017. if (iChangedelay == 2) /* also overall ? */
  1018. pData->iFRAMdelay = iDelay;
  1019. }
  1020. else
  1021. { /* reload default */
  1022. pData->iNextdelay = pData->iFRAMdelay;
  1023. }
  1024. if (iChangetimeout) /* timeout changed ? */
  1025. { /* for next subframe */
  1026. pData->iFrametimeout = iTimeout;
  1027. if ((iChangetimeout == 2) || /* also overall ? */
  1028. (iChangetimeout == 4) ||
  1029. (iChangetimeout == 6) ||
  1030. (iChangetimeout == 8))
  1031. pData->iFRAMtimeout = iTimeout;
  1032. }
  1033. else /* reload default */
  1034. pData->iFrametimeout = pData->iFRAMtimeout;
  1035. if (iChangeclipping) /* clipping changed ? */
  1036. {
  1037. pData->bFrameclipping = MNG_TRUE;
  1038. if (!iCliptype) /* absolute ? */
  1039. {
  1040. pData->iFrameclipl = iClipl;
  1041. pData->iFrameclipr = iClipr;
  1042. pData->iFrameclipt = iClipt;
  1043. pData->iFrameclipb = iClipb;
  1044. }
  1045. else /* relative */
  1046. {
  1047. pData->iFrameclipl = pData->iFrameclipl + iClipl;
  1048. pData->iFrameclipr = pData->iFrameclipr + iClipr;
  1049. pData->iFrameclipt = pData->iFrameclipt + iClipt;
  1050. pData->iFrameclipb = pData->iFrameclipb + iClipb;
  1051. }
  1052. if (iChangeclipping == 2) /* also overall ? */
  1053. {
  1054. pData->bFRAMclipping = MNG_TRUE;
  1055. if (!iCliptype) /* absolute ? */
  1056. {
  1057. pData->iFRAMclipl = iClipl;
  1058. pData->iFRAMclipr = iClipr;
  1059. pData->iFRAMclipt = iClipt;
  1060. pData->iFRAMclipb = iClipb;
  1061. }
  1062. else /* relative */
  1063. {
  1064. pData->iFRAMclipl = pData->iFRAMclipl + iClipl;
  1065. pData->iFRAMclipr = pData->iFRAMclipr + iClipr;
  1066. pData->iFRAMclipt = pData->iFRAMclipt + iClipt;
  1067. pData->iFRAMclipb = pData->iFRAMclipb + iClipb;
  1068. }
  1069. }
  1070. }
  1071. else
  1072. { /* reload defaults */
  1073. pData->bFrameclipping = pData->bFRAMclipping;
  1074. pData->iFrameclipl = pData->iFRAMclipl;
  1075. pData->iFrameclipr = pData->iFRAMclipr;
  1076. pData->iFrameclipt = pData->iFRAMclipt;
  1077. pData->iFrameclipb = pData->iFRAMclipb;
  1078. }
  1079. #endif
  1080. }
  1081. if (!pData->bTimerset) /* timer still off ? */
  1082. {
  1083. if (
  1084. #ifndef MNG_SKIPCHUNK_FRAM
  1085. (pData->iFramemode == 4) || /* insert background layer after a new frame */
  1086. #endif
  1087. (!pData->iLayerseq)) /* and certainly before the very first layer */
  1088. iRetcode = load_bkgdlayer (pData);
  1089. if (iRetcode) /* on error bail out */
  1090. return iRetcode;
  1091. pData->iFrameseq++; /* count the frame ! */
  1092. pData->bFramedone = MNG_TRUE; /* and indicate we've done one */
  1093. }
  1094. #ifdef MNG_SUPPORT_TRACE
  1095. MNG_TRACE (pData, MNG_FN_NEXT_FRAME, MNG_LC_END);
  1096. #endif
  1097. return MNG_NOERROR;
  1098. }
  1099. /* ************************************************************************** */
  1100. MNG_LOCAL mng_retcode next_layer (mng_datap pData)
  1101. {
  1102. mng_imagep pImage;
  1103. mng_retcode iRetcode = MNG_NOERROR;
  1104. #ifdef MNG_SUPPORT_TRACE
  1105. MNG_TRACE (pData, MNG_FN_NEXT_LAYER, MNG_LC_START);
  1106. #endif
  1107. #ifndef MNG_SKIPCHUNK_FRAM
  1108. if (!pData->iBreakpoint) /* no previous break here ? */
  1109. { /* interframe delay required ? */
  1110. if ((pData->eImagetype == mng_it_mng) && (pData->iLayerseq) &&
  1111. ((pData->iFramemode == 1) || (pData->iFramemode == 3)))
  1112. iRetcode = interframe_delay (pData);
  1113. else
  1114. pData->iFramedelay = pData->iNextdelay;
  1115. if (iRetcode) /* on error bail out */
  1116. return iRetcode;
  1117. }
  1118. #endif
  1119. if (!pData->bTimerset) /* timer still off ? */
  1120. {
  1121. if (!pData->iLayerseq) /* restore background for the very first layer ? */
  1122. { /* wait till IDAT/JDAT for PNGs & JNGs !!! */
  1123. if ((pData->eImagetype == mng_it_png) || (pData->eImagetype == mng_it_jng))
  1124. pData->bRestorebkgd = MNG_TRUE;
  1125. else
  1126. { /* for MNG we do it right away */
  1127. iRetcode = load_bkgdlayer (pData);
  1128. pData->iLayerseq++; /* and it counts as a layer then ! */
  1129. }
  1130. }
  1131. #ifndef MNG_SKIPCHUNK_FRAM
  1132. else
  1133. if (pData->iFramemode == 3) /* restore background for each layer ? */
  1134. iRetcode = load_bkgdlayer (pData);
  1135. #endif
  1136. if (iRetcode) /* on error bail out */
  1137. return iRetcode;
  1138. #ifndef MNG_NO_DELTA_PNG
  1139. if (pData->bHasDHDR) /* processing a delta-image ? */
  1140. pImage = (mng_imagep)pData->pDeltaImage;
  1141. else
  1142. #endif
  1143. pImage = (mng_imagep)pData->pCurrentobj;
  1144. if (!pImage) /* not an active object ? */
  1145. pImage = (mng_imagep)pData->pObjzero;
  1146. /* determine display rectangle */
  1147. pData->iDestl = MAX_COORD ((mng_int32)0, pImage->iPosx);
  1148. pData->iDestt = MAX_COORD ((mng_int32)0, pImage->iPosy);
  1149. /* is it a valid buffer ? */
  1150. if ((pImage->pImgbuf->iWidth) && (pImage->pImgbuf->iHeight))
  1151. {
  1152. pData->iDestr = MIN_COORD ((mng_int32)pData->iWidth,
  1153. pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth );
  1154. pData->iDestb = MIN_COORD ((mng_int32)pData->iHeight,
  1155. pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight);
  1156. }
  1157. else /* it's a single image ! */
  1158. {
  1159. pData->iDestr = MIN_COORD ((mng_int32)pData->iWidth,
  1160. (mng_int32)pData->iDatawidth );
  1161. pData->iDestb = MIN_COORD ((mng_int32)pData->iHeight,
  1162. (mng_int32)pData->iDataheight);
  1163. }
  1164. #ifndef MNG_SKIPCHUNK_FRAM
  1165. if (pData->bFrameclipping) /* frame clipping specified ? */
  1166. {
  1167. pData->iDestl = MAX_COORD (pData->iDestl, pData->iFrameclipl);
  1168. pData->iDestt = MAX_COORD (pData->iDestt, pData->iFrameclipt);
  1169. pData->iDestr = MIN_COORD (pData->iDestr, pData->iFrameclipr);
  1170. pData->iDestb = MIN_COORD (pData->iDestb, pData->iFrameclipb);
  1171. }
  1172. #endif
  1173. if (pImage->bClipped) /* is the image clipped itself ? */
  1174. {
  1175. pData->iDestl = MAX_COORD (pData->iDestl, pImage->iClipl);
  1176. pData->iDestt = MAX_COORD (pData->iDestt, pImage->iClipt);
  1177. pData->iDestr = MIN_COORD (pData->iDestr, pImage->iClipr);
  1178. pData->iDestb = MIN_COORD (pData->iDestb, pImage->iClipb);
  1179. }
  1180. /* determine source starting point */
  1181. pData->iSourcel = MAX_COORD ((mng_int32)0, pData->iDestl - pImage->iPosx);
  1182. pData->iSourcet = MAX_COORD ((mng_int32)0, pData->iDestt - pImage->iPosy);
  1183. if ((pImage->pImgbuf->iWidth) && (pImage->pImgbuf->iHeight))
  1184. { /* and maximum size */
  1185. pData->iSourcer = MIN_COORD ((mng_int32)pImage->pImgbuf->iWidth,
  1186. pData->iSourcel + pData->iDestr - pData->iDestl);
  1187. pData->iSourceb = MIN_COORD ((mng_int32)pImage->pImgbuf->iHeight,
  1188. pData->iSourcet + pData->iDestb - pData->iDestt);
  1189. }
  1190. else /* it's a single image ! */
  1191. {
  1192. pData->iSourcer = pData->iSourcel + pData->iDestr - pData->iDestl;
  1193. pData->iSourceb = pData->iSourcet + pData->iDestb - pData->iDestt;
  1194. }
  1195. pData->iLayerseq++; /* count the layer ! */
  1196. }
  1197. #ifdef MNG_SUPPORT_TRACE
  1198. MNG_TRACE (pData, MNG_FN_NEXT_LAYER, MNG_LC_END);
  1199. #endif
  1200. return MNG_NOERROR;
  1201. }
  1202. /* ************************************************************************** */
  1203. mng_retcode mng_display_image (mng_datap pData,
  1204. mng_imagep pImage,
  1205. mng_bool bLayeradvanced)
  1206. {
  1207. mng_retcode iRetcode;
  1208. #ifdef MNG_SUPPORT_TRACE
  1209. MNG_TRACE (pData, MNG_FN_DISPLAY_IMAGE, MNG_LC_START);
  1210. #endif
  1211. /* actively running ? */
  1212. #ifndef MNG_SKIPCHUNK_MAGN
  1213. if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
  1214. {
  1215. if ( (!pData->iBreakpoint) && /* needs magnification ? */
  1216. ( (pImage->iMAGN_MethodX) || (pImage->iMAGN_MethodY) ) )
  1217. {
  1218. iRetcode = mng_magnify_imageobject (pData, pImage);
  1219. if (iRetcode) /* on error bail out */
  1220. return iRetcode;
  1221. }
  1222. }
  1223. #endif
  1224. pData->pRetrieveobj = pImage; /* so retrieve-row and color-correction can find it */
  1225. if (!bLayeradvanced) /* need to advance the layer ? */
  1226. {
  1227. mng_imagep pSave = pData->pCurrentobj;
  1228. pData->pCurrentobj = pImage;
  1229. next_layer (pData); /* advance to next layer */
  1230. pData->pCurrentobj = pSave;
  1231. }
  1232. /* need to restore the background ? */
  1233. if ((!pData->bTimerset) && (pData->bRestorebkgd))
  1234. {
  1235. mng_imagep pSave = pData->pCurrentobj;
  1236. pData->pCurrentobj = pImage;
  1237. pData->bRestorebkgd = MNG_FALSE;
  1238. iRetcode = load_bkgdlayer (pData);
  1239. pData->pCurrentobj = pSave;
  1240. if (iRetcode) /* on error bail out */
  1241. return iRetcode;
  1242. pData->iLayerseq++; /* and it counts as a layer then ! */
  1243. }
  1244. /* actively running ? */
  1245. if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
  1246. {
  1247. if (!pData->bTimerset) /* all systems still go ? */
  1248. {
  1249. pData->iBreakpoint = 0; /* let's make absolutely sure... */
  1250. /* anything to display ? */
  1251. if ((pData->iDestr >= pData->iDestl) && (pData->iDestb >= pData->iDestt))
  1252. {
  1253. mng_int32 iY;
  1254. set_display_routine (pData); /* determine display routine */
  1255. /* and image-buffer retrieval routine */
  1256. switch (pImage->pImgbuf->iColortype)
  1257. {
  1258. case 0 : {
  1259. #ifndef MNG_NO_16BIT_SUPPORT
  1260. if (pImage->pImgbuf->iBitdepth > 8)
  1261. pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
  1262. else
  1263. #endif
  1264. pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
  1265. pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
  1266. break;
  1267. }
  1268. case 2 : {
  1269. #ifndef MNG_NO_16BIT_SUPPORT
  1270. if (pImage->pImgbuf->iBitdepth > 8)