Remove .gitignore do nothing is ignored.
[synfig.git] / synfig-core / trunk / src / modules / mod_mng / trgt_mng.cpp
index ed657b9..7a97c7c 100644 (file)
@@ -5,7 +5,8 @@
 **     $Id$
 **
 **     \legal
-**     Copyright 2007 Paul Wise
+**     Copyright (c) 2007 Paul Wise
+**     Copyright (c) 2007 Chris Moore
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
@@ -20,8 +21,6 @@
 **
 ** === N O T E S ===========================================================
 **
-** FIXME: THIS DOES NOT ACTUALLY WORK YET
-**
 ** You will need to read the PNG and MNG specs to understand this code
 **
 ** ========================================================================= */
@@ -70,56 +69,53 @@ mng_alloc_proc(mng_size_t size)
 }
 
 static void MNG_DECL
-mng_free_proc(mng_ptr ptr, mng_size_t size)
+mng_free_proc(mng_ptr ptr, mng_size_t size __attribute__ ((unused)))
 {
        free(ptr); return;
 }
 
 static mng_bool MNG_DECL
-mng_null_proc(mng_handle mng)
+mng_null_proc(mng_handle mng __attribute__ ((unused)))
 {
-       synfig::error("mng_trgt: error: mng_null_proc");
+       // synfig::info("%s:%d mng_trgt::mng_null_proc was called", __FILE__, __LINE__);
        return MNG_TRUE;
 }
 
 static mng_bool MNG_DECL
 mng_write_proc(mng_handle mng, mng_ptr buf, mng_uint32 size, mng_uint32* written)
 {
-       synfig::error("mng_trgt: error: mng_write_proc");
        FILE* file = (FILE*)mng_get_userdata (mng);
        *written = fwrite(buf, 1, size, file);
        return MNG_TRUE;
 }
 
 static mng_bool MNG_DECL
-mng_error_proc(mng_handle mng, mng_int32 error, mng_int8 severity, mng_chunkid chunkname,
-                          mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar errortext)
+mng_error_proc(mng_handle mng __attribute__ ((unused)), mng_int32 error __attribute__ ((unused)),
+                          mng_int8 severity __attribute__ ((unused)), mng_chunkid chunkname __attribute__ ((unused)),
+                          mng_uint32 chunkseq __attribute__ ((unused)), mng_int32 extra1 __attribute__ ((unused)),
+                          mng_int32 extra2 __attribute__ ((unused)), mng_pchar errortext)
 {
-       // mng_trgt* me =
-       (mng_trgt*)mng_get_userdata (mng);
-       fprintf(stderr,"mng_trgt: error: %s",errortext);
-       // me->ready=false;
+       synfig::error("%s:%d mng_trgt: error: %s", __FILE__, __LINE__, errortext);
        return MNG_TRUE;
 }
 
-mng_trgt::mng_trgt(const char *Filename):
-       filename(Filename)
+mng_trgt::mng_trgt(const char *Filename) : filename(Filename)
 {
        file=NULL;
        buffer=NULL;
-       color_buffer=NULL;      
-       zbuffer=NULL;   
+       color_buffer=NULL;
+       zbuffer=NULL;
        zbuffer_len=0;
        ready=false;
 }
 
 mng_trgt::~mng_trgt()
 {
-       synfig::error("mng_trgt: error: ~mng_trgt");
+       synfig::info("mng_trgt: ~mng_trgt");
        if (mng != MNG_NULL)
        {
                mng_putchunk_mend(mng);
-               if (mng_write(mng) != 0 )
+               if (mng_write(mng) != 0)
                {
                        mng_int8 severity;
                        mng_chunkid chunkname;
@@ -132,10 +128,10 @@ mng_trgt::~mng_trgt()
                }
                mng_cleanup (&mng);
        }
-       if (file != NULL ) fclose(file); file=NULL;
-       if (buffer != NULL ) { delete [] buffer; buffer = NULL; }
-       if (color_buffer != NULL ) { delete [] color_buffer; color_buffer = NULL; }
-       if (zbuffer != NULL ) { free(zbuffer); zbuffer = NULL; zbuffer_len = 0; }
+       if (file != NULL) fclose(file); file=NULL;
+       if (buffer != NULL) { delete [] buffer; buffer = NULL; }
+       if (color_buffer != NULL) { delete [] color_buffer; color_buffer = NULL; }
+       if (zbuffer != NULL) { free(zbuffer); zbuffer = NULL; zbuffer_len = 0; }
 }
 
 bool
@@ -143,7 +139,7 @@ mng_trgt::set_rend_desc(RendDesc *given_desc)
 {
        desc=*given_desc;
        imagecount=desc.get_frame_start();
-       if(desc.get_frame_end()-desc.get_frame_start()>0)
+       if (desc.get_frame_end()-desc.get_frame_start()>0)
                multi_image=true;
        else
                multi_image=false;
@@ -154,34 +150,64 @@ mng_trgt::set_rend_desc(RendDesc *given_desc)
 bool
 mng_trgt::init()
 {
+       // synfig::info("%s:%d mng_trgt::init()", __FILE__, __LINE__);
+
+       int frame_rate, num_frames, play_time;
+       int num_layers = 1;
+
+       if (multi_image)
+       {
+               frame_rate = int(desc.get_frame_rate());
+               printf("frame rt %d\n", frame_rate);
+               num_frames = desc.get_frame_end()-desc.get_frame_start();
+               play_time = num_frames;// / frame_rate;
+       }
+       else
+       {
+               frame_rate = 0;
+               num_frames = 1;
+               play_time = 0;
+       }
+
        time_t t = time (NULL);
        struct tm* gmt = gmtime(&t);
        w=desc.get_w(); h=desc.get_h();
-       //synfig::error("mng_trgt: init %d %d",w,h); 
        file = fopen(filename.c_str(), POPEN_BINARY_WRITE_TYPE);
-       if (file == NULL ) goto cleanup_on_error;
+       if (file == NULL) goto cleanup_on_error;
        mng = mng_initialize((mng_ptr)file, mng_alloc_proc, mng_free_proc, MNG_NULL);
-       if(mng == MNG_NULL) goto cleanup_on_error;
-       if (mng_setcb_errorproc(mng, mng_error_proc) != 0 ) goto cleanup_on_error;
-       if (mng_setcb_writedata(mng, mng_write_proc) != 0 ) goto cleanup_on_error;
-       if (mng_setcb_openstream(mng, mng_null_proc) != 0 ) goto cleanup_on_error;
-       if (mng_setcb_closestream(mng, mng_null_proc) != 0 ) goto cleanup_on_error;
-       if (mng_create(mng) != 0 ) goto cleanup_on_error;
-       if (mng_putchunk_mhdr(mng, w, h, multi_image?1000:0, 1, desc.get_frame_end()-desc.get_frame_start(), 0, 0) != 0 ) goto cleanup_on_error;
-       if (mng_putchunk_term(mng, MNG_TERMACTION_REPEAT, MNG_ITERACTION_LASTFRAME, 0, 0x7fffffff) != 0 ) goto cleanup_on_error;
-       if (mng_putchunk_text(mng, sizeof(MNG_TEXT_TITLE), MNG_TEXT_TITLE, get_canvas()->get_name().length(), const_cast<char *>(get_canvas()->get_name().c_str()) ) != 0 ) goto cleanup_on_error;
-       if (mng_putchunk_text(mng, sizeof(MNG_TEXT_DESCRIPTION), MNG_TEXT_DESCRIPTION, get_canvas()->get_description().length(), const_cast<char *>(get_canvas()->get_description().c_str()) ) != 0 ) goto cleanup_on_error;
-       if (mng_putchunk_text(mng, sizeof(MNG_TEXT_SOFTWARE), MNG_TEXT_SOFTWARE, sizeof("SYNFIG"), "SYNFIG" ) != 0 ) goto cleanup_on_error;
-       /* FIXME: not sure if this is correct */
-       if (mng_putchunk_gama(mng, MNG_FALSE, (int)(1.0/gamma().get_gamma()*100000)) != 0 ) goto cleanup_on_error;
-       if (mng_putchunk_phyg(mng, MNG_FALSE,round_to_int(desc.get_x_res()),round_to_int(desc.get_y_res()),MNG_UNIT_METER) != 0 ) goto cleanup_on_error;
-       if (mng_putchunk_time(mng, gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min, gmt->tm_sec) != 0 ) goto cleanup_on_error;
-       buffer=new unsigned char[4*w];
-       if (buffer == NULL ) goto cleanup_on_error;
+       if (mng == MNG_NULL) goto cleanup_on_error;
+       if (mng_setcb_errorproc(mng, mng_error_proc) != 0) goto cleanup_on_error;
+       if (mng_setcb_writedata(mng, mng_write_proc) != 0) goto cleanup_on_error;
+       if (mng_setcb_openstream(mng, mng_null_proc) != 0) goto cleanup_on_error;
+       if (mng_setcb_closestream(mng, mng_null_proc) != 0) goto cleanup_on_error;
+       if (mng_create(mng) != 0) goto cleanup_on_error;
+       if (mng_putchunk_mhdr(mng, w, h, frame_rate, num_layers, num_frames, play_time, MNG_SIMPLICITY_VALID|MNG_SIMPLICITY_SIMPLEFEATURES) != 0) goto cleanup_on_error;
+       if (mng_putchunk_term(mng, MNG_TERMACTION_REPEAT, MNG_ITERACTION_LASTFRAME, 0, 0x7fffffff) != 0) goto cleanup_on_error;
+       {
+               char title[] = MNG_TEXT_TITLE;
+               if (mng_putchunk_text(mng, sizeof(title), title,
+                                                         get_canvas()->get_name().length(), const_cast<char *>(get_canvas()->get_name().c_str())) != 0)
+                       goto cleanup_on_error;
+
+               char description[] = MNG_TEXT_DESCRIPTION;
+               if (mng_putchunk_text(mng, sizeof(description), description,
+                                                         get_canvas()->get_description().length(), const_cast<char *>(get_canvas()->get_description().c_str())) != 0)
+                       goto cleanup_on_error;
+
+               char software[] = MNG_TEXT_SOFTWARE; char synfig[] = "SYNFIG";
+               if (mng_putchunk_text(mng, sizeof(software), software,
+                                                         sizeof(synfig), synfig) != 0)
+                       goto cleanup_on_error;
+       }
+       if (mng_putchunk_gama(mng, MNG_FALSE, (int)(gamma().get_gamma()*100000)) != 0) goto cleanup_on_error;
+       if (mng_putchunk_phys(mng, MNG_FALSE, round_to_int(desc.get_x_res()),round_to_int(desc.get_y_res()), MNG_UNIT_METER) != 0) goto cleanup_on_error;
+       if (mng_putchunk_time(mng, gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min, gmt->tm_sec) != 0) goto cleanup_on_error;
+       buffer=new unsigned char[(4*w)+1];
+       if (buffer == NULL) goto cleanup_on_error;
        color_buffer=new Color[w];
-       if (color_buffer == NULL ) goto cleanup_on_error;
+       if (color_buffer == NULL) goto cleanup_on_error;
        return true;
-       
+
 cleanup_on_error:
        ready=false;
        if (mng != MNG_NULL)
@@ -193,125 +219,119 @@ cleanup_on_error:
                mng_int32 extra2;
                mng_pchar errortext;
                mng_getlasterror (mng, &severity, &chunkname, &chunkseq, &extra1,&extra2, &errortext);
-               synfig::error("mng_trgt: libmng: %s",errortext); 
+               synfig::error("mng_trgt: libmng: %s",errortext);
                mng_cleanup (&mng);
        }
-       if (file && file!=stdout ) fclose(file); file=NULL;
-       if (buffer != NULL ) { delete [] buffer; buffer = NULL; }
-       if (color_buffer != NULL ) { delete [] color_buffer; color_buffer = NULL; }
-       return false;   
+
+       if (file && file!=stdout)
+               fclose(file);
+       file=NULL;
+
+       if (buffer != NULL)
+       {
+               delete [] buffer;
+               buffer = NULL;
+       }
+
+       if (color_buffer != NULL)
+       {
+               delete [] color_buffer;
+               color_buffer = NULL;
+       }
+
+       return false;
 }
 
 void
 mng_trgt::end_frame()
 {
-       //synfig::error("mng_trgt: endf %d %d",w,h); 
-       //synfig::error("mng_trgt: error: endframe");
-       deflate(&zstream,Z_FINISH);
-       deflateEnd(&zstream);
-       if (mng != MNG_NULL )
+       // synfig::info("%s:%d mng_trgt::end_frame()", __FILE__, __LINE__);
+
+       if (deflate(&zstream,Z_FINISH) != Z_STREAM_END)
+       {
+               synfig::error("%s:%d deflate()", __FILE__, __LINE__);
+               return;
+       }
+       if (deflateEnd(&zstream) != Z_OK)
+       {
+               synfig::error("%s:%d deflateEnd()", __FILE__, __LINE__);
+               return;
+       }
+       if (mng != MNG_NULL)
        {
-               // mng_int8 severity;
-               // mng_chunkid chunkname;
-               // mng_uint32 chunkseq;
-               // mng_int32 extra1;
-               // mng_int32 extra2;
-               // mng_pchar errortext;
-               mng_putchunk_idat(mng, zbuffer_len, zbuffer);
-               //mng_getlasterror (mng, &severity, &chunkname, &chunkseq, &extra1,&extra2, &errortext);
-               //synfig::error("mng_trgt: libmng: %s %d",errortext,zbuffer_len); 
+               mng_putchunk_idat(mng, zstream.next_out-zbuffer, zbuffer);
                mng_putchunk_iend(mng);
-               //mng_getlasterror (mng, &severity, &chunkname, &chunkseq, &extra1,&extra2, &errortext);
-               //synfig::error("mng_trgt: libmng: %s %d",errortext); 
        }
        imagecount++;
        ready=false;
 }
 
 bool
-mng_trgt::start_frame(synfig::ProgressCallback *callback)
+mng_trgt::start_frame(synfig::ProgressCallback *callback __attribute__ ((unused)))
 {
-       //synfig::error("mng_trgt: startf %d %d",w,h); 
-       //synfig::error("mng_trgt: error: startframe");
-       /*
-       FIXME: figure out if we need this
-       mng_putchunk_fram(mng,
-               MNG_FALSE,
-               MNG_FRAMINGMODE_NOCHANGE,
-               0,
-               NULL,
-               MNG_CHANGEDELAY_NO,
-               MNG_CHANGETIMOUT_NO,
-               MNG_CHANGECLIPPING_NO,
-               MNG_CHANGESYNCID_NO,
-               0,
-               0,
-               0,
-               layer_offset_x,
-               layer_offset_x + layer_cols,
-               layer_offset_y,
-               layer_offset_y + layer_rows,
-               0,
-               0)
-       mng_getchunk_fram(mng_handle       hHandle,
-               mng_handle       hChunk,
-               mng_bool         *bEmpty,
-               mng_uint8        *iMode,
-               mng_uint32       *iNamesize,
-               mng_pchar        *zName,
-               mng_uint8        *iChangedelay,
-               mng_uint8        *iChangetimeout,
-               mng_uint8        *iChangeclipping,
-               mng_uint8        *iChangesyncid,
-               mng_uint32       *iDelay,
-               mng_uint32       *iTimeout,
-               mng_uint8        *iBoundarytype,
-               mng_int32        *iBoundaryl,
-               mng_int32        *iBoundaryr,
-               mng_int32        *iBoundaryt,
-               mng_int32        *iBoundaryb,
-               mng_uint32       *iCount,
-               mng_uint32p      *pSyncids);
-       */
-       if (mng == MNG_NULL ) return false;
-       if (mng_putchunk_defi(mng,0,MNG_DONOTSHOW_VISIBLE,MNG_ABSTRACT,MNG_FALSE,0,0,MNG_FALSE,0,0,0,0) != 0) return false;
-       if (mng_putchunk_ihdr(mng,w,h,MNG_BITDEPTH_8,MNG_COLORTYPE_RGBA,MNG_COMPRESSION_DEFLATE, 0/*MNG_FILTER_NO_DIFFERING*/,MNG_INTERLACE_NONE) != 0) return false;
+       // synfig::info("%s:%d mng_trgt::start_frame()", __FILE__, __LINE__);
+
+       if (mng == MNG_NULL)
+       {
+               synfig::error("%s:%d mng == MNG_NULL", __FILE__, __LINE__);
+               return false;
+       }
+
+       if (mng_putchunk_ihdr(mng, w, h, MNG_BITDEPTH_8, MNG_COLORTYPE_RGBA, MNG_COMPRESSION_DEFLATE, MNG_FILTER_ADAPTIVE, MNG_INTERLACE_NONE) != 0)
+       {
+               synfig::error("%s:%d mng_putchunk_ihdr()", __FILE__, __LINE__);
+               return false;
+       }
+
        zstream.zalloc = Z_NULL;
        zstream.zfree = Z_NULL;
        zstream.opaque = Z_NULL;
-       zstream.data_type = Z_BINARY; 
-       if (deflateInit(&zstream, Z_DEFAULT_COMPRESSION) != Z_OK ) return false;
-       //zbuffer_len = deflateBound(&zstream,4*w*h);
-       if(zbuffer == NULL)
+
+       if (deflateInit(&zstream, /* Z_BEST_COMPRESSION */ Z_DEFAULT_COMPRESSION) != Z_OK)
        {
-               zbuffer_len = 4*w*h;
+               synfig::error("%s:%d deflateInit()", __FILE__, __LINE__);
+               return false;
+       }
+
+       if (zbuffer == NULL)
+       {
+               zbuffer_len = deflateBound(&zstream,((4*w)+1)*h); // don't forget the 'filter' byte - one per scanline
                zbuffer = (unsigned char*)realloc(zbuffer, zbuffer_len);
-               zstream.next_out = zbuffer;
-               zstream.avail_out = zbuffer_len;
        }
+
+       zstream.avail_out = zbuffer_len;
+       zstream.next_out = zbuffer;
+
        ready=true;
+
        return true;
 }
 
 Color*
-mng_trgt::start_scanline(int scanline)
+mng_trgt::start_scanline(int scanline __attribute__ ((unused)))
 {
-       //synfig::error("mng_trgt: starts %d %d",w,h); 
-       //synfig::error("mng_trgt: error: startscanline");
        return color_buffer;
 }
 
 bool
 mng_trgt::end_scanline()
 {
-       //synfig::error("mng_trgt: ends %d %d",w,h); 
-       //synfig::error("mng_trgt: error: endscanline");
-       if(!file || !ready)
+       if (!file || !ready)
+       {
+               synfig::error("%s:%d !file or !ready", __FILE__, __LINE__);
                return false;
-       convert_color_format(buffer, color_buffer, desc.get_w(), PF_RGB|PF_A, gamma());
-       /* FIXME: Implement buffer management */
+       }
+
+       *buffer = MNG_FILTER_NONE;
+       convert_color_format(buffer+1, color_buffer, desc.get_w(), PF_RGB|PF_A, gamma());
+
        zstream.next_in = buffer;
-       zstream.avail_in = 4*w;
-       deflate(&zstream,Z_NO_FLUSH);
+       zstream.avail_in = (4*w)+1;
+
+       if (deflate(&zstream,Z_NO_FLUSH) != Z_OK) {
+               synfig::error("%s:%d deflate()", __FILE__, __LINE__);
+               return false;
+       }
+
        return true;
 }