diff options
Diffstat (limited to 'src/3rdparty/libmng/libmng_display.c')
-rw-r--r-- | src/3rdparty/libmng/libmng_display.c | 4699 |
1 files changed, 4699 insertions, 0 deletions
diff --git a/src/3rdparty/libmng/libmng_display.c b/src/3rdparty/libmng/libmng_display.c new file mode 100644 index 0000000..d2e460c --- /dev/null +++ b/src/3rdparty/libmng/libmng_display.c @@ -0,0 +1,4699 @@ +/* ************************************************************************** */ +/* * For conditions of distribution and use, * */ +/* * see copyright notice in libmng.h * */ +/* ************************************************************************** */ +/* * * */ +/* * project : libmng * */ +/* * file : libmng_display.c copyright (c) 2000 G.Juyn * */ +/* * version : 1.0.2 * */ +/* * * */ +/* * purpose : Display management (implementation) * */ +/* * * */ +/* * author : G.Juyn * */ +/* * web : http://www.3-t.com * */ +/* * email : mailto:[email protected] * */ +/* * * */ +/* * comment : implementation of the display management routines * */ +/* * * */ +/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */ +/* * - changed strict-ANSI stuff * */ +/* * 0.5.1 - 05/11/2000 - G.Juyn * */ +/* * - added callback error-reporting support * */ +/* * - fixed frame_delay misalignment * */ +/* * 0.5.1 - 05/12/2000 - G.Juyn * */ +/* * - added sanity check for frozen status * */ +/* * - changed trace to macro for callback error-reporting * */ +/* * 0.5.1 - 05/13/2000 - G.Juyn * */ +/* * - changed display_mend to reset state to initial or SAVE * */ +/* * - added eMNGma hack (will be removed in 1.0.0 !!!) * */ +/* * - added TERM animation object pointer (easier reference) * */ +/* * - added process_save & process_seek routines * */ +/* * 0.5.1 - 05/14/2000 - G.Juyn * */ +/* * - added save_state and restore_state for SAVE/SEEK/TERM * */ +/* * processing * */ +/* * * */ +/* * 0.5.2 - 05/20/2000 - G.Juyn * */ +/* * - added JNG support (JHDR/JDAT) * */ +/* * 0.5.2 - 05/23/2000 - G.Juyn * */ +/* * - fixed problem with DEFI clipping * */ +/* * 0.5.2 - 05/30/2000 - G.Juyn * */ +/* * - added delta-image support (DHDR,PROM,IPNG,IJNG) * */ +/* * 0.5.2 - 05/31/2000 - G.Juyn * */ +/* * - fixed pointer confusion (contributed by Tim Rowley) * */ +/* * 0.5.2 - 06/03/2000 - G.Juyn * */ +/* * - fixed makeup for Linux gcc compile * */ +/* * 0.5.2 - 06/05/2000 - G.Juyn * */ +/* * - added support for RGB8_A8 canvasstyle * */ +/* * 0.5.2 - 06/09/2000 - G.Juyn * */ +/* * - fixed timer-handling to run with Mozilla (Tim Rowley) * */ +/* * 0.5.2 - 06/10/2000 - G.Juyn * */ +/* * - fixed some compilation-warnings (contrib Jason Morris) * */ +/* * * */ +/* * 0.5.3 - 06/12/2000 - G.Juyn * */ +/* * - fixed display of stored JNG images * */ +/* * 0.5.3 - 06/13/2000 - G.Juyn * */ +/* * - fixed problem with BASI-IEND as object 0 * */ +/* * 0.5.3 - 06/16/2000 - G.Juyn * */ +/* * - changed progressive-display processing * */ +/* * 0.5.3 - 06/17/2000 - G.Juyn * */ +/* * - changed delta-image processing * */ +/* * 0.5.3 - 06/20/2000 - G.Juyn * */ +/* * - fixed some minor stuff * */ +/* * 0.5.3 - 06/21/2000 - G.Juyn * */ +/* * - added speed-modifier to timing routine * */ +/* * 0.5.3 - 06/22/2000 - G.Juyn * */ +/* * - added support for PPLT chunk processing * */ +/* * 0.5.3 - 06/29/2000 - G.Juyn * */ +/* * - swapped refresh parameters * */ +/* * * */ +/* * 0.9.0 - 06/30/2000 - G.Juyn * */ +/* * - changed refresh parameters to 'x,y,width,height' * */ +/* * * */ +/* * 0.9.1 - 07/07/2000 - G.Juyn * */ +/* * - implemented support for freeze/reset/resume & go_xxxx * */ +/* * 0.9.1 - 07/08/2000 - G.Juyn * */ +/* * - added support for improved timing * */ +/* * 0.9.1 - 07/14/2000 - G.Juyn * */ +/* * - changed EOF processing behavior * */ +/* * - fixed TERM delay processing * */ +/* * 0.9.1 - 07/15/2000 - G.Juyn * */ +/* * - fixed freeze & reset processing * */ +/* * 0.9.1 - 07/16/2000 - G.Juyn * */ +/* * - fixed storage of images during mng_read() * */ +/* * - fixed support for mng_display() after mng_read() * */ +/* * 0.9.1 - 07/24/2000 - G.Juyn * */ +/* * - fixed reading of still-images * */ +/* * * */ +/* * 0.9.2 - 08/05/2000 - G.Juyn * */ +/* * - changed file-prefixes * */ +/* * * */ +/* * 0.9.3 - 08/07/2000 - G.Juyn * */ +/* * - B111300 - fixup for improved portability * */ +/* * 0.9.3 - 08/21/2000 - G.Juyn * */ +/* * - fixed TERM processing delay of 0 msecs * */ +/* * 0.9.3 - 08/26/2000 - G.Juyn * */ +/* * - added MAGN chunk * */ +/* * 0.9.3 - 09/10/2000 - G.Juyn * */ +/* * - fixed problem with no refresh after TERM * */ +/* * - fixed DEFI behavior * */ +/* * 0.9.3 - 09/16/2000 - G.Juyn * */ +/* * - fixed timing & refresh behavior for single PNG/JNG * */ +/* * 0.9.3 - 09/19/2000 - G.Juyn * */ +/* * - refixed timing & refresh behavior for single PNG/JNG * */ +/* * 0.9.3 - 10/02/2000 - G.Juyn * */ +/* * - fixed timing again (this is getting boring...) * */ +/* * - refixed problem with no refresh after TERM * */ +/* * 0.9.3 - 10/16/2000 - G.Juyn * */ +/* * - added JDAA chunk * */ +/* * 0.9.3 - 10/17/2000 - G.Juyn * */ +/* * - fixed support for bKGD * */ +/* * 0.9.3 - 10/18/2000 - G.Juyn * */ +/* * - fixed delta-processing behavior * */ +/* * 0.9.3 - 10/19/2000 - G.Juyn * */ +/* * - added storage for pixel-/alpha-sampledepth for delta's * */ +/* * 0.9.3 - 10/27/2000 - G.Juyn * */ +/* * - fixed seperate read() & display() processing * */ +/* * * */ +/* * 0.9.4 - 10/31/2000 - G.Juyn * */ +/* * - fixed possible loop in display_resume() (Thanks Vova!) * */ +/* * 0.9.4 - 11/20/2000 - G.Juyn * */ +/* * - fixed unwanted repetition in mng_readdisplay() * */ +/* * 0.9.4 - 11/24/2000 - G.Juyn * */ +/* * - moved restore of object 0 to libmng_display * */ +/* * - added restore of object 0 to TERM processing !!! * */ +/* * - fixed TERM delay processing * */ +/* * - fixed TERM end processing (count = 0) * */ +/* * 0.9.4 - 12/16/2000 - G.Juyn * */ +/* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */ +/* * 0.9.4 - 1/18/2001 - G.Juyn * */ +/* * - removed test filter-methods 1 & 65 * */ +/* * - set default level-set for filtertype=64 to all zeroes * */ +/* * * */ +/* * 0.9.5 - 1/20/2001 - G.Juyn * */ +/* * - fixed compiler-warnings Mozilla (thanks Tim) * */ +/* * 0.9.5 - 1/23/2001 - G.Juyn * */ +/* * - fixed timing-problem with switching framing_modes * */ +/* * * */ +/* * 1.0.1 - 02/08/2001 - G.Juyn * */ +/* * - added MEND processing callback * */ +/* * 1.0.1 - 02/13/2001 - G.Juyn * */ +/* * - fixed first FRAM_MODE=4 timing problem * */ +/* * 1.0.1 - 04/21/2001 - G.Juyn * */ +/* * - fixed memory-leak for JNGs with alpha (Thanks Gregg!) * */ +/* * - added BGRA8 canvas with premultiplied alpha * */ +/* * * */ +/* * 1.0.2 - 06/25/2001 - G.Juyn * */ +/* * - fixed memory-leak with delta-images (Thanks Michael!) * */ +/* * * */ +/* ************************************************************************** */ + +#include "libmng.h" +#include "libmng_data.h" +#include "libmng_error.h" +#include "libmng_trace.h" +#ifdef __BORLANDC__ +#pragma hdrstop +#endif +#include "libmng_objects.h" +#include "libmng_object_prc.h" +#include "libmng_memory.h" +#include "libmng_zlib.h" +#include "libmng_jpeg.h" +#include "libmng_cms.h" +#include "libmng_pixels.h" +#include "libmng_display.h" + +#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI) +#pragma option -A /* force ANSI-C */ +#endif + +/* ************************************************************************** */ + +#ifdef MNG_INCLUDE_DISPLAY_PROCS + +/* ************************************************************************** */ + +mng_retcode set_delay (mng_datap pData, + mng_uint32 iInterval) +{ + if (!iInterval) /* at least 1 msec please! */ + iInterval = 1; + + if (!pData->fSettimer ((mng_handle)pData, iInterval)) + MNG_ERROR (pData, MNG_APPTIMERERROR) + + pData->bTimerset = MNG_TRUE; /* and indicate so */ + + return MNG_NOERROR; +} + +/* ************************************************************************** */ +/* * * */ +/* * Progressive display refresh - does the call to the refresh callback * */ +/* * and sets the timer to allow the app to perform the actual refresh to * */ +/* * the screen (eg. process its main message-loop) * */ +/* * * */ +/* ************************************************************************** */ + +mng_retcode display_progressive_refresh (mng_datap pData, + mng_uint32 iInterval) +{ + if (!pData->bSearching) /* we mustn't be searching !!! */ + { + if ((pData->bRunning) && /* let the app refresh first ? */ + (pData->iUpdatetop < pData->iUpdatebottom) && (pData->iUpdateleft < pData->iUpdateright)) + { + if (!pData->fRefresh (((mng_handle)pData), + pData->iUpdateleft, pData->iUpdatetop, + pData->iUpdateright - pData->iUpdateleft, + pData->iUpdatebottom - pData->iUpdatetop)) + MNG_ERROR (pData, MNG_APPMISCERROR) + + pData->iUpdateleft = 0; /* reset update-region */ + pData->iUpdateright = 0; + pData->iUpdatetop = 0; + pData->iUpdatebottom = 0; /* reset refreshneeded indicator */ + pData->bNeedrefresh = MNG_FALSE; + /* interval requested ? */ + if ((!pData->bFreezing) && (iInterval)) + { /* setup the timer */ + mng_retcode iRetcode = set_delay (pData, iInterval); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + } + } + + return MNG_NOERROR; +} + +/* ************************************************************************** */ +/* * * */ +/* * Generic display routines * */ +/* * * */ +/* ************************************************************************** */ + +mng_retcode interframe_delay (mng_datap pData) +{ + mng_uint32 iWaitfor = 0; + mng_uint32 iInterval; + mng_uint32 iRuninterval; + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_INTERFRAME_DELAY, MNG_LC_START) +#endif + + if (!pData->bSearching) /* we mustn't be searching !!! */ + { + if (pData->iFramedelay > 0) /* real delay ? */ + { + if ((pData->bRunning) && /* let the app refresh first ? */ + (pData->iUpdatetop < pData->iUpdatebottom) && (pData->iUpdateleft < pData->iUpdateright)) + if (!pData->fRefresh (((mng_handle)pData), + pData->iUpdateleft, pData->iUpdatetop, + pData->iUpdateright - pData->iUpdateleft, + pData->iUpdatebottom - pData->iUpdatetop)) + MNG_ERROR (pData, MNG_APPMISCERROR) + + pData->iUpdateleft = 0; /* reset update-region */ + pData->iUpdateright = 0; + pData->iUpdatetop = 0; + pData->iUpdatebottom = 0; /* reset refreshneeded indicator */ + pData->bNeedrefresh = MNG_FALSE; + /* get current tickcount */ + pData->iRuntime = pData->fGettickcount ((mng_handle)pData); + /* calculate interval since last sync-point */ + if (pData->iRuntime < pData->iSynctime) + iRuninterval = pData->iRuntime + ~pData->iSynctime + 1; + else + iRuninterval = pData->iRuntime - pData->iSynctime; + /* calculate actual run-time */ + if (pData->iRuntime < pData->iStarttime) + pData->iRuntime = pData->iRuntime + ~pData->iStarttime + 1; + else + pData->iRuntime = pData->iRuntime - pData->iStarttime; + + if (pData->iTicks) /* what are we aiming for */ + { + switch (pData->iSpeed) /* honor speed modifier */ + { + case mng_st_fast : + { + iWaitfor = (mng_uint32)(( 500 * pData->iFramedelay) / pData->iTicks); + break; + } + case mng_st_slow : + { + iWaitfor = (mng_uint32)((3000 * pData->iFramedelay) / pData->iTicks); + break; + } + case mng_st_slowest : + { + iWaitfor = (mng_uint32)((8000 * pData->iFramedelay) / pData->iTicks); + break; + } + default : + { + iWaitfor = (mng_uint32)((1000 * pData->iFramedelay) / pData->iTicks); + } + } + } + else + { + if (pData->eImagetype == mng_it_mng) + iWaitfor = 1000; + else + iWaitfor = 1; + } + + if (iWaitfor > iRuninterval) /* delay necessary ? */ + iInterval = iWaitfor - iRuninterval; + else + iInterval = 1; /* force app to process messageloop */ + + if (pData->bRunning) /* set the timer ? */ + { + iRetcode = set_delay (pData, iInterval); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + } + + if (pData->bRunning) /* increase frametime in advance */ + pData->iFrametime = pData->iFrametime + iWaitfor; + /* setup for next delay */ + pData->iFramedelay = pData->iNextdelay; + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_INTERFRAME_DELAY, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +void set_display_routine (mng_datap pData) +{ /* actively running ? */ + if ((pData->bRunning) && (!pData->bFreezing)) + { + switch (pData->iCanvasstyle) /* determine display routine */ + { + case MNG_CANVAS_RGB8 : { pData->fDisplayrow = (mng_fptr)display_rgb8; break; } + case MNG_CANVAS_RGBA8 : { pData->fDisplayrow = (mng_fptr)display_rgba8; break; } + case MNG_CANVAS_ARGB8 : { pData->fDisplayrow = (mng_fptr)display_argb8; break; } + case MNG_CANVAS_RGB8_A8 : { pData->fDisplayrow = (mng_fptr)display_rgb8_a8; break; } + case MNG_CANVAS_BGR8 : { pData->fDisplayrow = (mng_fptr)display_bgr8; break; } + case MNG_CANVAS_BGRA8 : { pData->fDisplayrow = (mng_fptr)display_bgra8; break; } + case MNG_CANVAS_BGRA8PM : { pData->fDisplayrow = (mng_fptr)display_bgra8_pm; break; } + case MNG_CANVAS_ABGR8 : { pData->fDisplayrow = (mng_fptr)display_abgr8; break; } +/* case MNG_CANVAS_RGB16 : { pData->fDisplayrow = (mng_fptr)display_rgb16; break; } */ +/* case MNG_CANVAS_RGBA16 : { pData->fDisplayrow = (mng_fptr)display_rgba16; break; } */ +/* case MNG_CANVAS_ARGB16 : { pData->fDisplayrow = (mng_fptr)display_argb16; break; } */ +/* case MNG_CANVAS_BGR16 : { pData->fDisplayrow = (mng_fptr)display_bgr16; break; } */ +/* case MNG_CANVAS_BGRA16 : { pData->fDisplayrow = (mng_fptr)display_bgra16; break; } */ +/* case MNG_CANVAS_ABGR16 : { pData->fDisplayrow = (mng_fptr)display_abgr16; break; } */ +/* case MNG_CANVAS_INDEX8 : { pData->fDisplayrow = (mng_fptr)display_index8; break; } */ +/* case MNG_CANVAS_INDEXA8 : { pData->fDisplayrow = (mng_fptr)display_indexa8; break; } */ +/* case MNG_CANVAS_AINDEX8 : { pData->fDisplayrow = (mng_fptr)display_aindex8; break; } */ +/* case MNG_CANVAS_GRAY8 : { pData->fDisplayrow = (mng_fptr)display_gray8; break; } */ +/* case MNG_CANVAS_GRAY16 : { pData->fDisplayrow = (mng_fptr)display_gray16; break; } */ +/* case MNG_CANVAS_GRAYA8 : { pData->fDisplayrow = (mng_fptr)display_graya8; break; } */ +/* case MNG_CANVAS_GRAYA16 : { pData->fDisplayrow = (mng_fptr)display_graya16; break; } */ +/* case MNG_CANVAS_AGRAY8 : { pData->fDisplayrow = (mng_fptr)display_agray8; break; } */ +/* case MNG_CANVAS_AGRAY16 : { pData->fDisplayrow = (mng_fptr)display_agray16; break; } */ +/* case MNG_CANVAS_DX15 : { pData->fDisplayrow = (mng_fptr)display_dx15; break; } */ +/* case MNG_CANVAS_DX16 : { pData->fDisplayrow = (mng_fptr)display_dx16; break; } */ + } + } + + return; +} + +/* ************************************************************************** */ + +mng_retcode load_bkgdlayer (mng_datap pData) +{ +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_LOAD_BKGDLAYER, MNG_LC_START) +#endif + /* actively running ? */ + if ((pData->bRunning) && (!pData->bFreezing)) + { + mng_int32 iY; + mng_retcode iRetcode; /* save values */ + mng_int32 iDestl = pData->iDestl; + mng_int32 iDestr = pData->iDestr; + mng_int32 iDestt = pData->iDestt; + mng_int32 iDestb = pData->iDestb; + mng_int32 iSourcel = pData->iSourcel; + mng_int32 iSourcer = pData->iSourcer; + mng_int32 iSourcet = pData->iSourcet; + mng_int32 iSourceb = pData->iSourceb; + mng_int8 iPass = pData->iPass; + mng_int32 iRow = pData->iRow; + mng_int32 iRowinc = pData->iRowinc; + mng_int32 iCol = pData->iCol; + mng_int32 iColinc = pData->iColinc; + mng_int32 iRowsamples = pData->iRowsamples; + mng_int32 iRowsize = pData->iRowsize; + mng_bool bIsRGBA16 = pData->bIsRGBA16; + mng_bool bIsOpaque = pData->bIsOpaque; + mng_fptr fCorrectrow = pData->fCorrectrow; + + pData->iDestl = 0; /* determine clipping region */ + pData->iDestt = 0; + pData->iDestr = pData->iWidth; + pData->iDestb = pData->iHeight; + + if (pData->bFrameclipping) /* frame clipping specified ? */ + { + pData->iDestl = MAX_COORD (pData->iDestl, pData->iFrameclipl); + pData->iDestt = MAX_COORD (pData->iDestt, pData->iFrameclipt); + pData->iDestr = MIN_COORD (pData->iDestr, pData->iFrameclipr); + pData->iDestb = MIN_COORD (pData->iDestb, pData->iFrameclipb); + } + /* anything to clear ? */ + if ((pData->iDestr >= pData->iDestl) && (pData->iDestb >= pData->iDestt)) + { + pData->iPass = -1; /* these are the object's dimensions now */ + pData->iRow = 0; + pData->iRowinc = 1; + pData->iCol = 0; + pData->iColinc = 1; + pData->iRowsamples = pData->iWidth; + pData->iRowsize = pData->iRowsamples << 2; + pData->bIsRGBA16 = MNG_FALSE; /* let's keep it simple ! */ + pData->bIsOpaque = MNG_TRUE; + + pData->iSourcel = 0; /* source relative to destination */ + pData->iSourcer = pData->iDestr - pData->iDestl; + pData->iSourcet = 0; + pData->iSourceb = pData->iDestb - pData->iDestt; + + set_display_routine (pData); /* determine display routine */ + /* default restore using preset BG color */ + pData->fRestbkgdrow = (mng_fptr)restore_bkgd_bgcolor; + + if (((pData->eImagetype == mng_it_png) || (pData->eImagetype == mng_it_jng)) && + (pData->bUseBKGD)) + { /* prefer bKGD in PNG/JNG */ + mng_imagep pImage = (mng_imagep)pData->pCurrentobj; + + if (!pImage) + pImage = (mng_imagep)pData->pObjzero; + + if (pImage->pImgbuf->bHasBKGD) + pData->fRestbkgdrow = (mng_fptr)restore_bkgd_bkgd; + } + + if (pData->fGetbkgdline) /* background-canvas-access callback set ? */ + { + switch (pData->iBkgdstyle) + { + case MNG_CANVAS_RGB8 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_rgb8; break; } + case MNG_CANVAS_BGR8 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_bgr8; break; } + /* case MNG_CANVAS_RGB16 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_rgb16; break; } */ + /* case MNG_CANVAS_BGR16 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_bgr16; break; } */ + /* case MNG_CANVAS_INDEX8 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_index8; break; } */ + /* case MNG_CANVAS_GRAY8 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_gray8; break; } */ + /* case MNG_CANVAS_GRAY16 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_gray16; break; } */ + /* case MNG_CANVAS_DX15 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_dx15; break; } */ + /* case MNG_CANVAS_DX16 : { pData->fRestbkgdrow = (mng_fptr)restore_bkgd_dx16; break; } */ + } + } + + if (pData->bHasBACK) + { /* background image ? */ + if ((pData->iBACKmandatory & 0x02) && (pData->iBACKimageid)) + pData->fRestbkgdrow = (mng_fptr)restore_bkgd_backimage; + else /* background color ? */ + if (pData->iBACKmandatory & 0x01) + pData->fRestbkgdrow = (mng_fptr)restore_bkgd_backcolor; + + } + + pData->fCorrectrow = MNG_NULL; /* default no color-correction */ + + + /* TODO: determine color correction; this is tricky; + the BACK color is treated differently as the image; + it probably requires a rewrite of the logic here... */ + + + /* get a temporary row-buffer */ + MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize) + + iY = pData->iDestt; /* this is where we start */ + iRetcode = MNG_NOERROR; /* so far, so good */ + + while ((!iRetcode) && (iY < pData->iDestb)) + { /* restore a background row */ + iRetcode = ((mng_restbkgdrow)pData->fRestbkgdrow) (pData); + /* color correction ? */ + if ((!iRetcode) && (pData->fCorrectrow)) + iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData); + + if (!iRetcode) /* so... display it */ + iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData); + + if (!iRetcode) + iRetcode = next_row (pData); /* adjust variables for next row */ + + iY++; /* and next line */ + } + /* drop the temporary row-buffer */ + MNG_FREE (pData, pData->pRGBArow, pData->iRowsize) + + if (iRetcode) /* on error bail out */ + return iRetcode; + + } + + pData->iDestl = iDestl; /* restore values */ + pData->iDestr = iDestr; + pData->iDestt = iDestt; + pData->iDestb = iDestb; + pData->iSourcel = iSourcel; + pData->iSourcer = iSourcer; + pData->iSourcet = iSourcet; + pData->iSourceb = iSourceb; + pData->iPass = iPass; + pData->iRow = iRow; + pData->iRowinc = iRowinc; + pData->iCol = iCol; + pData->iColinc = iColinc; + pData->iRowsamples = iRowsamples; + pData->iRowsize = iRowsize; + pData->bIsRGBA16 = bIsRGBA16; + pData->bIsOpaque = bIsOpaque; + pData->fCorrectrow = fCorrectrow; + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_LOAD_BKGDLAYER, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode clear_canvas (mng_datap pData) +{ + mng_int32 iY; + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_CLEAR_CANVAS, MNG_LC_START) +#endif + + pData->iDestl = 0; /* clipping region is full canvas! */ + pData->iDestt = 0; + pData->iDestr = pData->iWidth; + pData->iDestb = pData->iHeight; + + pData->iSourcel = 0; /* source is same as destination */ + pData->iSourcer = pData->iWidth; + pData->iSourcet = 0; + pData->iSourceb = pData->iHeight; + + pData->iPass = -1; /* these are the object's dimensions now */ + pData->iRow = 0; + pData->iRowinc = 1; + pData->iCol = 0; + pData->iColinc = 1; + pData->iRowsamples = pData->iWidth; + pData->iRowsize = pData->iRowsamples << 2; + pData->bIsRGBA16 = MNG_FALSE; /* let's keep it simple ! */ + pData->bIsOpaque = MNG_TRUE; + + set_display_routine (pData); /* determine display routine */ + /* get a temporary row-buffer */ + /* it's transparent black by default!! */ + MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize) + + iY = pData->iDestt; /* this is where we start */ + iRetcode = MNG_NOERROR; /* so far, so good */ + + while ((!iRetcode) && (iY < pData->iDestb)) + { /* clear a row then */ + iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData); + + if (!iRetcode) + iRetcode = next_row (pData); /* adjust variables for next row */ + + iY++; /* and next line */ + } + /* drop the temporary row-buffer */ + MNG_FREE (pData, pData->pRGBArow, pData->iRowsize) + + if (iRetcode) /* on error bail out */ + return iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_CLEAR_CANVAS, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode next_frame (mng_datap pData, + mng_uint8 iFramemode, + mng_uint8 iChangedelay, + mng_uint32 iDelay, + mng_uint8 iChangetimeout, + mng_uint32 iTimeout, + mng_uint8 iChangeclipping, + mng_uint8 iCliptype, + mng_int32 iClipl, + mng_int32 iClipr, + mng_int32 iClipt, + mng_int32 iClipb) +{ + mng_retcode iRetcode = MNG_NOERROR; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_NEXT_FRAME, MNG_LC_START) +#endif + + if (!pData->iBreakpoint) /* no previous break here ? */ + { + mng_uint8 iOldmode = pData->iFramemode; + /* interframe delay required ? */ + if ((iOldmode == 2) || (iOldmode == 4)) + { +/* changed here because FRAM 1/3 will delay themselves before each image */ + if ((pData->iFrameseq) && (iFramemode != 1) && (iFramemode != 3)) + iRetcode = interframe_delay (pData); + else + pData->iFramedelay = pData->iNextdelay; + } + else + { /* delay before inserting background layer? */ + if ((pData->bFramedone) && (iFramemode == 4)) + iRetcode = interframe_delay (pData); + } + + if (iRetcode) /* on error bail out */ + return iRetcode; + /* now we'll assume we're in the next frame! */ + if (iFramemode) /* save the new framing mode ? */ + { + pData->iFRAMmode = iFramemode; + pData->iFramemode = iFramemode; + } + else /* reload default */ + pData->iFramemode = pData->iFRAMmode; + + if (iChangedelay) /* delay changed ? */ + { + pData->iNextdelay = iDelay; /* for *after* next subframe */ + + if ((iOldmode == 2) || (iOldmode == 4)) +/* pData->iFramedelay = iDelay; */ + pData->iFramedelay = pData->iFRAMdelay; + + if (iChangedelay == 2) /* also overall ? */ + pData->iFRAMdelay = iDelay; + } + else + { /* reload default */ + pData->iNextdelay = pData->iFRAMdelay; + +/* if ((iOldmode == 2) || (iOldmode == 4)) + pData->iFramedelay = pData->iNextdelay; */ + } + + if (iChangetimeout) /* timeout changed ? */ + { /* for next subframe */ + pData->iFrametimeout = iTimeout; + + if ((iChangetimeout == 2) || /* also overall ? */ + (iChangetimeout == 4) || + (iChangetimeout == 6) || + (iChangetimeout == 8)) + pData->iFRAMtimeout = iTimeout; + } + else /* reload default */ + pData->iFrametimeout = pData->iFRAMtimeout; + + if (iChangeclipping) /* clipping changed ? */ + { + pData->bFrameclipping = MNG_TRUE; + + if (!iCliptype) /* absolute ? */ + { + pData->iFrameclipl = iClipl; + pData->iFrameclipr = iClipr; + pData->iFrameclipt = iClipt; + pData->iFrameclipb = iClipb; + } + else /* relative */ + { + pData->iFrameclipl = pData->iFrameclipl + iClipl; + pData->iFrameclipr = pData->iFrameclipr + iClipr; + pData->iFrameclipt = pData->iFrameclipt + iClipt; + pData->iFrameclipb = pData->iFrameclipb + iClipb; + } + + if (iChangeclipping == 2) /* also overall ? */ + { + pData->bFRAMclipping = MNG_TRUE; + + if (!iCliptype) /* absolute ? */ + { + pData->iFRAMclipl = iClipl; + pData->iFRAMclipr = iClipr; + pData->iFRAMclipt = iClipt; + pData->iFRAMclipb = iClipb; + } + else /* relative */ + { + pData->iFRAMclipl = pData->iFRAMclipl + iClipl; + pData->iFRAMclipr = pData->iFRAMclipr + iClipr; + pData->iFRAMclipt = pData->iFRAMclipt + iClipt; + pData->iFRAMclipb = pData->iFRAMclipb + iClipb; + } + } + } + else + { /* reload defaults */ + pData->bFrameclipping = pData->bFRAMclipping; + pData->iFrameclipl = pData->iFRAMclipl; + pData->iFrameclipr = pData->iFRAMclipr; + pData->iFrameclipt = pData->iFRAMclipt; + pData->iFrameclipb = pData->iFRAMclipb; + } + } + + if (!pData->bTimerset) /* timer still off ? */ + { + if ((pData->iFramemode == 4) || /* insert background layer after a new frame */ + (!pData->iLayerseq)) /* and certainly before the very first layer */ + iRetcode = load_bkgdlayer (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + + if ((pData->bDisplaying) && (pData->bRunning)) + { + pData->iFrameseq++; /* count the frame ! */ + pData->bFramedone = MNG_TRUE; /* and indicate we've done one */ + } + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_NEXT_FRAME, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode next_layer (mng_datap pData) +{ + mng_imagep pImage; + mng_retcode iRetcode = MNG_NOERROR; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_NEXT_LAYER, MNG_LC_START) +#endif + + if (!pData->iBreakpoint) /* no previous break here ? */ + { /* interframe delay required ? */ + if ((pData->eImagetype == mng_it_mng) && (pData->iLayerseq) && + ((pData->iFramemode == 1) || (pData->iFramemode == 3))) + iRetcode = interframe_delay (pData); + else + pData->iFramedelay = pData->iNextdelay; + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + + if (!pData->bTimerset) /* timer still off ? */ + { + if (!pData->iLayerseq) /* restore background for the very first layer ? */ + { /* wait till IDAT/JDAT for PNGs & JNGs !!! */ + if ((pData->eImagetype == mng_it_png) || (pData->eImagetype == mng_it_jng)) + pData->bRestorebkgd = MNG_TRUE; + else + { /* for MNG we do it right away */ + iRetcode = load_bkgdlayer (pData); + + if (pData->bRunning) + pData->iLayerseq++; /* and it counts as a layer then ! */ + } + } + else + if (pData->iFramemode == 3) /* restore background for each layer ? */ + iRetcode = load_bkgdlayer (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + + if (pData->bHasDHDR) /* processing a delta-image ? */ + pImage = (mng_imagep)pData->pDeltaImage; + else + pImage = (mng_imagep)pData->pCurrentobj; + + if (!pImage) /* not an active object ? */ + pImage = (mng_imagep)pData->pObjzero; + /* determine display rectangle */ + pData->iDestl = MAX_COORD ((mng_int32)0, pImage->iPosx); + pData->iDestt = MAX_COORD ((mng_int32)0, pImage->iPosy); + /* is it a valid buffer ? */ + if ((pImage->pImgbuf->iWidth) && (pImage->pImgbuf->iHeight)) + { + pData->iDestr = MIN_COORD ((mng_int32)pData->iWidth, + pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth ); + pData->iDestb = MIN_COORD ((mng_int32)pData->iHeight, + pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight); + } + else /* it's a single image ! */ + { + pData->iDestr = MIN_COORD ((mng_int32)pData->iWidth, + (mng_int32)pData->iDatawidth ); + pData->iDestb = MIN_COORD ((mng_int32)pData->iHeight, + (mng_int32)pData->iDataheight); + } + + if (pData->bFrameclipping) /* frame clipping specified ? */ + { + pData->iDestl = MAX_COORD (pData->iDestl, pData->iFrameclipl); + pData->iDestt = MAX_COORD (pData->iDestt, pData->iFrameclipt); + pData->iDestr = MIN_COORD (pData->iDestr, pData->iFrameclipr); + pData->iDestb = MIN_COORD (pData->iDestb, pData->iFrameclipb); + } + + if (pImage->bClipped) /* is the image clipped itself ? */ + { + pData->iDestl = MAX_COORD (pData->iDestl, pImage->iClipl); + pData->iDestt = MAX_COORD (pData->iDestt, pImage->iClipt); + pData->iDestr = MIN_COORD (pData->iDestr, pImage->iClipr); + pData->iDestb = MIN_COORD (pData->iDestb, pImage->iClipb); + } + /* determine source starting point */ + pData->iSourcel = MAX_COORD ((mng_int32)0, pData->iDestl - pImage->iPosx); + pData->iSourcet = MAX_COORD ((mng_int32)0, pData->iDestt - pImage->iPosy); + + if ((pImage->pImgbuf->iWidth) && (pImage->pImgbuf->iHeight)) + { /* and maximum size */ + pData->iSourcer = MIN_COORD ((mng_int32)pImage->pImgbuf->iWidth, + pData->iSourcel + pData->iDestr - pData->iDestl); + pData->iSourceb = MIN_COORD ((mng_int32)pImage->pImgbuf->iHeight, + pData->iSourcet + pData->iDestb - pData->iDestt); + } + else /* it's a single image ! */ + { + pData->iSourcer = pData->iSourcel + pData->iDestr - pData->iDestl; + pData->iSourceb = pData->iSourcet + pData->iDestb - pData->iDestt; + } + + if (pData->bRunning) + pData->iLayerseq++; /* count the layer ! */ + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_NEXT_LAYER, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode display_image (mng_datap pData, + mng_imagep pImage, + mng_bool bLayeradvanced) +{ + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_DISPLAY_IMAGE, MNG_LC_START) +#endif + /* actively running ? */ + if ((pData->bRunning) && (!pData->bFreezing)) + { + if ( (!pData->iBreakpoint) && /* needs magnification ? */ + ( (pImage->iMAGN_MethodX) || (pImage->iMAGN_MethodY) ) ) + { + iRetcode = magnify_imageobject (pData, pImage); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + } + + pData->pRetrieveobj = pImage; /* so retrieve-row and color-correction can find it */ + + if (!bLayeradvanced) /* need to advance the layer ? */ + { + mng_imagep pSave = pData->pCurrentobj; + pData->pCurrentobj = pImage; + next_layer (pData); /* advance to next layer */ + pData->pCurrentobj = pSave; + } + /* need to restore the background ? */ + if ((!pData->bTimerset) && (pData->bRestorebkgd)) + { + mng_imagep pSave = pData->pCurrentobj; + pData->pCurrentobj = pImage; + pData->bRestorebkgd = MNG_FALSE; + iRetcode = load_bkgdlayer (pData); + pData->pCurrentobj = pSave; + + if (iRetcode) /* on error bail out */ + return iRetcode; + + if (pData->bRunning) + pData->iLayerseq++; /* and it counts as a layer then ! */ + } + /* actively running ? */ + if ((pData->bRunning) && (!pData->bFreezing)) + { + if (!pData->bTimerset) /* all systems still go ? */ + { + pData->iBreakpoint = 0; /* let's make absolutely sure... */ + /* anything to display ? */ + if ((pData->iDestr >= pData->iDestl) && (pData->iDestb >= pData->iDestt)) + { + mng_int32 iY; + + set_display_routine (pData); /* determine display routine */ + /* and image-buffer retrieval routine */ + switch (pImage->pImgbuf->iColortype) + { + case 0 : { if (pImage->pImgbuf->iBitdepth > 8) + pData->fRetrieverow = (mng_fptr)retrieve_g16; + else + pData->fRetrieverow = (mng_fptr)retrieve_g8; + + pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS); + break; + } + + case 2 : { if (pImage->pImgbuf->iBitdepth > 8) + pData->fRetrieverow = (mng_fptr)retrieve_rgb16; + else + pData->fRetrieverow = (mng_fptr)retrieve_rgb8; + + pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS); + break; + } + + + case 3 : { pData->fRetrieverow = (mng_fptr)retrieve_idx8; + pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS); + break; + } + + + case 4 : { if (pImage->pImgbuf->iBitdepth > 8) + pData->fRetrieverow = (mng_fptr)retrieve_ga16; + else + pData->fRetrieverow = (mng_fptr)retrieve_ga8; + + pData->bIsOpaque = MNG_FALSE; + break; + } + + + case 6 : { if (pImage->pImgbuf->iBitdepth > 8) + pData->fRetrieverow = (mng_fptr)retrieve_rgba16; + else + pData->fRetrieverow = (mng_fptr)retrieve_rgba8; + + pData->bIsOpaque = MNG_FALSE; + break; + } + + case 8 : { if (pImage->pImgbuf->iBitdepth > 8) + pData->fRetrieverow = (mng_fptr)retrieve_g16; + else + pData->fRetrieverow = (mng_fptr)retrieve_g8; + + pData->bIsOpaque = MNG_TRUE; + break; + } + + case 10 : { if (pImage->pImgbuf->iBitdepth > 8) + pData->fRetrieverow = (mng_fptr)retrieve_rgb16; + else + pData->fRetrieverow = (mng_fptr)retrieve_rgb8; + + pData->bIsOpaque = MNG_TRUE; + break; + } + + + case 12 : { if (pImage->pImgbuf->iBitdepth > 8) + pData->fRetrieverow = (mng_fptr)retrieve_ga16; + else + pData->fRetrieverow = (mng_fptr)retrieve_ga8; + + pData->bIsOpaque = MNG_FALSE; + break; + } + + + case 14 : { if (pImage->pImgbuf->iBitdepth > 8) + pData->fRetrieverow = (mng_fptr)retrieve_rgba16; + else + pData->fRetrieverow = (mng_fptr)retrieve_rgba8; + + pData->bIsOpaque = MNG_FALSE; + break; + } + + } + + pData->iPass = -1; /* these are the object's dimensions now */ + pData->iRow = pData->iSourcet; + pData->iRowinc = 1; + pData->iCol = 0; + pData->iColinc = 1; + pData->iRowsamples = pImage->pImgbuf->iWidth; + pData->iRowsize = pData->iRowsamples << 2; + pData->bIsRGBA16 = MNG_FALSE; + /* adjust for 16-bit object ? */ + if (pImage->pImgbuf->iBitdepth > 8) + { + pData->bIsRGBA16 = MNG_TRUE; + pData->iRowsize = pData->iRowsamples << 3; + } + + pData->fCorrectrow = MNG_NULL; /* default no color-correction */ + +#ifdef MNG_NO_CMS + iRetcode = MNG_NOERROR; +#else +#if defined(MNG_FULL_CMS) /* determine color-management routine */ + iRetcode = init_full_cms_object (pData); +#elif defined(MNG_GAMMA_ONLY) + iRetcode = init_gamma_only_object (pData); +#elif defined(MNG_APP_CMS) + iRetcode = init_app_cms_object (pData); +#endif + if (iRetcode) /* on error bail out */ + return iRetcode; +#endif /* MNG_NO_CMS */ + /* get a temporary row-buffer */ + MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize) + + iY = pData->iSourcet; /* this is where we start */ + + while ((!iRetcode) && (iY < pData->iSourceb)) + { /* get a row */ + iRetcode = ((mng_retrieverow)pData->fRetrieverow) (pData); + /* color correction ? */ + if ((!iRetcode) && (pData->fCorrectrow)) + iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData); + + if (!iRetcode) /* so... display it */ + iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData); + + if (!iRetcode) /* adjust variables for next row */ + iRetcode = next_row (pData); + + iY++; /* and next line */ + } + /* drop the temporary row-buffer */ + MNG_FREE (pData, pData->pRGBArow, pData->iRowsize) + + if (iRetcode) /* on error bail out */ + return iRetcode; + +#if defined(MNG_INCLUDE_LCMS) /* cleanup cms stuff */ + iRetcode = mng_clear_cms (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; +#endif + } + } + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_DISPLAY_IMAGE, MNG_LC_END) +#endif + + return MNG_NOERROR; /* whehehe, this is good ! */ +} + +/* ************************************************************************** */ + +mng_retcode execute_delta_image (mng_datap pData, + mng_imagep pTarget, + mng_imagep pDelta) +{ + mng_imagedatap pBuftarget = pTarget->pImgbuf; + mng_imagedatap pBufdelta = pDelta->pImgbuf; + mng_uint32 iY; + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_EXECUTE_DELTA_IMAGE, MNG_LC_START) +#endif + /* actively running ? */ + if ((pData->bRunning) && (!pData->bFreezing)) + { + if (pBufdelta->bHasPLTE) /* palette in delta ? */ + { + mng_uint32 iX; + /* new palette larger than old one ? */ + if ((!pBuftarget->bHasPLTE) || (pBuftarget->iPLTEcount < pBufdelta->iPLTEcount)) + pBuftarget->iPLTEcount = pBufdelta->iPLTEcount; + /* it's definitely got a PLTE now */ + pBuftarget->bHasPLTE = MNG_TRUE; + + for (iX = 0; iX < pBufdelta->iPLTEcount; iX++) + { + pBuftarget->aPLTEentries[iX].iRed = pBufdelta->aPLTEentries[iX].iRed; + pBuftarget->aPLTEentries[iX].iGreen = pBufdelta->aPLTEentries[iX].iGreen; + pBuftarget->aPLTEentries[iX].iBlue = pBufdelta->aPLTEentries[iX].iBlue; + } + } + + if (pBufdelta->bHasTRNS) /* cheap transparency in delta ? */ + { + switch (pData->iColortype) /* drop it into the target */ + { + case 0: { /* gray */ + pBuftarget->iTRNSgray = pBufdelta->iTRNSgray; + pBuftarget->iTRNSred = 0; + pBuftarget->iTRNSgreen = 0; + pBuftarget->iTRNSblue = 0; + pBuftarget->iTRNScount = 0; + break; + } + case 2: { /* rgb */ + pBuftarget->iTRNSgray = 0; + pBuftarget->iTRNSred = pBufdelta->iTRNSred; + pBuftarget->iTRNSgreen = pBufdelta->iTRNSgreen; + pBuftarget->iTRNSblue = pBufdelta->iTRNSblue; + pBuftarget->iTRNScount = 0; + break; + } + case 3: { /* indexed */ + pBuftarget->iTRNSgray = 0; + pBuftarget->iTRNSred = 0; + pBuftarget->iTRNSgreen = 0; + pBuftarget->iTRNSblue = 0; + /* existing range smaller than new one ? */ + if ((!pBuftarget->bHasTRNS) || (pBuftarget->iTRNScount < pBufdelta->iTRNScount)) + pBuftarget->iTRNScount = pBufdelta->iTRNScount; + + MNG_COPY (pBuftarget->aTRNSentries, pBufdelta->aTRNSentries, pBufdelta->iTRNScount) + break; + } + } + + pBuftarget->bHasTRNS = MNG_TRUE; /* tell it it's got a tRNS now */ + } + + if (pBufdelta->bHasBKGD) /* bkgd in source ? */ + { /* drop it onto the target */ + pBuftarget->bHasBKGD = MNG_TRUE; + pBuftarget->iBKGDindex = pBufdelta->iBKGDindex; + pBuftarget->iBKGDgray = pBufdelta->iBKGDgray; + pBuftarget->iBKGDred = pBufdelta->iBKGDred; + pBuftarget->iBKGDgreen = pBufdelta->iBKGDgreen; + pBuftarget->iBKGDblue = pBufdelta->iBKGDblue; + } + + if (pBufdelta->bHasGAMA) /* gamma in source ? */ + { + pBuftarget->bHasGAMA = MNG_TRUE; /* drop it onto the target */ + pBuftarget->iGamma = pBufdelta->iGamma; + } + + if (pBufdelta->bHasCHRM) /* chroma in delta ? */ + { /* drop it onto the target */ + pBuftarget->bHasCHRM = MNG_TRUE; + pBuftarget->iWhitepointx = pBufdelta->iWhitepointx; + pBuftarget->iWhitepointy = pBufdelta->iWhitepointy; + pBuftarget->iPrimaryredx = pBufdelta->iPrimaryredx; + pBuftarget->iPrimaryredy = pBufdelta->iPrimaryredy; + pBuftarget->iPrimarygreenx = pBufdelta->iPrimarygreenx; + pBuftarget->iPrimarygreeny = pBufdelta->iPrimarygreeny; + pBuftarget->iPrimarybluex = pBufdelta->iPrimarybluex; + pBuftarget->iPrimarybluey = pBufdelta->iPrimarybluey; + } + + if (pBufdelta->bHasSRGB) /* sRGB in delta ? */ + { /* drop it onto the target */ + pBuftarget->bHasSRGB = MNG_TRUE; + pBuftarget->iRenderingintent = pBufdelta->iRenderingintent; + } + + if (pBufdelta->bHasICCP) /* ICC profile in delta ? */ + { + pBuftarget->bHasICCP = MNG_TRUE; /* drop it onto the target */ + + if (pBuftarget->pProfile) /* profile existed ? */ + MNG_FREEX (pData, pBuftarget->pProfile, pBuftarget->iProfilesize) + /* allocate a buffer & copy it */ + MNG_ALLOC (pData, pBuftarget->pProfile, pBufdelta->iProfilesize) + MNG_COPY (pBuftarget->pProfile, pBufdelta->pProfile, pBufdelta->iProfilesize) + /* store it's length as well */ + pBuftarget->iProfilesize = pBufdelta->iProfilesize; + } + /* need to execute delta pixels ? */ + if ((!pData->bDeltaimmediate) && (pData->iDeltatype != MNG_DELTATYPE_NOCHANGE)) + { + pData->fScalerow = MNG_NULL; /* not needed by default */ + + switch (pBuftarget->iBitdepth) /* determine scaling routine */ + { + + + } + + pData->fDeltarow = MNG_NULL; /* let's assume there's nothing to do */ + + switch (pBuftarget->iColortype) /* determine delta processing routine */ + { + case 0 : ; + case 8 : { /* gray */ + if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) ) + { + if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3) || + (pBufdelta->iColortype == 8)) + { + switch (pBuftarget->iBitdepth) + { + case 1 : { pData->fDeltarow = (mng_fptr)delta_g1_g1; break; } + case 2 : { pData->fDeltarow = (mng_fptr)delta_g2_g2; break; } + case 4 : { pData->fDeltarow = (mng_fptr)delta_g4_g4; break; } + case 8 : { pData->fDeltarow = (mng_fptr)delta_g8_g8; break; } + case 16 : { pData->fDeltarow = (mng_fptr)delta_g16_g16; break; } + } + } + } + + break; + } + + case 2 : ; + case 10 : { /* rgb */ + if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) ) + { + if ((pBufdelta->iColortype == 2) || (pBufdelta->iColortype == 10)) + { + switch (pBuftarget->iBitdepth) + { + case 8 : { pData->fDeltarow = (mng_fptr)delta_rgb8_rgb8; break; } + case 16 : { pData->fDeltarow = (mng_fptr)delta_rgb16_rgb16; break; } + } + } + } + + break; + } + + case 3 : { /* indexed; abuse gray routines */ + if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) ) + { + if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3)) + { + switch (pBuftarget->iBitdepth) + { + case 1 : { pData->fDeltarow = (mng_fptr)delta_g1_g1; break; } + case 2 : { pData->fDeltarow = (mng_fptr)delta_g2_g2; break; } + case 4 : { pData->fDeltarow = (mng_fptr)delta_g4_g4; break; } + case 8 : { pData->fDeltarow = (mng_fptr)delta_g8_g8; break; } + } + } + } + + break; + } + + case 4 : ; + case 12 : { /* gray + alpha */ + if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) ) + { + if ((pBufdelta->iColortype == 4) || (pBufdelta->iColortype == 12)) + { + switch (pBuftarget->iBitdepth) + { + case 8 : { pData->fDeltarow = (mng_fptr)delta_ga8_ga8; break; } + case 16 : { pData->fDeltarow = (mng_fptr)delta_ga16_ga16; break; } + } + } + } + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) ) + { + if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3) || + (pBufdelta->iColortype == 8)) + { + switch (pBuftarget->iBitdepth) + { + case 8 : { pData->fDeltarow = (mng_fptr)delta_ga8_g8; break; } + case 16 : { pData->fDeltarow = (mng_fptr)delta_ga16_g16; break; } + } + } + } + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) ) + { + if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3)) + { + switch (pBuftarget->iBitdepth) + { + case 8 : { pData->fDeltarow = (mng_fptr)delta_ga8_a8; break; } + case 16 : { pData->fDeltarow = (mng_fptr)delta_ga16_a16; break; } + } + } + } + + break; + } + + case 6 : ; + case 14 : { /* rgb + alpha */ + if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) ) + { + if ((pBufdelta->iColortype == 6) || (pBufdelta->iColortype == 14)) + { + switch (pBuftarget->iBitdepth) + { + case 8 : { pData->fDeltarow = (mng_fptr)delta_rgba8_rgba8; break; } + case 16 : { pData->fDeltarow = (mng_fptr)delta_rgba16_rgba16; break; } + } + } + } + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) ) + { + if ((pBufdelta->iColortype == 2) || (pBufdelta->iColortype == 10)) + { + switch (pBuftarget->iBitdepth) + { + case 8 : { pData->fDeltarow = (mng_fptr)delta_rgba8_rgb8; break; } + case 16 : { pData->fDeltarow = (mng_fptr)delta_rgba16_rgb16; break; } + } + } + } + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) ) + { + if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3)) + { + switch (pBuftarget->iBitdepth) + { + case 8 : { pData->fDeltarow = (mng_fptr)delta_rgba8_a8; break; } + case 16 : { pData->fDeltarow = (mng_fptr)delta_rgba16_a16; break; } + } + } + } + + break; + } + + } + + if (pData->fDeltarow) /* do we need to take action ? */ + { + pData->iPass = -1; /* setup row dimensions and stuff */ + pData->iRow = pData->iDeltaBlocky; + pData->iRowinc = 1; + pData->iCol = pData->iDeltaBlockx; + pData->iColinc = 1; + pData->iRowsamples = pBufdelta->iWidth; + pData->iRowsize = pBuftarget->iRowsize; + /* indicate where to retrieve & where to store */ + pData->pRetrieveobj = (mng_objectp)pDelta; + pData->pStoreobj = (mng_objectp)pTarget; + + if (pData->pRGBArow) /* prevent duplicate allocation! */ + MNG_FREE (pData, pData->pRGBArow, (pData->iDatawidth << 3)) + /* get a temporary row-buffer */ + MNG_ALLOC (pData, pData->pRGBArow, pBufdelta->iRowsize) + + iY = 0; /* this is where we start */ + iRetcode = MNG_NOERROR; /* still oke for now */ + + while ((!iRetcode) && (iY < pBufdelta->iHeight)) + { /* get a row */ + mng_uint8p pWork = pBufdelta->pImgdata + (iY * pBufdelta->iRowsize); + + MNG_COPY (pData->pRGBArow, pWork, pBufdelta->iRowsize); + + if (pData->fScalerow) /* scale it (if necessary) */ + iRetcode = ((mng_scalerow)pData->fScalerow) (pData); + + if (!iRetcode) /* and... execute it */ + iRetcode = ((mng_deltarow)pData->fDeltarow) (pData); + + if (!iRetcode) /* adjust variables for next row */ + iRetcode = next_row (pData); + + iY++; /* and next line */ + } + /* drop the temporary row-buffer */ + MNG_FREE (pData, pData->pRGBArow, pBufdelta->iRowsize) + + if (iRetcode) /* on error bail out */ + return iRetcode; + + } + else + MNG_ERROR (pData, MNG_INVALIDDELTA) + + } + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_EXECUTE_DELTA_IMAGE, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode save_state (mng_datap pData) +{ + mng_savedatap pSave; + mng_imagep pImage; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_SAVE_STATE, MNG_LC_START) +#endif + + if (pData->pSavedata) /* sanity check */ + MNG_ERROR (pData, MNG_INTERNALERROR) + /* get a buffer for saving */ + MNG_ALLOC (pData, pData->pSavedata, sizeof (mng_savedata)) + + pSave = pData->pSavedata; /* address it more directly */ + /* and copy global data from the main struct */ +#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE) + pSave->bHasglobalPLTE = pData->bHasglobalPLTE; + pSave->bHasglobalTRNS = pData->bHasglobalTRNS; + pSave->bHasglobalGAMA = pData->bHasglobalGAMA; + pSave->bHasglobalCHRM = pData->bHasglobalCHRM; + pSave->bHasglobalSRGB = pData->bHasglobalSRGB; + pSave->bHasglobalICCP = pData->bHasglobalICCP; + pSave->bHasglobalBKGD = pData->bHasglobalBKGD; +#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */ + + pSave->iBACKred = pData->iBACKred; + pSave->iBACKgreen = pData->iBACKgreen; + pSave->iBACKblue = pData->iBACKblue; + pSave->iBACKmandatory = pData->iBACKmandatory; + pSave->iBACKimageid = pData->iBACKimageid; + pSave->iBACKtile = pData->iBACKtile; + + pSave->iFRAMmode = pData->iFRAMmode; + pSave->iFRAMdelay = pData->iFRAMdelay; + pSave->iFRAMtimeout = pData->iFRAMtimeout; + pSave->bFRAMclipping = pData->bFRAMclipping; + pSave->iFRAMclipl = pData->iFRAMclipl; + pSave->iFRAMclipr = pData->iFRAMclipr; + pSave->iFRAMclipt = pData->iFRAMclipt; + pSave->iFRAMclipb = pData->iFRAMclipb; + + pSave->iGlobalPLTEcount = pData->iGlobalPLTEcount; + + MNG_COPY (pSave->aGlobalPLTEentries, pData->aGlobalPLTEentries, sizeof (mng_rgbpaltab)) + + pSave->iGlobalTRNSrawlen = pData->iGlobalTRNSrawlen; + MNG_COPY (pSave->aGlobalTRNSrawdata, pData->aGlobalTRNSrawdata, 256) + + pSave->iGlobalGamma = pData->iGlobalGamma; + + pSave->iGlobalWhitepointx = pData->iGlobalWhitepointx; + pSave->iGlobalWhitepointy = pData->iGlobalWhitepointy; + pSave->iGlobalPrimaryredx = pData->iGlobalPrimaryredx; + pSave->iGlobalPrimaryredy = pData->iGlobalPrimaryredy; + pSave->iGlobalPrimarygreenx = pData->iGlobalPrimarygreenx; + pSave->iGlobalPrimarygreeny = pData->iGlobalPrimarygreeny; + pSave->iGlobalPrimarybluex = pData->iGlobalPrimarybluex; + pSave->iGlobalPrimarybluey = pData->iGlobalPrimarybluey; + + pSave->iGlobalRendintent = pData->iGlobalRendintent; + + pSave->iGlobalProfilesize = pData->iGlobalProfilesize; + + if (pSave->iGlobalProfilesize) /* has a profile ? */ + { /* then copy that ! */ + MNG_ALLOC (pData, pSave->pGlobalProfile, pSave->iGlobalProfilesize) + MNG_COPY (pSave->pGlobalProfile, pData->pGlobalProfile, pSave->iGlobalProfilesize) + } + + pSave->iGlobalBKGDred = pData->iGlobalBKGDred; + pSave->iGlobalBKGDgreen = pData->iGlobalBKGDgreen; + pSave->iGlobalBKGDblue = pData->iGlobalBKGDblue; + + /* freeze current image objects */ + pImage = (mng_imagep)pData->pFirstimgobj; + + while (pImage) + { /* freeze the object AND it's buffer */ + pImage->bFrozen = MNG_TRUE; + pImage->pImgbuf->bFrozen = MNG_TRUE; + /* neeeext */ + pImage = (mng_imagep)pImage->sHeader.pNext; + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_SAVE_STATE, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode mng_reset_objzero (mng_datap pData) +{ + mng_imagep pImage = (mng_imagep)pData->pObjzero; + mng_retcode iRetcode = reset_object_details (pData, pImage, 0, 0, 0, + 0, 0, 0, 0, MNG_TRUE); + + if (iRetcode) /* on error bail out */ + return iRetcode; + + pImage->bVisible = MNG_TRUE; + pImage->bViewable = MNG_TRUE; + pImage->iPosx = 0; + pImage->iPosy = 0; + pImage->bClipped = MNG_FALSE; + pImage->iClipl = 0; + pImage->iClipr = 0; + pImage->iClipt = 0; + pImage->iClipb = 0; + pImage->iMAGN_MethodX = 0; + pImage->iMAGN_MethodY = 0; + pImage->iMAGN_MX = 0; + pImage->iMAGN_MY = 0; + pImage->iMAGN_ML = 0; + pImage->iMAGN_MR = 0; + pImage->iMAGN_MT = 0; + pImage->iMAGN_MB = 0; + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode restore_state (mng_datap pData) +{ + mng_savedatap pSave; + mng_imagep pImage; + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_RESTORE_STATE, MNG_LC_START) +#endif + /* restore object 0 status !!! */ + iRetcode = mng_reset_objzero (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + /* fresh cycle; fake no frames done yet */ + pData->bFramedone = MNG_FALSE; + + if (pData->pSavedata) /* do we have a saved state ? */ + { + pSave = pData->pSavedata; /* address it more directly */ + /* and copy it back to the main struct */ +#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE) + pData->bHasglobalPLTE = pSave->bHasglobalPLTE; + pData->bHasglobalTRNS = pSave->bHasglobalTRNS; + pData->bHasglobalGAMA = pSave->bHasglobalGAMA; + pData->bHasglobalCHRM = pSave->bHasglobalCHRM; + pData->bHasglobalSRGB = pSave->bHasglobalSRGB; + pData->bHasglobalICCP = pSave->bHasglobalICCP; + pData->bHasglobalBKGD = pSave->bHasglobalBKGD; +#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */ + + pData->iBACKred = pSave->iBACKred; + pData->iBACKgreen = pSave->iBACKgreen; + pData->iBACKblue = pSave->iBACKblue; + pData->iBACKmandatory = pSave->iBACKmandatory; + pData->iBACKimageid = pSave->iBACKimageid; + pData->iBACKtile = pSave->iBACKtile; + + pData->iFRAMmode = pSave->iFRAMmode; + pData->iFRAMdelay = pSave->iFRAMdelay; + pData->iFRAMtimeout = pSave->iFRAMtimeout; + pData->bFRAMclipping = pSave->bFRAMclipping; + pData->iFRAMclipl = pSave->iFRAMclipl; + pData->iFRAMclipr = pSave->iFRAMclipr; + pData->iFRAMclipt = pSave->iFRAMclipt; + pData->iFRAMclipb = pSave->iFRAMclipb; + /* also the next subframe parms */ + pData->iFramemode = pSave->iFRAMmode; + pData->iFramedelay = pSave->iFRAMdelay; + pData->iFrametimeout = pSave->iFRAMtimeout; + pData->bFrameclipping = pSave->bFRAMclipping; + pData->iFrameclipl = pSave->iFRAMclipl; + pData->iFrameclipr = pSave->iFRAMclipr; + pData->iFrameclipt = pSave->iFRAMclipt; + pData->iFrameclipb = pSave->iFRAMclipb; + + pData->iNextdelay = pSave->iFRAMdelay; + + pData->iGlobalPLTEcount = pSave->iGlobalPLTEcount; + MNG_COPY (pData->aGlobalPLTEentries, pSave->aGlobalPLTEentries, sizeof (mng_rgbpaltab)) + + pData->iGlobalTRNSrawlen = pSave->iGlobalTRNSrawlen; + MNG_COPY (pData->aGlobalTRNSrawdata, pSave->aGlobalTRNSrawdata, 256) + + pData->iGlobalGamma = pSave->iGlobalGamma; + + pData->iGlobalWhitepointx = pSave->iGlobalWhitepointx; + pData->iGlobalWhitepointy = pSave->iGlobalWhitepointy; + pData->iGlobalPrimaryredx = pSave->iGlobalPrimaryredx; + pData->iGlobalPrimaryredy = pSave->iGlobalPrimaryredy; + pData->iGlobalPrimarygreenx = pSave->iGlobalPrimarygreenx; + pData->iGlobalPrimarygreeny = pSave->iGlobalPrimarygreeny; + pData->iGlobalPrimarybluex = pSave->iGlobalPrimarybluex; + pData->iGlobalPrimarybluey = pSave->iGlobalPrimarybluey; + + pData->iGlobalRendintent = pSave->iGlobalRendintent; + + pData->iGlobalProfilesize = pSave->iGlobalProfilesize; + + if (pData->iGlobalProfilesize) /* has a profile ? */ + { /* then copy that ! */ + MNG_ALLOC (pData, pData->pGlobalProfile, pData->iGlobalProfilesize) + MNG_COPY (pData->pGlobalProfile, pSave->pGlobalProfile, pData->iGlobalProfilesize) + } + + pData->iGlobalBKGDred = pSave->iGlobalBKGDred; + pData->iGlobalBKGDgreen = pSave->iGlobalBKGDgreen; + pData->iGlobalBKGDblue = pSave->iGlobalBKGDblue; + } + else /* no saved-data; so reset the lot */ + { +#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE) + pData->bHasglobalPLTE = MNG_FALSE; + pData->bHasglobalTRNS = MNG_FALSE; + pData->bHasglobalGAMA = MNG_FALSE; + pData->bHasglobalCHRM = MNG_FALSE; + pData->bHasglobalSRGB = MNG_FALSE; + pData->bHasglobalICCP = MNG_FALSE; + pData->bHasglobalBKGD = MNG_FALSE; +#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */ + + if (!pData->bEMNGMAhack) /* TODO: remove line in 1.0.0 !!! */ + { /* TODO: remove line in 1.0.0 !!! */ + pData->iBACKred = 0; + pData->iBACKgreen = 0; + pData->iBACKblue = 0; + pData->iBACKmandatory = 0; + pData->iBACKimageid = 0; + pData->iBACKtile = 0; + } /* TODO: remove line in 1.0.0 !!! */ + + pData->iFRAMmode = 1; + pData->iFRAMdelay = 1; + pData->iFRAMtimeout = 0x7fffffffl; + pData->bFRAMclipping = MNG_FALSE; + pData->iFRAMclipl = 0; + pData->iFRAMclipr = 0; + pData->iFRAMclipt = 0; + pData->iFRAMclipb = 0; + /* also the next subframe parms */ + pData->iFramemode = 1; + pData->iFramedelay = 1; + pData->iFrametimeout = 0x7fffffffl; + pData->bFrameclipping = MNG_FALSE; + pData->iFrameclipl = 0; + pData->iFrameclipr = 0; + pData->iFrameclipt = 0; + pData->iFrameclipb = 0; + + pData->iNextdelay = 1; + + pData->iGlobalPLTEcount = 0; + + pData->iGlobalTRNSrawlen = 0; + + pData->iGlobalGamma = 0; + + pData->iGlobalWhitepointx = 0; + pData->iGlobalWhitepointy = 0; + pData->iGlobalPrimaryredx = 0; + pData->iGlobalPrimaryredy = 0; + pData->iGlobalPrimarygreenx = 0; + pData->iGlobalPrimarygreeny = 0; + pData->iGlobalPrimarybluex = 0; + pData->iGlobalPrimarybluey = 0; + + pData->iGlobalRendintent = 0; + + if (pData->iGlobalProfilesize) /* free a previous profile ? */ + MNG_FREE (pData, pData->pGlobalProfile, pData->iGlobalProfilesize) + + pData->iGlobalProfilesize = 0; + + pData->iGlobalBKGDred = 0; + pData->iGlobalBKGDgreen = 0; + pData->iGlobalBKGDblue = 0; + } + + if (!pData->bEMNGMAhack) /* TODO: remove line in 1.0.0 !!! */ + { /* TODO: remove line in 1.0.0 !!! */ + /* drop un-frozen image objects */ + pImage = (mng_imagep)pData->pFirstimgobj; + + while (pImage) + { /* is it un-frozen ? */ + if (!pImage->bFrozen) + { + mng_imagep pPrev = (mng_imagep)pImage->sHeader.pPrev; + mng_imagep pNext = (mng_imagep)pImage->sHeader.pNext; + + if (pPrev) /* unlink it */ + pPrev->sHeader.pNext = pNext; + else + pData->pFirstimgobj = pNext; + + if (pNext) + pNext->sHeader.pPrev = pPrev; + else + pData->pLastimgobj = pPrev; + + if (pImage->pImgbuf->bFrozen) /* buffer frozen ? */ + { + if (pImage->pImgbuf->iRefcount <= 2) + MNG_ERROR (pData, MNG_INTERNALERROR) + /* decrease ref counter */ + pImage->pImgbuf->iRefcount--; + /* just cleanup the object then */ + MNG_FREEX (pData, pImage, sizeof (mng_image)) + } + else + { /* free the image buffer */ + iRetcode = free_imagedataobject (pData, pImage->pImgbuf); + /* and cleanup the object */ + MNG_FREEX (pData, pImage, sizeof (mng_image)) + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + + pImage = pNext; /* this is the next */ + } + else /* neeeext */ + pImage = (mng_imagep)pImage->sHeader.pNext; + + } + } /* TODO: remove line in 1.0.0 !!! */ + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_RESTORE_STATE, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ +/* * * */ +/* * General display processing routine * */ +/* * * */ +/* ************************************************************************** */ + +mng_retcode process_display (mng_datap pData) +{ + mng_retcode iRetcode = MNG_NOERROR; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY, MNG_LC_START) +#endif + + if (!pData->iBreakpoint) /* not broken previously ? */ + { + if ((pData->iRequestframe) || (pData->iRequestlayer) || (pData->iRequesttime)) + { + pData->bSearching = MNG_TRUE; /* indicate we're searching */ + + iRetcode = clear_canvas (pData); /* make the canvas virgin black ?!? */ + + if (iRetcode) /* on error bail out */ + return iRetcode; + /* let's start from the top, shall we */ + pData->pCurraniobj = pData->pFirstaniobj; + } + } + + do /* process the objects */ + { + if (pData->bSearching) /* are we looking sor something ? */ + { + if ((pData->iRequestframe) && + (pData->iRequestframe < ((mng_object_headerp)pData->pCurraniobj)->iFramenr)) + { + pData->iRequestframe = 0; /* found the frame ! */ + pData->bSearching = MNG_FALSE; + } + else + if ((pData->iRequestlayer) && + (pData->iRequestlayer < ((mng_object_headerp)pData->pCurraniobj)->iLayernr)) + { + pData->iRequestlayer = 0; /* found the layer ! */ + pData->bSearching = MNG_FALSE; + } + else + if ((pData->iRequesttime) && + (pData->iRequesttime < ((mng_object_headerp)pData->pCurraniobj)->iPlaytime)) + { + pData->iRequesttime = 0; /* found the playtime ! */ + pData->bSearching = MNG_FALSE; + } + } + /* do we need to finish something first ? */ + if ((pData->iBreakpoint) && (pData->iBreakpoint < 99)) + { + switch (pData->iBreakpoint) /* return to broken display routine */ + { + case 1 : { iRetcode = process_display_fram2 (pData); break; } + case 3 : ; /* same as 4 !!! */ + case 4 : { iRetcode = process_display_show (pData); break; } + case 5 : { iRetcode = process_display_clon2 (pData); break; } + case 9 : { iRetcode = process_display_magn2 (pData); break; } + default : MNG_ERROR (pData, MNG_INTERNALERROR) + } + } + else + { + if (pData->pCurraniobj) + iRetcode = ((mng_object_headerp)pData->pCurraniobj)->fProcess (pData, pData->pCurraniobj); + } + + if (!pData->bTimerset) /* reset breakpoint flag ? */ + pData->iBreakpoint = 0; + /* can we advance to next object ? */ + if ((!iRetcode) && (pData->pCurraniobj) && + (!pData->bTimerset) && (!pData->bSectionwait)) + { + pData->pCurraniobj = ((mng_object_headerp)pData->pCurraniobj)->pNext; + /* MEND processing to be done ? */ + if ((pData->eImagetype == mng_it_mng) && (!pData->pCurraniobj)) + iRetcode = process_display_mend (pData); + + if (!pData->pCurraniobj) /* refresh after last image ? */ + pData->bNeedrefresh = MNG_TRUE; + } + } /* until error or a break or no more objects */ + while ((!iRetcode) && (pData->pCurraniobj) && + (!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bFreezing)); + + if (iRetcode) /* on error bail out */ + return iRetcode; + /* refresh needed ? */ + if ((!pData->bTimerset) && (pData->bNeedrefresh)) + { + iRetcode = display_progressive_refresh (pData, 1); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + /* timer break ? */ + if ((pData->bTimerset) && (!pData->iBreakpoint)) + pData->iBreakpoint = 99; + else + if (!pData->bTimerset) + pData->iBreakpoint = 0; /* reset if no timer break */ + + if ((!pData->bTimerset) && (!pData->pCurraniobj)) + pData->bRunning = MNG_FALSE; /* all done now ! */ + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ +/* * * */ +/* * Chunk display processing routines * */ +/* * * */ +/* ************************************************************************** */ + +mng_retcode process_display_ihdr (mng_datap pData) +{ /* address the current "object" if any */ + mng_imagep pImage = (mng_imagep)pData->pCurrentobj; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IHDR, MNG_LC_START) +#endif + + if (!pData->bHasDHDR) + { + pData->fInitrowproc = MNG_NULL; /* do nothing by default */ + pData->fDisplayrow = MNG_NULL; + pData->fCorrectrow = MNG_NULL; + pData->fStorerow = MNG_NULL; + pData->fProcessrow = MNG_NULL; + pData->fDifferrow = MNG_NULL; + pData->pStoreobj = MNG_NULL; + } + + if (!pData->iBreakpoint) /* not previously broken ? */ + { + mng_retcode iRetcode = MNG_NOERROR; + + if (pData->bHasDHDR) /* is a delta-image ? */ + { + if (pData->iDeltatype == MNG_DELTATYPE_REPLACE) + iRetcode = reset_object_details (pData, (mng_imagep)pData->pDeltaImage, + pData->iDatawidth, pData->iDataheight, + pData->iBitdepth, pData->iColortype, + pData->iCompression, pData->iFilter, + pData->iInterlace, MNG_TRUE); + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) ) + { + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iPixelsampledepth = pData->iBitdepth; + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iBitdepth; + } + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) ) + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iBitdepth; + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) ) + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iPixelsampledepth = pData->iBitdepth; + + /* process immediatly if bitdepth & colortype are equal */ + pData->bDeltaimmediate = + (mng_bool)((pData->iBitdepth == ((mng_imagep)pData->pDeltaImage)->pImgbuf->iBitdepth ) && + (pData->iColortype == ((mng_imagep)pData->pDeltaImage)->pImgbuf->iColortype) ); + } + else + { + if (pImage) /* update object buffer ? */ + iRetcode = reset_object_details (pData, pImage, + pData->iDatawidth, pData->iDataheight, + pData->iBitdepth, pData->iColortype, + pData->iCompression, pData->iFilter, + pData->iInterlace, MNG_TRUE); + else + iRetcode = reset_object_details (pData, (mng_imagep)pData->pObjzero, + pData->iDatawidth, pData->iDataheight, + pData->iBitdepth, pData->iColortype, + pData->iCompression, pData->iFilter, + pData->iInterlace, MNG_TRUE); + } + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + + if (!pData->bHasDHDR) + { + if (pImage) /* real object ? */ + pData->pStoreobj = pImage; /* tell the row routines */ + else /* otherwise use object 0 */ + pData->pStoreobj = pData->pObjzero; + /* display "on-the-fly" ? */ + if ( (((mng_imagep)pData->pStoreobj)->iMAGN_MethodX == 0) && + (((mng_imagep)pData->pStoreobj)->iMAGN_MethodY == 0) && + ( (pData->eImagetype == mng_it_png ) || + (((mng_imagep)pData->pStoreobj)->bVisible) ) ) + { + next_layer (pData); /* that's a new layer then ! */ + + if (pData->bTimerset) /* timer break ? */ + pData->iBreakpoint = 2; + else + { + pData->iBreakpoint = 0; + /* anything to display ? */ + if ((pData->iDestr > pData->iDestl) && (pData->iDestb > pData->iDestt)) + set_display_routine (pData); /* then determine display routine */ + } + } + } + + if (!pData->bTimerset) /* no timer break ? */ + { + switch (pData->iColortype) /* determine row initialization routine */ + { + case 0 : { /* gray */ + switch (pData->iBitdepth) + { + case 1 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g1_ni; + else + pData->fInitrowproc = (mng_fptr)init_g1_i; + + break; + } + case 2 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g2_ni; + else + pData->fInitrowproc = (mng_fptr)init_g2_i; + + break; + } + case 4 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g4_ni; + else + pData->fInitrowproc = (mng_fptr)init_g4_i; + + break; + } + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g8_ni; + else + pData->fInitrowproc = (mng_fptr)init_g8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g16_ni; + else + pData->fInitrowproc = (mng_fptr)init_g16_i; + + break; + } + } + + break; + } + case 2 : { /* rgb */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgb8_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgb8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgb16_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgb16_i; + + break; + } + } + + break; + } + case 3 : { /* indexed */ + switch (pData->iBitdepth) + { + case 1 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx1_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx1_i; + + break; + } + case 2 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx2_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx2_i; + + break; + } + case 4 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx4_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx4_i; + + break; + } + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx8_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx8_i; + + break; + } + } + + break; + } + case 4 : { /* gray+alpha */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_ga8_ni; + else + pData->fInitrowproc = (mng_fptr)init_ga8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_ga16_ni; + else + pData->fInitrowproc = (mng_fptr)init_ga16_i; + + break; + } + } + + break; + } + case 6 : { /* rgb+alpha */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgba8_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgba8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgba16_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgba16_i; + + break; + } + } + + break; + } + } + + pData->iFilterofs = 0; /* determine filter characteristics */ + pData->iLevel0 = 0; /* default levels */ + pData->iLevel1 = 0; + pData->iLevel2 = 0; + pData->iLevel3 = 0; + /* leveling & differing ? */ +/* if (pData->iFilter & 0x40) + { + switch (pData->iColortype) + { + case 0 : { + if (pData->iBitdepth <= 8) + pData->iFilterofs = 1; + else + pData->iFilterofs = 2; + + break; + } + case 2 : { + if (pData->iBitdepth <= 8) + pData->iFilterofs = 3; + else + pData->iFilterofs = 6; + + break; + } + case 3 : { + pData->iFilterofs = 1; + break; + } + case 4 : { + if (pData->iBitdepth <= 8) + pData->iFilterofs = 2; + else + pData->iFilterofs = 4; + + break; + } + case 6 : { + if (pData->iBitdepth <= 8) + pData->iPixelofs = 5; + else + pData->iFilterofs = 8; + + break; + } + } + } */ + /* no adaptive filtering ? */ +/* if (pData->iFilter & 0x01) + pData->iPixelofs = pData->iFilterofs; + else */ + pData->iPixelofs = pData->iFilterofs + 1; + + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IHDR, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_idat (mng_datap pData, + mng_uint32 iRawlen, + mng_uint8p pRawdata) +{ + mng_retcode iRetcode = MNG_NOERROR; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IDAT, MNG_LC_START) +#endif + + if (pData->bRestorebkgd) /* need to restore the background ? */ + { + pData->bRestorebkgd = MNG_FALSE; + iRetcode = load_bkgdlayer (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + + if ((pData->bDisplaying) && (pData->bRunning)) + pData->iLayerseq++; /* and it counts as a layer then ! */ + } + + if (pData->fInitrowproc) /* need to initialize row processing? */ + { + iRetcode = ((mng_initrowproc)pData->fInitrowproc) (pData); + pData->fInitrowproc = MNG_NULL; /* only call this once !!! */ + } + + if ((!iRetcode) && (!pData->bInflating)) + /* initialize inflate */ + iRetcode = mngzlib_inflateinit (pData); + + if (!iRetcode) /* all ok? then inflate, my man */ + iRetcode = mngzlib_inflaterows (pData, iRawlen, pRawdata); + + if (iRetcode) /* on error bail out */ + return iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IDAT, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_iend (mng_datap pData) +{ + mng_retcode iRetcode, iRetcode2; + mng_bool bDodisplay = MNG_FALSE; + mng_bool bMagnify = MNG_FALSE; + mng_bool bCleanup = (mng_bool)(pData->iBreakpoint != 0); + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IEND, MNG_LC_START) +#endif + +#ifdef MNG_INCLUDE_JNG /* progressive+alpha JNG can be displayed now */ + if ( (pData->bHasJHDR ) && + ( (pData->bJPEGprogressive) || (pData->bJPEGprogressive2)) && + ( (pData->eImagetype == mng_it_jng ) || + (((mng_imagep)pData->pStoreobj)->bVisible) ) && + ( (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) || + (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) ) ) + bDodisplay = MNG_TRUE; +#endif + + if ( (pData->pStoreobj) && /* on-the-fly magnification ? */ + ( (((mng_imagep)pData->pStoreobj)->iMAGN_MethodX) || + (((mng_imagep)pData->pStoreobj)->iMAGN_MethodY) ) ) + bMagnify = MNG_TRUE; + + if ((pData->bHasBASI) || /* was it a BASI stream */ + (bDodisplay) || /* or should we display the JNG */ + (bMagnify) || /* or should we magnify it */ + /* or did we get broken here last time ? */ + ((pData->iBreakpoint) && (pData->iBreakpoint != 8))) + { + mng_imagep pImage = (mng_imagep)pData->pCurrentobj; + + if (!pImage) /* or was it object 0 ? */ + pImage = (mng_imagep)pData->pObjzero; + /* display it now then ? */ + if ((pImage->bVisible) && (pImage->bViewable)) + { /* ok, so do it */ + iRetcode = display_image (pData, pImage, bDodisplay); + + if (iRetcode) /* on error bail out */ + return iRetcode; + + if (pData->bTimerset) /* timer break ? */ + pData->iBreakpoint = 6; + } + } + else + if ((pData->bHasDHDR) || /* was it a DHDR stream */ + (pData->iBreakpoint == 8)) /* or did we get broken here last time ? */ + { + mng_imagep pImage = (mng_imagep)pData->pDeltaImage; + + if (!pData->iBreakpoint) + { /* perform the delta operations needed */ + iRetcode = execute_delta_image (pData, pImage, (mng_imagep)pData->pObjzero); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + /* display it now then ? */ + if ((pImage->bVisible) && (pImage->bViewable)) + { /* ok, so do it */ + iRetcode = display_image (pData, pImage, MNG_FALSE); + + if (iRetcode) /* on error bail out */ + return iRetcode; + + if (pData->bTimerset) /* timer break ? */ + pData->iBreakpoint = 8; + } + } + + if (!pData->bTimerset) /* can we continue ? */ + { + pData->iBreakpoint = 0; /* clear this flag now ! */ + /* cleanup object 0 */ + reset_object_details (pData, (mng_imagep)pData->pObjzero, + 0, 0, 0, 0, 0, 0, 0, MNG_TRUE); + + if (pData->bInflating) /* if we've been inflating */ + { /* cleanup row-processing, */ + iRetcode = cleanup_rowproc (pData); + /* also cleanup inflate! */ + iRetcode2 = mngzlib_inflatefree (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + if (iRetcode2) + return iRetcode2; + } + +#ifdef MNG_INCLUDE_JNG + if (pData->bJPEGdecompress) /* if we've been decompressing JDAT */ + { /* cleanup row-processing, */ + iRetcode = cleanup_rowproc (pData); + /* also cleanup decompress! */ + iRetcode2 = mngjpeg_decompressfree (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + if (iRetcode2) + return iRetcode2; + } + + if (pData->bJPEGdecompress2) /* if we've been decompressing JDAA */ + { /* cleanup row-processing, */ + iRetcode = cleanup_rowproc (pData); + /* also cleanup decompress! */ + iRetcode2 = mngjpeg_decompressfree2 (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + if (iRetcode2) + return iRetcode2; + } +#endif + + if (bCleanup) /* if we got broken last time we need to cleanup */ + { + pData->bHasIHDR = MNG_FALSE; /* IEND signals the end for most ... */ + pData->bHasBASI = MNG_FALSE; + pData->bHasDHDR = MNG_FALSE; +#ifdef MNG_INCLUDE_JNG + pData->bHasJHDR = MNG_FALSE; + pData->bHasJSEP = MNG_FALSE; + pData->bHasJDAA = MNG_FALSE; + pData->bHasJDAT = MNG_FALSE; +#endif + pData->bHasPLTE = MNG_FALSE; + pData->bHasTRNS = MNG_FALSE; + pData->bHasGAMA = MNG_FALSE; + pData->bHasCHRM = MNG_FALSE; + pData->bHasSRGB = MNG_FALSE; + pData->bHasICCP = MNG_FALSE; + pData->bHasBKGD = MNG_FALSE; + pData->bHasIDAT = MNG_FALSE; + } + /* if the image was displayed on the fly, */ + /* we'll have to make the app refresh */ + if ((pData->eImagetype != mng_it_mng) && (pData->fDisplayrow)) + pData->bNeedrefresh = MNG_TRUE; + + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IEND, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_mend (mng_datap pData) +{ +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MEND, MNG_LC_START) +#endif + /* TERM processed ? */ + if ((pData->bDisplaying) && (pData->bRunning) && + (pData->bHasTERM) && (pData->pTermaniobj)) + { + mng_retcode iRetcode; + mng_ani_termp pTERM; + /* get the right animation object ! */ + pTERM = (mng_ani_termp)pData->pTermaniobj; + + pData->iIterations++; /* increase iteration count */ + + switch (pTERM->iTermaction) /* determine what to do! */ + { + case 0 : { /* show last frame indefinitly */ + break; /* piece of cake, that is... */ + } + + case 1 : { /* cease displaying anything */ + pData->bFrameclipping = MNG_FALSE; + load_bkgdlayer (pData); + break; + } + + case 2 : { /* show first image after TERM */ + + /* TODO: something */ + + break; + } + + case 3 : { /* repeat */ + if ((pTERM->iItermax) && (pTERM->iItermax < 0x7FFFFFFF)) + pTERM->iItermax--; + + if (pTERM->iItermax) /* go back to TERM ? */ + { /* restore to initial or SAVE state */ + iRetcode = restore_state (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + /* notify the app ? */ + if (pData->fProcessmend) + { + mng_bool bOke = pData->fProcessmend ((mng_handle)pData, + pData->iIterations, + pTERM->iItermax); + if (!bOke) /* stop here and now ? */ + break; + } + /* restart from TERM chunk */ + pData->pCurraniobj = pTERM; + + if (pTERM->iDelay) /* set the delay (?) */ + { + mng_uint32 iWaitfor = 1000; + /* what are we aiming for */ + if (pData->iTicks) + { /* honor speed modifier */ + switch (pData->iSpeed) + { + case mng_st_fast : + { + iWaitfor = (mng_uint32)(( 500 * pTERM->iDelay) / pData->iTicks); + break; + } + case mng_st_slow : + { + iWaitfor = (mng_uint32)((3000 * pTERM->iDelay) / pData->iTicks); + break; + } + case mng_st_slowest : + { + iWaitfor = (mng_uint32)((8000 * pTERM->iDelay) / pData->iTicks); + break; + } + default : + { + iWaitfor = (mng_uint32)((1000 * pTERM->iDelay) / pData->iTicks); + } + } + } + + iRetcode = display_progressive_refresh (pData, iWaitfor); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + } + else + { + switch (pTERM->iIteraction) + { + case 0 : { /* show last frame indefinitly */ + break; /* piece of cake, that is... */ + } + + case 1 : { /* cease displaying anything */ + pData->bFrameclipping = MNG_FALSE; + load_bkgdlayer (pData); + break; + } + + case 2 : { /* show first image after TERM */ + + /* TODO: something */ + + break; + } + + } + } + + break; + } + + } + } + + if (!pData->pCurraniobj) /* always let the app refresh at the end ! */ + pData->bNeedrefresh = MNG_TRUE; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MEND, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_defi (mng_datap pData) +{ + mng_imagep pImage; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DEFI, MNG_LC_START) +#endif + + if (!pData->iDEFIobjectid) /* object id=0 ? */ + { + pImage = (mng_imagep)pData->pObjzero; + + if (pData->bDEFIhasdonotshow) + pImage->bVisible = (mng_bool)(pData->iDEFIdonotshow == 0); + + if (pData->bDEFIhasloca) + { + pImage->iPosx = pData->iDEFIlocax; + pImage->iPosy = pData->iDEFIlocay; + } + + if (pData->bDEFIhasclip) + { + pImage->bClipped = pData->bDEFIhasclip; + pImage->iClipl = pData->iDEFIclipl; + pImage->iClipr = pData->iDEFIclipr; + pImage->iClipt = pData->iDEFIclipt; + pImage->iClipb = pData->iDEFIclipb; + } + + pData->pCurrentobj = 0; /* not a real object ! */ + } + else + { /* already exists ? */ + pImage = (mng_imagep)find_imageobject (pData, pData->iDEFIobjectid); + + if (!pImage) /* if not; create new */ + { + mng_retcode iRetcode = create_imageobject (pData, pData->iDEFIobjectid, + (mng_bool)(pData->iDEFIconcrete == 1), + (mng_bool)(pData->iDEFIdonotshow == 0), + MNG_FALSE, 0, 0, 0, 0, 0, 0, 0, + pData->iDEFIlocax, pData->iDEFIlocay, + pData->bDEFIhasclip, + pData->iDEFIclipl, pData->iDEFIclipr, + pData->iDEFIclipt, pData->iDEFIclipb, + &pImage); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + else + { /* exists; then set new info */ + if (pData->bDEFIhasdonotshow) + pImage->bVisible = (mng_bool)(pData->iDEFIdonotshow == 0); + + pImage->bViewable = MNG_FALSE; + + if (pData->bDEFIhasloca) + { + pImage->iPosx = pData->iDEFIlocax; + pImage->iPosy = pData->iDEFIlocay; + } + + if (pData->bDEFIhasclip) + { + pImage->bClipped = pData->bDEFIhasclip; + pImage->iClipl = pData->iDEFIclipl; + pImage->iClipr = pData->iDEFIclipr; + pImage->iClipt = pData->iDEFIclipt; + pImage->iClipb = pData->iDEFIclipb; + } + + if (pData->bDEFIhasconcrete) + pImage->pImgbuf->bConcrete = (mng_bool)(pData->iDEFIconcrete == 1); + } + + pData->pCurrentobj = pImage; /* others may want to know this */ + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DEFI, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_basi (mng_datap pData, + mng_uint16 iRed, + mng_uint16 iGreen, + mng_uint16 iBlue, + mng_bool bHasalpha, + mng_uint16 iAlpha, + mng_uint8 iViewable) +{ /* address the current "object" if any */ + mng_imagep pImage = (mng_imagep)pData->pCurrentobj; + mng_uint8p pWork; + mng_uint32 iX; + mng_imagedatap pBuf; + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_BASI, MNG_LC_START) +#endif + + if (!pImage) /* or is it an "on-the-fly" image ? */ + pImage = (mng_imagep)pData->pObjzero; + /* address the object-buffer */ + pBuf = pImage->pImgbuf; + + pData->fDisplayrow = MNG_NULL; /* do nothing by default */ + pData->fCorrectrow = MNG_NULL; + pData->fStorerow = MNG_NULL; + pData->fProcessrow = MNG_NULL; + /* set parms now that they're known */ + iRetcode = reset_object_details (pData, pImage, pData->iDatawidth, + pData->iDataheight, pData->iBitdepth, + pData->iColortype, pData->iCompression, + pData->iFilter, pData->iInterlace, MNG_FALSE); + if (iRetcode) /* on error bail out */ + return iRetcode; + /* save the viewable flag */ + pImage->bViewable = (mng_bool)(iViewable == 1); + pBuf->bViewable = pImage->bViewable; + pData->pStoreobj = pImage; /* let row-routines know which object */ + + pWork = pBuf->pImgdata; /* fill the object-buffer with the specified + "color" sample */ + switch (pData->iColortype) /* depending on color_type & bit_depth */ + { + case 0 : { /* gray */ + if (pData->iBitdepth == 16) + { + for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++) + { + mng_put_uint16 (pWork, iRed); + pWork += 2; + } + } + else + { + for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++) + { + *pWork = (mng_uint8)iRed; + pWork++; + } + } + /* force tRNS ? */ + if ((bHasalpha) && (!iAlpha)) + { + pBuf->bHasTRNS = MNG_TRUE; + pBuf->iTRNSgray = iRed; + } + + break; + } + + case 2 : { /* rgb */ + if (pData->iBitdepth == 16) + { + for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++) + { + mng_put_uint16 (pWork, iRed ); + mng_put_uint16 (pWork+2, iGreen); + mng_put_uint16 (pWork+4, iBlue ); + pWork += 6; + } + } + else + { + for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++) + { + *pWork = (mng_uint8)iRed; + *(pWork+1) = (mng_uint8)iGreen; + *(pWork+2) = (mng_uint8)iBlue; + pWork += 3; + } + } + /* force tRNS ? */ + if ((bHasalpha) && (!iAlpha)) + { + pBuf->bHasTRNS = MNG_TRUE; + pBuf->iTRNSred = iRed; + pBuf->iTRNSgreen = iGreen; + pBuf->iTRNSblue = iBlue; + } + + break; + } + + case 3 : { /* indexed */ + pBuf->bHasPLTE = MNG_TRUE; + + switch (pData->iBitdepth) + { + case 1 : { pBuf->iPLTEcount = 2; break; } + case 2 : { pBuf->iPLTEcount = 4; break; } + case 4 : { pBuf->iPLTEcount = 16; break; } + case 8 : { pBuf->iPLTEcount = 256; break; } + default : { pBuf->iPLTEcount = 1; break; } + } + + pBuf->aPLTEentries [0].iRed = (mng_uint8)iRed; + pBuf->aPLTEentries [0].iGreen = (mng_uint8)iGreen; + pBuf->aPLTEentries [0].iBlue = (mng_uint8)iBlue; + + for (iX = 1; iX < pBuf->iPLTEcount; iX++) + { + pBuf->aPLTEentries [iX].iRed = 0; + pBuf->aPLTEentries [iX].iGreen = 0; + pBuf->aPLTEentries [iX].iBlue = 0; + } + /* force tRNS ? */ + if ((bHasalpha) && (iAlpha < 255)) + { + pBuf->bHasTRNS = MNG_TRUE; + pBuf->iTRNScount = 1; + pBuf->aTRNSentries [0] = (mng_uint8)iAlpha; + } + + break; + } + + case 4 : { /* gray+alpha */ + if (pData->iBitdepth == 16) + { + for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++) + { + mng_put_uint16 (pWork, iRed); + mng_put_uint16 (pWork+2, iAlpha); + pWork += 4; + } + } + else + { + for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++) + { + *pWork = (mng_uint8)iRed; + *(pWork+1) = (mng_uint8)iAlpha; + pWork += 2; + } + } + + break; + } + + case 6 : { /* rgb+alpha */ + if (pData->iBitdepth == 16) + { + for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++) + { + mng_put_uint16 (pWork, iRed); + mng_put_uint16 (pWork+2, iGreen); + mng_put_uint16 (pWork+4, iBlue); + mng_put_uint16 (pWork+6, iAlpha); + pWork += 8; + } + } + else + { + for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++) + { + *pWork = (mng_uint8)iRed; + *(pWork+1) = (mng_uint8)iGreen; + *(pWork+2) = (mng_uint8)iBlue; + *(pWork+3) = (mng_uint8)iAlpha; + pWork += 4; + } + } + + break; + } + + } + + switch (pData->iColortype) /* determine row initialization routine */ + { /* just to accomodate IDAT if it arrives */ + case 0 : { /* gray */ + switch (pData->iBitdepth) + { + case 1 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g1_ni; + else + pData->fInitrowproc = (mng_fptr)init_g1_i; + + break; + } + case 2 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g2_ni; + else + pData->fInitrowproc = (mng_fptr)init_g2_i; + + break; + } + case 4 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g4_ni; + else + pData->fInitrowproc = (mng_fptr)init_g4_i; + + break; + } + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g8_ni; + else + pData->fInitrowproc = (mng_fptr)init_g8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g16_ni; + else + pData->fInitrowproc = (mng_fptr)init_g16_i; + + break; + } + } + + break; + } + case 2 : { /* rgb */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgb8_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgb8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgb16_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgb16_i; + + break; + } + } + + break; + } + case 3 : { /* indexed */ + switch (pData->iBitdepth) + { + case 1 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx1_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx1_i; + + break; + } + case 2 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx2_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx2_i; + + break; + } + case 4 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx4_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx4_i; + + break; + } + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx8_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx8_i; + + break; + } + } + + break; + } + case 4 : { /* gray+alpha */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_ga8_ni; + else + pData->fInitrowproc = (mng_fptr)init_ga8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_ga16_ni; + else + pData->fInitrowproc = (mng_fptr)init_ga16_i; + + break; + } + } + + break; + } + case 6 : { /* rgb+alpha */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgba8_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgba8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgba16_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgba16_i; + + break; + } + } + + break; + } + } + + pData->iFilterofs = 0; /* determine filter characteristics */ + pData->iLevel0 = 0; /* default levels */ + pData->iLevel1 = 0; + pData->iLevel2 = 0; + pData->iLevel3 = 0; + /* leveling & differing ? */ +/* if (pData->iFilter & 0x40) + { + switch (pData->iColortype) + { + case 0 : { + if (pData->iBitdepth <= 8) + pData->iFilterofs = 1; + else + pData->iFilterofs = 2; + + break; + } + case 2 : { + if (pData->iBitdepth <= 8) + pData->iFilterofs = 3; + else + pData->iFilterofs = 6; + + break; + } + case 3 : { + pData->iFilterofs = 1; + break; + } + case 4 : { + if (pData->iBitdepth <= 8) + pData->iFilterofs = 2; + else + pData->iFilterofs = 4; + + break; + } + case 6 : { + if (pData->iBitdepth <= 8) + pData->iPixelofs = 5; + else + pData->iFilterofs = 8; + + break; + } + } + } */ + /* no adaptive filtering ? */ +/* if (pData->iFilter & 0x01) + pData->iPixelofs = pData->iFilterofs; + else */ + pData->iPixelofs = pData->iFilterofs + 1; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_BASI, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_clon (mng_datap pData, + mng_uint16 iSourceid, + mng_uint16 iCloneid, + mng_uint8 iClonetype, + mng_bool bHasdonotshow, + mng_uint8 iDonotshow, + mng_uint8 iConcrete, + mng_bool bHasloca, + mng_uint8 iLocationtype, + mng_int32 iLocationx, + mng_int32 iLocationy) +{ + mng_imagep pSource, pClone; + mng_bool bVisible, bAbstract; + mng_retcode iRetcode = MNG_NOERROR; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLON, MNG_LC_START) +#endif + /* locate the source object first */ + pSource = find_imageobject (pData, iSourceid); + /* check if the clone exists */ + pClone = find_imageobject (pData, iCloneid); + + if (!pSource) /* source must exist ! */ + MNG_ERROR (pData, MNG_OBJECTUNKNOWN); + + if (pClone) /* clone must not exist ! */ + MNG_ERROR (pData, MNG_OBJECTEXISTS); + + if (bHasdonotshow) /* DoNotShow flag filled ? */ + bVisible = (mng_bool)(iDonotshow == 0); + else + bVisible = pSource->bVisible; + + bAbstract = (mng_bool)(iConcrete == 1); + + switch (iClonetype) /* determine action to take */ + { + case 0 : { /* full clone */ + iRetcode = clone_imageobject (pData, iCloneid, MNG_FALSE, + bVisible, bAbstract, bHasloca, + iLocationtype, iLocationx, iLocationy, + pSource, &pClone); + break; + } + + case 1 : { /* partial clone */ + iRetcode = clone_imageobject (pData, iCloneid, MNG_TRUE, + bVisible, bAbstract, bHasloca, + iLocationtype, iLocationx, iLocationy, + pSource, &pClone); + break; + } + + case 2 : { /* renumber object */ + iRetcode = renum_imageobject (pData, pSource, iCloneid, + bVisible, bAbstract, bHasloca, + iLocationtype, iLocationx, iLocationy); + pClone = pSource; + break; + } + + } + + if (iRetcode) /* on error bail out */ + return iRetcode; + + /* display on the fly ? */ + if ((pClone->bViewable) && (pClone->bVisible)) + { + pData->pLastclone = pClone; /* remember in case of timer break ! */ + /* display it */ + display_image (pData, pClone, MNG_FALSE); + + if (pData->bTimerset) /* timer break ? */ + pData->iBreakpoint = 5; + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLON, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_clon2 (mng_datap pData) +{ +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLON, MNG_LC_START) +#endif + /* only called after timer break ! */ + display_image (pData, (mng_imagep)pData->pLastclone, MNG_FALSE); + pData->iBreakpoint = 0; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLON, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_disc (mng_datap pData, + mng_uint32 iCount, + mng_uint16p pIds) +{ + mng_uint32 iX; + mng_imagep pImage; + mng_uint32 iRetcode; +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DISC, MNG_LC_START) +#endif + + if (iCount) /* specific list ? */ + { + mng_uint16p pWork = pIds; + + for (iX = 0; iX < iCount; iX++) /* iterate the list */ + { + pImage = find_imageobject (pData, *pWork++); + + if (pImage) /* found the object ? */ + { /* then drop it */ + iRetcode = free_imageobject (pData, pImage); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + } + } + else /* empty: drop all un-frozen objects */ + { + mng_imagep pNext = (mng_imagep)pData->pFirstimgobj; + + while (pNext) /* any left ? */ + { + pImage = pNext; + pNext = pImage->sHeader.pNext; + + if (!pImage->bFrozen) /* not frozen ? */ + { /* then drop it */ + iRetcode = free_imageobject (pData, pImage); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + } + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DISC, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_fram (mng_datap pData, + mng_uint8 iFramemode, + mng_uint8 iChangedelay, + mng_uint32 iDelay, + mng_uint8 iChangetimeout, + mng_uint32 iTimeout, + mng_uint8 iChangeclipping, + mng_uint8 iCliptype, + mng_int32 iClipl, + mng_int32 iClipr, + mng_int32 iClipt, + mng_int32 iClipb) +{ + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_FRAM, MNG_LC_START) +#endif + /* advance a frame then */ + iRetcode = next_frame (pData, iFramemode, iChangedelay, iDelay, + iChangetimeout, iTimeout, iChangeclipping, + iCliptype, iClipl, iClipr, iClipt, iClipb); + + if (pData->bTimerset) /* timer break ? */ + pData->iBreakpoint = 1; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_FRAM, MNG_LC_END) +#endif + + return iRetcode; +} + +/* ************************************************************************** */ + +mng_retcode process_display_fram2 (mng_datap pData) +{ + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_FRAM, MNG_LC_START) +#endif + /* again; after the break */ + iRetcode = next_frame (pData, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + pData->iBreakpoint = 0; /* not again! */ + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_FRAM, MNG_LC_END) +#endif + + return iRetcode; +} + +/* ************************************************************************** */ + +mng_retcode process_display_move (mng_datap pData, + mng_uint16 iFromid, + mng_uint16 iToid, + mng_uint8 iMovetype, + mng_int32 iMovex, + mng_int32 iMovey) +{ + mng_uint16 iX; + mng_imagep pImage; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MOVE, MNG_LC_START) +#endif + /* iterate the list */ + for (iX = iFromid; iX <= iToid; iX++) + { + if (!iX) /* object id=0 ? */ + pImage = (mng_imagep)pData->pObjzero; + else + pImage = find_imageobject (pData, iX); + + if (pImage) /* object exists ? */ + { + switch (iMovetype) + { + case 0 : { /* absolute */ + pImage->iPosx = iMovex; + pImage->iPosy = iMovey; + break; + } + case 1 : { /* relative */ + pImage->iPosx = pImage->iPosx + iMovex; + pImage->iPosy = pImage->iPosy + iMovey; + break; + } + } + } + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MOVE, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_clip (mng_datap pData, + mng_uint16 iFromid, + mng_uint16 iToid, + mng_uint8 iCliptype, + mng_int32 iClipl, + mng_int32 iClipr, + mng_int32 iClipt, + mng_int32 iClipb) +{ + mng_uint16 iX; + mng_imagep pImage; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLIP, MNG_LC_START) +#endif + /* iterate the list */ + for (iX = iFromid; iX <= iToid; iX++) + { + if (!iX) /* object id=0 ? */ + pImage = (mng_imagep)pData->pObjzero; + else + pImage = find_imageobject (pData, iX); + + if (pImage) /* object exists ? */ + { + switch (iCliptype) + { + case 0 : { /* absolute */ + pImage->bClipped = MNG_TRUE; + pImage->iClipl = iClipl; + pImage->iClipr = iClipr; + pImage->iClipt = iClipt; + pImage->iClipb = iClipb; + break; + } + case 1 : { /* relative */ + pImage->bClipped = MNG_TRUE; + pImage->iClipl = pImage->iClipl + iClipl; + pImage->iClipr = pImage->iClipr + iClipr; + pImage->iClipt = pImage->iClipt + iClipt; + pImage->iClipb = pImage->iClipb + iClipb; + break; + } + } + } + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLIP, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_show (mng_datap pData) +{ + mng_int16 iX, iS, iFrom, iTo; + mng_imagep pImage; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SHOW, MNG_LC_START) +#endif + + /* TODO: optimization for the cases where "abs (iTo - iFrom)" is rather high; + especially where ((iFrom==1) && (iTo==65535)); eg. an empty SHOW !!! */ + + if (pData->iBreakpoint == 3) /* previously broken during cycle-mode ? */ + { + pImage = find_imageobject (pData, pData->iSHOWnextid); + + if (pImage) /* still there ? */ + display_image (pData, pImage, MNG_FALSE); + + pData->iBreakpoint = 0; /* let's not go through this again! */ + } + else + { + if (pData->iBreakpoint) /* previously broken at other point ? */ + { /* restore last parms */ + iFrom = (mng_int16)pData->iSHOWfromid; + iTo = (mng_int16)pData->iSHOWtoid; + iX = (mng_int16)pData->iSHOWnextid; + iS = (mng_int16)pData->iSHOWskip; + } + else + { /* regular sequence ? */ + if (pData->iSHOWtoid >= pData->iSHOWfromid) + iS = 1; + else /* reverse sequence ! */ + iS = -1; + + iFrom = (mng_int16)pData->iSHOWfromid; + iTo = (mng_int16)pData->iSHOWtoid; + iX = iFrom; + + pData->iSHOWfromid = (mng_uint16)iFrom; + pData->iSHOWtoid = (mng_uint16)iTo; + pData->iSHOWskip = iS; + } + /* cycle mode ? */ + if ((pData->iSHOWmode == 6) || (pData->iSHOWmode == 7)) + { + mng_uint16 iTrigger = 0; + mng_uint16 iFound = 0; + mng_uint16 iPass = 0; + mng_imagep pFound = 0; + + do + { + iPass++; /* lets prevent endless loops when there + are no potential candidates in the list! */ + + if (iS > 0) /* forward ? */ + { + for (iX = iFrom; iX <= iTo; iX += iS) + { + pImage = find_imageobject (pData, (mng_uint16)iX); + + if (pImage) /* object exists ? */ + { + if (iFound) /* already found a candidate ? */ + pImage->bVisible = MNG_FALSE; + else + if (iTrigger) /* found the trigger ? */ + { + pImage->bVisible = MNG_TRUE; + iFound = iX; + pFound = pImage; + } + else + if (pImage->bVisible) /* ok, this is the trigger */ + { + pImage->bVisible = MNG_FALSE; + iTrigger = iX; + } + } + } + } + else + { + for (iX = iFrom; iX >= iTo; iX += iS) + { + pImage = find_imageobject (pData, (mng_uint16)iX); + + if (pImage) /* object exists ? */ + { + if (iFound) /* already found a candidate ? */ + pImage->bVisible = MNG_FALSE; + else + if (iTrigger) /* found the trigger ? */ + { + pImage->bVisible = MNG_TRUE; + iFound = iX; + pFound = pImage; + } + else + if (pImage->bVisible) /* ok, this is the trigger */ + { + pImage->bVisible = MNG_FALSE; + iTrigger = iX; + } + } + } + } + + if (!iTrigger) /* did not find a trigger ? */ + iTrigger = 1; /* then fake it so the first image + gets nominated */ + } /* cycle back to beginning ? */ + while ((iPass < 2) && (iTrigger) && (!iFound)); + + pData->iBreakpoint = 0; /* just a sanity precaution */ + /* display it ? */ + if ((pData->iSHOWmode == 6) && (pFound)) + { + display_image (pData, pFound, MNG_FALSE); + + if (pData->bTimerset) /* timer set ? */ + { + pData->iBreakpoint = 3; + pData->iSHOWnextid = iFound; /* save it for after the break */ + } + } + } + else + { + do + { + pImage = find_imageobject (pData, iX); + + if (pImage) /* object exists ? */ + { + if (pData->iBreakpoint) /* did we get broken last time ? */ + { /* could only happen in the display routine */ + display_image (pData, pImage, MNG_FALSE); + pData->iBreakpoint = 0; /* only once inside this loop please ! */ + } + else + { + switch (pData->iSHOWmode) /* do what ? */ + { + case 0 : { + pImage->bVisible = MNG_TRUE; + display_image (pData, pImage, MNG_FALSE); + break; + } + case 1 : { + pImage->bVisible = MNG_FALSE; + break; + } + case 2 : { + if (pImage->bVisible) + display_image (pData, pImage, MNG_FALSE); + break; + } + case 3 : { + pImage->bVisible = MNG_TRUE; + break; + } + case 4 : { + pImage->bVisible = (mng_bool)(!pImage->bVisible); + if (pImage->bVisible) + display_image (pData, pImage, MNG_FALSE); + break; + } + case 5 : { + pImage->bVisible = (mng_bool)(!pImage->bVisible); + } + } + } + } + + if (!pData->bTimerset) /* next ? */ + iX += iS; + + } /* continue ? */ + while ((!pData->bTimerset) && (((iS > 0) && (iX <= iTo)) || + ((iS < 0) && (iX >= iTo)) )); + + if (pData->bTimerset) /* timer set ? */ + { + pData->iBreakpoint = 4; + pData->iSHOWnextid = iX; /* save for next time */ + } + else + pData->iBreakpoint = 0; + + } + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SHOW, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_save (mng_datap pData) +{ + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SAVE, MNG_LC_START) +#endif + + iRetcode = save_state (pData); /* save the current state */ + + if (iRetcode) /* on error bail out */ + return iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SAVE, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_seek (mng_datap pData) +{ + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SEEK, MNG_LC_START) +#endif + + iRetcode = restore_state (pData); /* restore the initial or SAVE state */ + + if (iRetcode) /* on error bail out */ + return iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SEEK, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +#ifdef MNG_INCLUDE_JNG +mng_retcode process_display_jhdr (mng_datap pData) +{ /* address the current "object" if any */ + mng_imagep pImage = (mng_imagep)pData->pCurrentobj; + mng_retcode iRetcode = MNG_NOERROR; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JHDR, MNG_LC_START) +#endif + + if (!pData->bHasDHDR) + { + pData->fInitrowproc = MNG_NULL; /* do nothing by default */ + pData->fDisplayrow = MNG_NULL; + pData->fCorrectrow = MNG_NULL; + pData->fStorerow = MNG_NULL; + pData->fProcessrow = MNG_NULL; + pData->fDifferrow = MNG_NULL; + pData->fStorerow2 = MNG_NULL; + pData->fStorerow3 = MNG_NULL; + + pData->pStoreobj = MNG_NULL; /* initialize important work-parms */ + + pData->iJPEGrow = 0; + pData->iJPEGalpharow = 0; + pData->iJPEGrgbrow = 0; + pData->iRowmax = 0; /* so init_rowproc does the right thing ! */ + } + + if (!pData->iBreakpoint) /* not previously broken ? */ + { + if (pData->bHasDHDR) /* delta-image ? */ + { + if (pData->iDeltatype == MNG_DELTATYPE_REPLACE) + { + iRetcode = reset_object_details (pData, (mng_imagep)pData->pDeltaImage, + pData->iDatawidth, pData->iDataheight, + pData->iJHDRimgbitdepth, pData->iJHDRcolortype, + pData->iJHDRalphacompression, pData->iJHDRalphafilter, + pData->iJHDRalphainterlace, MNG_TRUE); + + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphabitdepth = pData->iJHDRalphabitdepth; + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iJHDRcompression = pData->iJHDRimgcompression; + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iJHDRinterlace = pData->iJHDRimginterlace; + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth; + } + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) ) + { + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iPixelsampledepth = pData->iJHDRimgbitdepth; + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth; + } + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) ) + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth; + else + if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) || + (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) ) + ((mng_imagep)pData->pDeltaImage)->pImgbuf->iPixelsampledepth = pData->iJHDRimgbitdepth; + + } + else + { + if (pImage) /* update object buffer ? */ + { + iRetcode = reset_object_details (pData, pImage, + pData->iDatawidth, pData->iDataheight, + pData->iJHDRimgbitdepth, pData->iJHDRcolortype, + pData->iJHDRalphacompression, pData->iJHDRalphafilter, + pData->iJHDRalphainterlace, MNG_TRUE); + + pImage->pImgbuf->iAlphabitdepth = pData->iJHDRalphabitdepth; + pImage->pImgbuf->iJHDRcompression = pData->iJHDRimgcompression; + pImage->pImgbuf->iJHDRinterlace = pData->iJHDRimginterlace; + pImage->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth; + } + else /* update object 0 */ + { + iRetcode = reset_object_details (pData, (mng_imagep)pData->pObjzero, + pData->iDatawidth, pData->iDataheight, + pData->iJHDRimgbitdepth, pData->iJHDRcolortype, + pData->iJHDRalphacompression, pData->iJHDRalphafilter, + pData->iJHDRalphainterlace, MNG_TRUE); + + ((mng_imagep)pData->pObjzero)->pImgbuf->iAlphabitdepth = pData->iJHDRalphabitdepth; + ((mng_imagep)pData->pObjzero)->pImgbuf->iJHDRcompression = pData->iJHDRimgcompression; + ((mng_imagep)pData->pObjzero)->pImgbuf->iJHDRinterlace = pData->iJHDRimginterlace; + ((mng_imagep)pData->pObjzero)->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth; + } + } + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + + if (!pData->bHasDHDR) + { /* we're always storing a JPEG */ + if (pImage) /* real object ? */ + pData->pStoreobj = pImage; /* tell the row routines */ + else /* otherwise use object 0 */ + pData->pStoreobj = pData->pObjzero; + /* display "on-the-fly" ? */ + if ( (((mng_imagep)pData->pStoreobj)->iMAGN_MethodX == 0) && + (((mng_imagep)pData->pStoreobj)->iMAGN_MethodY == 0) && + ( (pData->eImagetype == mng_it_jng ) || + (((mng_imagep)pData->pStoreobj)->bVisible) ) ) + { + next_layer (pData); /* that's a new layer then ! */ + + if (pData->bTimerset) /* timer break ? */ + pData->iBreakpoint = 7; + else + { + pData->iBreakpoint = 0; + /* anything to display ? */ + if ((pData->iDestr > pData->iDestl) && (pData->iDestb > pData->iDestt)) + { + set_display_routine (pData); /* then determine display routine */ + /* display from the object we store in */ + pData->pRetrieveobj = pData->pStoreobj; + } + } + } + } + + if (!pData->bTimerset) /* no timer break ? */ + { /* default row initialization ! */ + pData->fInitrowproc = (mng_fptr)init_rowproc; + + if ((!pData->bHasDHDR) || (pData->iDeltatype == MNG_DELTATYPE_REPLACE)) + { /* 8-bit JPEG ? */ + if (pData->iJHDRimgbitdepth == 8) + { /* intermediate row is 8-bit deep */ + pData->bIsRGBA16 = MNG_FALSE; + pData->iRowsamples = pData->iDatawidth; + + switch (pData->iJHDRcolortype) /* determine pixel processing routines */ + { + case MNG_COLORTYPE_JPEGGRAY : + { + pData->fStorerow2 = (mng_fptr)store_jpeg_g8; + pData->fRetrieverow = (mng_fptr)retrieve_g8; + pData->bIsOpaque = MNG_TRUE; + break; + } + case MNG_COLORTYPE_JPEGCOLOR : + { + pData->fStorerow2 = (mng_fptr)store_jpeg_rgb8; + pData->fRetrieverow = (mng_fptr)retrieve_rgb8; + pData->bIsOpaque = MNG_TRUE; + break; + } + case MNG_COLORTYPE_JPEGGRAYA : + { + pData->fStorerow2 = (mng_fptr)store_jpeg_ga8; + pData->fRetrieverow = (mng_fptr)retrieve_ga8; + pData->bIsOpaque = MNG_FALSE; + break; + } + case MNG_COLORTYPE_JPEGCOLORA : + { + pData->fStorerow2 = (mng_fptr)store_jpeg_rgba8; + pData->fRetrieverow = (mng_fptr)retrieve_rgba8; + pData->bIsOpaque = MNG_FALSE; + break; + } + } + } + else + { + pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */ + + /* TODO: 12-bit JPEG */ + /* TODO: 8- + 12-bit JPEG (eg. type=20) */ + + } + /* possible IDAT alpha-channel ? */ + if (pData->iJHDRalphacompression == MNG_COMPRESSION_DEFLATE) + { + /* determine alpha processing routine */ + switch (pData->iJHDRalphabitdepth) + { + case 1 : { pData->fInitrowproc = (mng_fptr)init_jpeg_a1_ni; break; } + case 2 : { pData->fInitrowproc = (mng_fptr)init_jpeg_a2_ni; break; } + case 4 : { pData->fInitrowproc = (mng_fptr)init_jpeg_a4_ni; break; } + case 8 : { pData->fInitrowproc = (mng_fptr)init_jpeg_a8_ni; break; } + case 16 : { pData->fInitrowproc = (mng_fptr)init_jpeg_a16_ni; break; } + } + } + else /* possible JDAA alpha-channel ? */ + if (pData->iJHDRalphacompression == MNG_COMPRESSION_BASELINEJPEG) + { /* 8-bit JPEG ? */ + if (pData->iJHDRimgbitdepth == 8) + { + if (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA) + pData->fStorerow3 = (mng_fptr)store_jpeg_g8_alpha; + else + if (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) + pData->fStorerow3 = (mng_fptr)store_jpeg_rgb8_alpha; + } + else + { + /* TODO: 12-bit JPEG with 8-bit JDAA */ + } + } + /* initialize JPEG library */ + iRetcode = mngjpeg_initialize (pData); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + else + { /* must be alpha add/replace !! */ + if ((pData->iDeltatype != MNG_DELTATYPE_BLOCKALPHAADD ) && + (pData->iDeltatype != MNG_DELTATYPE_BLOCKALPHAREPLACE) ) + MNG_ERROR (pData, MNG_INVDELTATYPE) + /* determine alpha processing routine */ + switch (pData->iJHDRalphabitdepth) + { + case 1 : { pData->fInitrowproc = (mng_fptr)init_g1_ni; break; } + case 2 : { pData->fInitrowproc = (mng_fptr)init_g2_ni; break; } + case 4 : { pData->fInitrowproc = (mng_fptr)init_g4_ni; break; } + case 8 : { pData->fInitrowproc = (mng_fptr)init_g8_ni; break; } + case 16 : { pData->fInitrowproc = (mng_fptr)init_g16_ni; break; } + } + } + + pData->iFilterofs = 0; /* determine filter characteristics */ + pData->iLevel0 = 0; /* default levels */ + pData->iLevel1 = 0; + pData->iLevel2 = 0; + pData->iLevel3 = 0; + /* leveling & differing ? */ +/* if (pData->iJHDRalphafilter & 0x40) + { + if (pData->iJHDRalphabitdepth <= 8) + pData->iFilterofs = 1; + else + pData->iFilterofs = 2; + + } */ + /* no adaptive filtering ? */ +/* if (pData->iJHDRalphafilter & 0x01) + pData->iPixelofs = pData->iFilterofs; + else */ + pData->iPixelofs = pData->iFilterofs + 1; + + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JHDR, MNG_LC_END) +#endif + + return MNG_NOERROR; +} +#endif /* MNG_INCLUDE_JNG */ + +/* ************************************************************************** */ + +#ifdef MNG_INCLUDE_JNG +mng_retcode process_display_jdaa (mng_datap pData, + mng_uint32 iRawlen, + mng_uint8p pRawdata) +{ + mng_retcode iRetcode = MNG_NOERROR; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JDAA, MNG_LC_START) +#endif + + if (!pData->bJPEGdecompress2) /* if we're not decompressing already */ + { + if (pData->fInitrowproc) /* initialize row-processing? */ + { + iRetcode = ((mng_initrowproc)pData->fInitrowproc) (pData); + pData->fInitrowproc = MNG_NULL; /* only call this once !!! */ + } + + if (!iRetcode) /* initialize decompress */ + iRetcode = mngjpeg_decompressinit2 (pData); + } + + if (!iRetcode) /* all ok? then decompress, my man */ + iRetcode = mngjpeg_decompressdata2 (pData, iRawlen, pRawdata); + + if (iRetcode) + return iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JDAA, MNG_LC_END) +#endif + + return MNG_NOERROR; +} +#endif /* MNG_INCLUDE_JNG */ + +/* ************************************************************************** */ + +#ifdef MNG_INCLUDE_JNG +mng_retcode process_display_jdat (mng_datap pData, + mng_uint32 iRawlen, + mng_uint8p pRawdata) +{ + mng_retcode iRetcode = MNG_NOERROR; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JDAT, MNG_LC_START) +#endif + + if (pData->bRestorebkgd) /* need to restore the background ? */ + { + pData->bRestorebkgd = MNG_FALSE; + iRetcode = load_bkgdlayer (pData); + + if ((pData->bDisplaying) && (pData->bRunning)) + pData->iLayerseq++; /* and it counts as a layer then ! */ + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + + if (!pData->bJPEGdecompress) /* if we're not decompressing already */ + { + if (pData->fInitrowproc) /* initialize row-processing? */ + { + iRetcode = ((mng_initrowproc)pData->fInitrowproc) (pData); + pData->fInitrowproc = MNG_NULL; /* only call this once !!! */ + } + + if (!iRetcode) /* initialize decompress */ + iRetcode = mngjpeg_decompressinit (pData); + } + + if (!iRetcode) /* all ok? then decompress, my man */ + iRetcode = mngjpeg_decompressdata (pData, iRawlen, pRawdata); + + if (iRetcode) + return iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JDAT, MNG_LC_END) +#endif + + return MNG_NOERROR; +} +#endif /* MNG_INCLUDE_JNG */ + +/* ************************************************************************** */ + +mng_retcode process_display_dhdr (mng_datap pData, + mng_uint16 iObjectid, + mng_uint8 iImagetype, + mng_uint8 iDeltatype, + mng_uint32 iBlockwidth, + mng_uint32 iBlockheight, + mng_uint32 iBlockx, + mng_uint32 iBlocky) +{ + mng_imagep pImage; + mng_retcode iRetcode; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DHDR, MNG_LC_START) +#endif + + pData->fInitrowproc = MNG_NULL; /* do nothing by default */ + pData->fDisplayrow = MNG_NULL; + pData->fCorrectrow = MNG_NULL; + pData->fStorerow = MNG_NULL; + pData->fProcessrow = MNG_NULL; + pData->pStoreobj = MNG_NULL; + + pData->fDeltagetrow = MNG_NULL; + pData->fDeltaaddrow = MNG_NULL; + pData->fDeltareplacerow = MNG_NULL; + pData->fDeltaputrow = MNG_NULL; + + pImage = find_imageobject (pData, iObjectid); + + if (pImage) /* object exists ? */ + { + if (pImage->pImgbuf->bConcrete) /* is it concrete ? */ + { /* previous magnification to be done ? */ + if ((pImage->iMAGN_MethodX) || (pImage->iMAGN_MethodY)) + { + iRetcode = magnify_imageobject (pData, pImage); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + /* save delta fields */ + pData->pDeltaImage = (mng_ptr)pImage; + pData->iDeltaImagetype = iImagetype; + pData->iDeltatype = iDeltatype; + pData->iDeltaBlockwidth = iBlockwidth; + pData->iDeltaBlockheight = iBlockheight; + pData->iDeltaBlockx = iBlockx; + pData->iDeltaBlocky = iBlocky; + /* restore target-object fields */ + pData->iDatawidth = pImage->pImgbuf->iWidth; + pData->iDataheight = pImage->pImgbuf->iHeight; + pData->iBitdepth = pImage->pImgbuf->iBitdepth; + pData->iColortype = pImage->pImgbuf->iColortype; + pData->iCompression = pImage->pImgbuf->iCompression; + pData->iFilter = pImage->pImgbuf->iFilter; + pData->iInterlace = pImage->pImgbuf->iInterlace; + +#ifdef MNG_INCLUDE_JNG + pData->iJHDRimgbitdepth = pImage->pImgbuf->iBitdepth; + pData->iJHDRcolortype = pImage->pImgbuf->iColortype; + pData->iJHDRimgcompression = pImage->pImgbuf->iJHDRcompression; + pData->iJHDRimginterlace = pImage->pImgbuf->iJHDRinterlace; + pData->iJHDRalphacompression = pImage->pImgbuf->iCompression; + pData->iJHDRalphafilter = pImage->pImgbuf->iFilter; + pData->iJHDRalphainterlace = pImage->pImgbuf->iInterlace; + pData->iJHDRalphabitdepth = pImage->pImgbuf->iAlphabitdepth; +#endif + /* block size specified ? */ + if (iDeltatype != MNG_DELTATYPE_NOCHANGE) + { + pData->iDatawidth = iBlockwidth; + pData->iDataheight = iBlockheight; + } + + switch (iDeltatype) /* determine nr of delta-channels */ + { + case MNG_DELTATYPE_BLOCKALPHAADD : ; + case MNG_DELTATYPE_BLOCKALPHAREPLACE : + { +#ifdef MNG_INCLUDE_JNG + if ((pData->iColortype == MNG_COLORTYPE_GRAYA ) || + (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA) ) + { + pData->iColortype = MNG_COLORTYPE_GRAY; + pData->iJHDRcolortype = MNG_COLORTYPE_JPEGGRAY; + } + else + if ((pData->iColortype == MNG_COLORTYPE_RGBA ) || + (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) ) + { + pData->iColortype = MNG_COLORTYPE_GRAY; + pData->iJHDRcolortype = MNG_COLORTYPE_JPEGGRAY; + } +#else + if (pData->iColortype == MNG_COLORTYPE_GRAYA) + pData->iColortype = MNG_COLORTYPE_GRAY; + else + if (pData->iColortype == MNG_COLORTYPE_RGBA) + pData->iColortype = MNG_COLORTYPE_GRAY; +#endif + else /* target has no alpha; that sucks! */ + MNG_ERROR (pData, MNG_TARGETNOALPHA) + + break; + } + + case MNG_DELTATYPE_BLOCKCOLORADD : ; + case MNG_DELTATYPE_BLOCKCOLORREPLACE : + { +#ifdef MNG_INCLUDE_JNG + if ((pData->iColortype == MNG_COLORTYPE_GRAYA ) || + (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA) ) + { + pData->iColortype = MNG_COLORTYPE_GRAY; + pData->iJHDRcolortype = MNG_COLORTYPE_JPEGGRAY; + } + else + if ((pData->iColortype == MNG_COLORTYPE_RGBA ) || + (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) ) + { + pData->iColortype = MNG_COLORTYPE_RGB; + pData->iJHDRcolortype = MNG_COLORTYPE_JPEGCOLOR; + } +#else + if (pData->iColortype == MNG_COLORTYPE_GRAYA) + pData->iColortype = MNG_COLORTYPE_GRAY; + else + if (pData->iColortype == MNG_COLORTYPE_RGBA) + pData->iColortype = MNG_COLORTYPE_RGB; +#endif + else /* target has no alpha; that sucks! */ + MNG_ERROR (pData, MNG_TARGETNOALPHA) + + break; + } + + } + /* full image replace ? */ + if (iDeltatype == MNG_DELTATYPE_REPLACE) + { + iRetcode = reset_object_details (pData, pImage, + pData->iDatawidth, pData->iDataheight, + pData->iBitdepth, pData->iColortype, + pData->iCompression, pData->iFilter, + pData->iInterlace, MNG_FALSE); + + if (iRetcode) /* on error bail out */ + return iRetcode; + + pData->pStoreobj = pImage; /* and store straight into this object */ + } + else + { + mng_imagedatap pBufzero, pBuf; + /* we store in object 0 and process it later */ + pData->pStoreobj = pData->pObjzero; + /* make sure to initialize object 0 then */ + iRetcode = reset_object_details (pData, (mng_imagep)pData->pObjzero, + pData->iDatawidth, pData->iDataheight, + pData->iBitdepth, pData->iColortype, + pData->iCompression, pData->iFilter, + pData->iInterlace, MNG_TRUE); + + if (iRetcode) /* on error bail out */ + return iRetcode; + + pBuf = pImage->pImgbuf; /* copy possible palette & cheap transparency */ + pBufzero = ((mng_imagep)pData->pObjzero)->pImgbuf; + + pBufzero->bHasPLTE = pBuf->bHasPLTE; + pBufzero->bHasTRNS = pBuf->bHasTRNS; + + if (pBufzero->bHasPLTE) /* copy palette ? */ + { + mng_uint32 iX; + + pBufzero->iPLTEcount = pBuf->iPLTEcount; + + for (iX = 0; iX < pBuf->iPLTEcount; iX++) + { + pBufzero->aPLTEentries [iX].iRed = pBuf->aPLTEentries [iX].iRed; + pBufzero->aPLTEentries [iX].iGreen = pBuf->aPLTEentries [iX].iGreen; + pBufzero->aPLTEentries [iX].iBlue = pBuf->aPLTEentries [iX].iBlue; + } + } + + if (pBufzero->bHasTRNS) /* copy cheap transparency ? */ + { + pBufzero->iTRNSgray = pBuf->iTRNSgray; + pBufzero->iTRNSred = pBuf->iTRNSred; + pBufzero->iTRNSgreen = pBuf->iTRNSgreen; + pBufzero->iTRNSblue = pBuf->iTRNSblue; + pBufzero->iTRNScount = pBuf->iTRNScount; + + MNG_COPY (pBufzero->aTRNSentries, pBuf->aTRNSentries, + sizeof (pBufzero->aTRNSentries)) + } + /* process immediatly if bitdepth & colortype are equal */ + pData->bDeltaimmediate = + (mng_bool)((pData->bDisplaying) && (pData->bRunning) && + (pData->iBitdepth == ((mng_imagep)pData->pDeltaImage)->pImgbuf->iBitdepth ) && + (pData->iColortype == ((mng_imagep)pData->pDeltaImage)->pImgbuf->iColortype) ); + } + + switch (pData->iColortype) /* determine row initialization routine */ + { + case 0 : { /* gray */ + switch (pData->iBitdepth) + { + case 1 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g1_ni; + else + pData->fInitrowproc = (mng_fptr)init_g1_i; + + break; + } + case 2 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g2_ni; + else + pData->fInitrowproc = (mng_fptr)init_g2_i; + + break; + } + case 4 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g4_ni; + else + pData->fInitrowproc = (mng_fptr)init_g4_i; + + break; + } + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g8_ni; + else + pData->fInitrowproc = (mng_fptr)init_g8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_g16_ni; + else + pData->fInitrowproc = (mng_fptr)init_g16_i; + + break; + } + } + + break; + } + case 2 : { /* rgb */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgb8_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgb8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgb16_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgb16_i; + + break; + } + } + + break; + } + case 3 : { /* indexed */ + switch (pData->iBitdepth) + { + case 1 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx1_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx1_i; + + break; + } + case 2 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx2_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx2_i; + + break; + } + case 4 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx4_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx4_i; + + break; + } + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_idx8_ni; + else + pData->fInitrowproc = (mng_fptr)init_idx8_i; + + break; + } + } + + break; + } + case 4 : { /* gray+alpha */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_ga8_ni; + else + pData->fInitrowproc = (mng_fptr)init_ga8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_ga16_ni; + else + pData->fInitrowproc = (mng_fptr)init_ga16_i; + + break; + } + } + + break; + } + case 6 : { /* rgb+alpha */ + switch (pData->iBitdepth) + { + case 8 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgba8_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgba8_i; + + break; + } + case 16 : { + if (!pData->iInterlace) + pData->fInitrowproc = (mng_fptr)init_rgba16_ni; + else + pData->fInitrowproc = (mng_fptr)init_rgba16_i; + + break; + } + } + + break; + } + } + } + else + MNG_ERROR (pData, MNG_OBJNOTCONCRETE) + + } + else + MNG_ERROR (pData, MNG_OBJECTUNKNOWN) + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DHDR, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_prom (mng_datap pData, + mng_uint8 iBitdepth, + mng_uint8 iColortype, + mng_uint8 iFilltype) +{ +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PROM, MNG_LC_START) +#endif + + + /* TODO: everything */ + + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PROM, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_ipng (mng_datap pData) +{ +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IPNG, MNG_LC_START) +#endif + /* indicate it for what it is now */ + pData->iDeltaImagetype = MNG_IMAGETYPE_PNG; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IPNG, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_ijng (mng_datap pData) +{ +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IJNG, MNG_LC_START) +#endif + /* indicate it for what it is now */ + pData->iDeltaImagetype = MNG_IMAGETYPE_JNG; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IJNG, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_pplt (mng_datap pData, + mng_uint8 iType, + mng_uint32 iCount, + mng_palette8ep paIndexentries, + mng_uint8p paAlphaentries, + mng_uint8p paUsedentries) +{ + mng_uint32 iX; + mng_imagep pImage = (mng_imagep)pData->pObjzero; + mng_imagedatap pBuf = pImage->pImgbuf; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PPLT, MNG_LC_START) +#endif + + switch (iType) + { + case MNG_DELTATYPE_REPLACERGB : + { + for (iX = 0; iX < iCount; iX++) + { + if (paUsedentries [iX]) + { + pBuf->aPLTEentries [iX].iRed = paIndexentries [iX].iRed; + pBuf->aPLTEentries [iX].iGreen = paIndexentries [iX].iGreen; + pBuf->aPLTEentries [iX].iBlue = paIndexentries [iX].iBlue; + } + } + + break; + } + case MNG_DELTATYPE_DELTARGB : + { + for (iX = 0; iX < iCount; iX++) + { + if (paUsedentries [iX]) + { + pBuf->aPLTEentries [iX].iRed = + (mng_uint8)(pBuf->aPLTEentries [iX].iRed + + paIndexentries [iX].iRed ); + pBuf->aPLTEentries [iX].iGreen = + (mng_uint8)(pBuf->aPLTEentries [iX].iGreen + + paIndexentries [iX].iGreen); + pBuf->aPLTEentries [iX].iBlue = + (mng_uint8)(pBuf->aPLTEentries [iX].iBlue + + paIndexentries [iX].iBlue ); + } + } + + break; + } + case MNG_DELTATYPE_REPLACEALPHA : + { + for (iX = 0; iX < iCount; iX++) + { + if (paUsedentries [iX]) + pBuf->aTRNSentries [iX] = paAlphaentries [iX]; + } + + break; + } + case MNG_DELTATYPE_DELTAALPHA : + { + for (iX = 0; iX < iCount; iX++) + { + if (paUsedentries [iX]) + pBuf->aTRNSentries [iX] = + (mng_uint8)(pBuf->aTRNSentries [iX] + + paAlphaentries [iX]); + } + + break; + } + case MNG_DELTATYPE_REPLACERGBA : + { + for (iX = 0; iX < iCount; iX++) + { + if (paUsedentries [iX]) + { + pBuf->aPLTEentries [iX].iRed = paIndexentries [iX].iRed; + pBuf->aPLTEentries [iX].iGreen = paIndexentries [iX].iGreen; + pBuf->aPLTEentries [iX].iBlue = paIndexentries [iX].iBlue; + pBuf->aTRNSentries [iX] = paAlphaentries [iX]; + } + } + + break; + } + case MNG_DELTATYPE_DELTARGBA : + { + for (iX = 0; iX < iCount; iX++) + { + if (paUsedentries [iX]) + { + pBuf->aPLTEentries [iX].iRed = + (mng_uint8)(pBuf->aPLTEentries [iX].iRed + + paIndexentries [iX].iRed ); + pBuf->aPLTEentries [iX].iGreen = + (mng_uint8)(pBuf->aPLTEentries [iX].iGreen + + paIndexentries [iX].iGreen); + pBuf->aPLTEentries [iX].iBlue = + (mng_uint8)(pBuf->aPLTEentries [iX].iBlue + + paIndexentries [iX].iBlue ); + pBuf->aTRNSentries [iX] = + (mng_uint8)(pBuf->aTRNSentries [iX] + + paAlphaentries [iX]); + } + } + + break; + } + } + + if ((iType != MNG_DELTATYPE_REPLACERGB) && (iType != MNG_DELTATYPE_DELTARGB)) + { + if (pBuf->bHasTRNS) + { + if (iCount > pBuf->iTRNScount) + pBuf->iTRNScount = iCount; + } + else + { + pBuf->iTRNScount = iCount; + pBuf->bHasTRNS = MNG_TRUE; + } + } + + if ((iType != MNG_DELTATYPE_REPLACEALPHA) && (iType != MNG_DELTATYPE_DELTAALPHA)) + { + if (iCount > pBuf->iPLTEcount) + pBuf->iPLTEcount = iCount; + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PPLT, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_magn (mng_datap pData, + mng_uint16 iFirstid, + mng_uint16 iLastid, + mng_uint16 iMethodX, + mng_uint16 iMX, + mng_uint16 iMY, + mng_uint16 iML, + mng_uint16 iMR, + mng_uint16 iMT, + mng_uint16 iMB, + mng_uint16 iMethodY) +{ + mng_uint16 iX; + mng_imagep pImage; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MAGN, MNG_LC_START) +#endif + /* iterate the object-ids */ + for (iX = iFirstid; iX <= iLastid; iX++) + { + if (iX == 0) /* process object 0 ? */ + { + pImage = (mng_imagep)pData->pObjzero; + + pImage->iMAGN_MethodX = iMethodX; + pImage->iMAGN_MethodY = iMethodY; + pImage->iMAGN_MX = iMX; + pImage->iMAGN_MY = iMY; + pImage->iMAGN_ML = iML; + pImage->iMAGN_MR = iMR; + pImage->iMAGN_MT = iMT; + pImage->iMAGN_MB = iMB; + } + else + { + pImage = find_imageobject (pData, iX); + /* object exists & is not frozen ? */ + if ((pImage) && (!pImage->bFrozen)) + { /* previous magnification to be done ? */ + if ((pImage->iMAGN_MethodX) || (pImage->iMAGN_MethodY)) + { + mng_retcode iRetcode = magnify_imageobject (pData, pImage); + + if (iRetcode) /* on error bail out */ + return iRetcode; + } + + pImage->iMAGN_MethodX = iMethodX; + pImage->iMAGN_MethodY = iMethodY; + pImage->iMAGN_MX = iMX; + pImage->iMAGN_MY = iMY; + pImage->iMAGN_ML = iML; + pImage->iMAGN_MR = iMR; + pImage->iMAGN_MT = iMT; + pImage->iMAGN_MB = iMB; + } + } + } + + iX = iFirstid; + /* iterate again for showing */ + while ((iX <= iLastid) && (!pData->bTimerset)) + { + if (iX) /* only real objects ! */ + { + pImage = find_imageobject (pData, iX); + /* object exists & is not frozen & + is visible & is viewable ? */ + if ((pImage) && (!pImage->bFrozen) && + (pImage->bVisible) && (pImage->bViewable)) + display_image (pData, pImage, MNG_FALSE); + } + + iX++; + } + + if (pData->bTimerset) /* broken ? */ + { + pData->iMAGNfromid = iFirstid; + pData->iMAGNtoid = iLastid; + pData->iBreakpoint = 9; + } + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MAGN, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +mng_retcode process_display_magn2 (mng_datap pData) +{ + mng_uint16 iX; + mng_imagep pImage; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MAGN, MNG_LC_START) +#endif + + iX = pData->iMAGNfromid; + /* iterate again for showing */ + while ((iX <= pData->iMAGNtoid) && (!pData->bTimerset)) + { + if (iX) /* only real objects ! */ + { + pImage = find_imageobject (pData, iX); + /* object exists & is not frozen & + is visible & is viewable ? */ + if ((pImage) && (!pImage->bFrozen) && + (pImage->bVisible) && (pImage->bViewable)) + display_image (pData, pImage, MNG_FALSE); + } + + iX++; + } + + if (pData->bTimerset) /* broken ? */ + pData->iBreakpoint = 9; + +#ifdef MNG_SUPPORT_TRACE + MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MAGN, MNG_LC_END) +#endif + + return MNG_NOERROR; +} + +/* ************************************************************************** */ + +#endif /* MNG_INCLUDE_DISPLAY_PROCS */ + +/* ************************************************************************** */ +/* * end of file * */ +/* ************************************************************************** */ + |