Author: rpmcruz Date: Fri Oct 12 14:35:29 2007 New Revision: 41406 URL: http://svn.opensuse.org/viewcvs/yast?rev=41406&view=rev Log: * src/ygdkmngloader.h/c / src/YGImage.cc: added support for inline MNG images. Fixed ticks per second. * tests/YGImage.ycp: added a bunch of MNGs I found... Modified: trunk/gtk/ChangeLog trunk/gtk/src/YGImage.cc trunk/gtk/src/ygdkmngloader.c trunk/gtk/src/ygdkmngloader.h trunk/gtk/tests/Image.ycp trunk/gtk/tests/ImageMng.ycp Modified: trunk/gtk/ChangeLog URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/ChangeLog?rev=41406&r1=41405&r2=41406&view=diff ============================================================================== --- trunk/gtk/ChangeLog (original) +++ trunk/gtk/ChangeLog Fri Oct 12 14:35:29 2007 @@ -1,3 +1,9 @@ +2007-10-12 Ricardo Cruz <rpmcruz@alunos.dcc.fc.up.pt> + + * src/ygdkmngloader.h/c / src/YGImage.cc: added support for inline MNG + images. + * tests/YGImage.ycp: added a bunch of MNGs I found... + 2007-10-11 Ricardo Cruz <rpmcruz@alunos.dcc.fc.up.pt> * src/YGPackageSelector.cc: speed up Patterns view. Modified: trunk/gtk/src/YGImage.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGImage.cc?rev=41406&r1=41405&r2=41406&view=diff ============================================================================== --- trunk/gtk/src/YGImage.cc (original) +++ trunk/gtk/src/YGImage.cc Fri Oct 12 14:35:29 2007 @@ -125,15 +125,24 @@ alt_text = g_strdup (text->value_cstr()); initOptions (opt); - GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); - g_signal_connect (G_OBJECT (loader), "area-prepared", - G_CALLBACK (image_loaded_cb), this); - GError *error = 0; - if (!gdk_pixbuf_loader_write (loader, - byteblock->value(), byteblock->size(), &error)) - g_warning ("Could not load image from data blocks: %s", error->message); - gdk_pixbuf_loader_close (loader, &error); + if (m_isAnimation && ygdk_mng_pixbuf_is_data_mng (byteblock->value(), byteblock->size())) + { + GdkPixbufAnimation *pixbuf; + pixbuf = ygdk_mng_pixbuf_new_from_data (byteblock->value(), byteblock->size(), &error); + loadAnimation (pixbuf, error ? error->message : "(undefined)"); + } + else + { + GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); + g_signal_connect (G_OBJECT (loader), "area-prepared", + G_CALLBACK (image_loaded_cb), this); + + if (!gdk_pixbuf_loader_write (loader, + byteblock->value(), byteblock->size(), &error)) + g_warning ("Could not load image from data blocks: %s", error->message); + gdk_pixbuf_loader_close (loader, &error); + } } virtual ~YGImage() Modified: trunk/gtk/src/ygdkmngloader.c URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygdkmngloader.c?rev=41406&r1=41405&r2=41406&view=diff ============================================================================== --- trunk/gtk/src/ygdkmngloader.c (original) +++ trunk/gtk/src/ygdkmngloader.c Fri Oct 12 14:35:29 2007 @@ -30,47 +30,58 @@ //** Utilities to read the MNG file -typedef gboolean (*ChunkParser)(YGdkMngPixbuf*, guint8*, GError**); - -struct ChunkLoad { - guint8 Id; - ChunkParser Function; - -}; +typedef struct DataStream { + const guint8 *data; + const long size; + long offset; +} DataStream; +static DataStream data_stream_constructor (const guint8 *raw_data, long size) +{ + DataStream data = { raw_data, size, 0 }; + return data; +} -static gboolean read_signature (FILE *file) +static gboolean read_signature (DataStream *data) { - guchar buf[8]; - fread (buf, 1, 8, file); - return memcmp (buf, "\212MNG\r\n\032\n", 8) == 0; + if (data->offset+8 > data->size) + return FALSE; + data->offset += 8; + return memcmp (data->data + data->offset-8, "\212MNG\r\n\032\n", 8) == 0; } -static gboolean read_uint8 (FILE *file, guint8 *value) +static gboolean read_uint8 (DataStream *data, guint8 *value) { - return fread (value, 1, 1, file) >= 1; + if (data->offset+1 > data->size) + return FALSE; + *value = data->data [data->offset++]; + return TRUE; } -static gboolean read_uint32 (FILE *file, guint32 *value) +static gboolean read_uint32 (DataStream *data, guint32 *value) { - guint8 buffer[4]; - if (fread (buffer, 1, 4, file) < 4) + if (data->offset+4 > data->size) return FALSE; - *value = buffer[0] << 24; *value |= buffer[1] << 16; - *value |= buffer[2] << 8; *value |= buffer[3]; + *value = data->data[data->offset+0] << 24; + *value |= data->data[data->offset+1] << 16; + *value |= data->data[data->offset+2] << 8; + *value |= data->data[data->offset+3]; + data->offset += 4; return TRUE; } -static gboolean read_data (FILE *file, guint32 size, GdkPixbufLoader *loader, +static gboolean read_data (DataStream *data, guint32 size, GdkPixbufLoader *loader, GError **error) { - guchar data [size]; - if (fread (data, 1, size, file) < size) + if (data->offset+size > data->size) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "Unexpected end of file when reading PNG chunk"); return FALSE; } - return gdk_pixbuf_loader_write (loader, data, size, error); + gboolean ret; + ret = gdk_pixbuf_loader_write (loader, data->data + data->offset, size, error); + data->offset += size; + return ret; } static void image_prepared_cb (GdkPixbufLoader *loader, YGdkMngPixbuf *mng_pixbuf) @@ -91,17 +102,34 @@ { FILE *file = fopen (filename, "rb"); if (!file) - return FALSE; - return read_signature (file); + goto is_file_mng_failed; + + guchar raw_data [8]; + if (fread (raw_data, 1, 8, file) < 8) + goto is_file_mng_failed; + + gboolean ret = ygdk_mng_pixbuf_is_data_mng (raw_data, 8); + fclose (file); + return ret; + +is_file_mng_failed: + fclose (file); + return FALSE; +} + +gboolean ygdk_mng_pixbuf_is_data_mng (const guint8 *raw_data, long size) +{ + DataStream data = data_stream_constructor (raw_data, size); + return read_signature (&data); } +#define SET_ERROR(msg) { error = TRUE; \ + g_set_error (error_msg, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, msg); } + GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_file (const gchar *filename, GError **error_msg) { gboolean error = FALSE; - #define SET_ERROR(msg) { error = TRUE; \ - g_set_error (error_msg, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, msg); } - FILE *file = fopen (filename, "rb"); if (!file) { @@ -109,7 +137,31 @@ return NULL; } - if (!read_signature (file)) + fseek (file, 0, SEEK_END); + long file_size = ftell (file); + fseek (file, 0, SEEK_SET); + + GdkPixbufAnimation *mng_pixbuf = 0; + guchar *data = mmap (NULL, file_size, PROT_READ, MAP_PRIVATE, + fileno (file), 0); + if (data == MAP_FAILED) + SET_ERROR ("Could not map file") + else + { + mng_pixbuf = ygdk_mng_pixbuf_new_from_data (data, file_size, error_msg); + munmap (data, file_size); + } + fclose (file); + return mng_pixbuf; +} + +GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_data (const guint8 *raw_data, long size, + GError **error_msg) +{ + DataStream data = data_stream_constructor (raw_data, size); + + gboolean error = FALSE; + if (!read_signature (&data)) { SET_ERROR ("Not a MNG file") return NULL; @@ -119,19 +171,19 @@ mng_pixbuf->iteration_max = 0x7fffffff; guint32 chunk_size, chunk_id; - long offset; + long chunk_offset; GdkPixbufLoader *loader = NULL; /* currently loading... */ gboolean first_read = TRUE; do { - error = !read_uint32 (file, &chunk_size); - error = error || !read_uint32 (file, &chunk_id); + error = !read_uint32 (&data, &chunk_size); + error = error || !read_uint32 (&data, &chunk_id); if (error) { SET_ERROR ("Unexpected end of file on new chunk") break; } - offset = ftell (file) + chunk_size + 4/*CRC*/; + chunk_offset = data.offset + chunk_size + 4/*CRC*/; if (first_read && chunk_id != MNG_UINT_MHDR) { @@ -154,9 +206,9 @@ if (chunk_size == 7*4) { // Read MHDR chunk data - error = !read_uint32 (file, &mng_pixbuf->frame_width); - error = error || !read_uint32 (file, &mng_pixbuf->frame_height); - error = error || !read_uint32 (file, &mng_pixbuf->ticks_per_second); + error = !read_uint32 (&data, &mng_pixbuf->frame_width); + error = error || !read_uint32 (&data, &mng_pixbuf->frame_height); + error = error || !read_uint32 (&data, &mng_pixbuf->ticks_per_second); if (error) SET_ERROR ("Unexpected end of file on MHDR chunk") /* Next atttributes: Nominal_layer_count, Nominal_frame_count, @@ -165,7 +217,7 @@ mng_pixbuf->frame_height <= 0 || mng_pixbuf->ticks_per_second < 0) SET_ERROR ("Invalid MHDR parameter") -fprintf(stderr, "ticks per second: %d\n", mng_pixbuf->ticks_per_second); +//fprintf(stderr, "ticks per second: %d\n", mng_pixbuf->ticks_per_second); } else SET_ERROR ("MHDR chunk must be 28 bytes long") @@ -191,12 +243,12 @@ { // Read TERM chunk data guint8 t; - error = !read_uint8 (file, &t); // term action + error = !read_uint8 (&data, &t); // term action if (t == 3 && chunk_size == 2+8) { - error = error || !read_uint8 (file, &t); // after term action - error = error || !read_uint32 (file, &mng_pixbuf->last_frame_delay); - error = error || !read_uint32 (file, &mng_pixbuf->iteration_max); + error = error || !read_uint8 (&data, &t); // after term action + error = error || !read_uint32 (&data, &mng_pixbuf->last_frame_delay); + error = error || !read_uint32 (&data, &mng_pixbuf->iteration_max); if (error) SET_ERROR ("Unexpected end of file on TERM chunk") } @@ -226,8 +278,8 @@ // loading a PNG stream if (loader) { - fseek (file, -8, SEEK_CUR); - if (!read_data (file, chunk_size+8+4, loader, error_msg)) + data.offset -= 8; + if (!read_data (&data, chunk_size+8+4, loader, error_msg)) error = TRUE; else if (chunk_id == MNG_UINT_IEND) { @@ -240,7 +292,7 @@ } } - fseek (file, offset, SEEK_SET); + data.offset = chunk_offset; first_read = FALSE; } while (chunk_id != MNG_UINT_MEND && !error); @@ -249,11 +301,11 @@ g_object_unref (G_OBJECT (mng_pixbuf)); return NULL; } - #undef SET_ERROR - return GDK_PIXBUF_ANIMATION (mng_pixbuf); } +#undef SET_ERROR + static gboolean ygdk_mng_pixbuf_is_static_image (GdkPixbufAnimation *anim) { return FALSE; @@ -314,7 +366,7 @@ static int ygdk_mng_pixbuf_iter_get_delay_time (GdkPixbufAnimationIter *iter) { YGdkMngPixbufIter *mng_iter = YGDK_MNG_PIXBUF_ITER (iter); - int delay = mng_iter->mng_pixbuf->ticks_per_second; + int delay = 1000.0 / mng_iter->mng_pixbuf->ticks_per_second; if (mng_iter->cur_frame == g_list_length (mng_iter->mng_pixbuf->frames)-1) delay += mng_iter->mng_pixbuf->last_frame_delay; return delay; Modified: trunk/gtk/src/ygdkmngloader.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygdkmngloader.h?rev=41406&r1=41405&r2=41406&view=diff ============================================================================== --- trunk/gtk/src/ygdkmngloader.h (original) +++ trunk/gtk/src/ygdkmngloader.h Fri Oct 12 14:35:29 2007 @@ -44,8 +44,10 @@ GdkPixbufAnimationClass parent_class; } YGdkMngPixbufClass; -GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_file (const gchar *filename, GError **error_msg); +GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_file (const gchar *filename, GError **error); +GdkPixbufAnimation *ygdk_mng_pixbuf_new_from_data (const guint8 *data, long size, GError **error); gboolean ygdk_mng_pixbuf_is_file_mng (const gchar *filename); +gboolean ygdk_mng_pixbuf_is_data_mng (const guint8 *data, long size); GType ygdk_mng_pixbuf_get_type (void) G_GNUC_CONST; Modified: trunk/gtk/tests/Image.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/Image.ycp?rev=41406&r1=41405&r2=41406&view=diff ============================================================================== --- trunk/gtk/tests/Image.ycp (original) +++ trunk/gtk/tests/Image.ycp Fri Oct 12 14:35:29 2007 @@ -1,5 +1,5 @@ // Image test -string filename = "image.gif"; +string filename = "tests/image.gif"; { UI::OpenDialog ( Modified: trunk/gtk/tests/ImageMng.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/tests/ImageMng.ycp?rev=41406&r1=41405&r2=41406&view=diff ============================================================================== --- trunk/gtk/tests/ImageMng.ycp (original) +++ trunk/gtk/tests/ImageMng.ycp Fri Oct 12 14:35:29 2007 @@ -1,4 +1,6 @@ // Image test +// TODO: make it getting the filename as an argument + { UI::OpenDialog ( `VBox ( @@ -10,8 +12,14 @@ `Frame ("Which MNG file:", `RadioButtonGroup (`id(`rb), `VBox( - `Left (`RadioButton(`id (`endless), `opt(`notify), "&Endless")), - `Left (`RadioButton(`id (`loop3), `opt(`notify), "&Loop 3")) + `Left (`RadioButton(`id (`movie1), `opt(`notify), "&Movie1")), + `Left (`RadioButton(`id (`movie2), `opt(`notify), "&Movie2")), + `Left (`RadioButton(`id (`movie3), `opt(`notify), "&Movie3")), + `Left (`RadioButton(`id (`movie4), `opt(`notify), "&Movie4")), + `Left (`RadioButton(`id (`movie5), `opt(`notify), "&Movie5")), + `Left (`RadioButton(`id (`movie6), `opt(`notify), "&Movie6")), + `Left (`RadioButton(`id (`movie7), `opt(`notify), "&Movie7")), + `Left (`RadioButton(`id (`movie8), `opt(`notify), "&Movie8")) ) ) ), @@ -52,10 +60,26 @@ } string filename = ""; - if ((boolean) UI::QueryWidget(`id(`loop3), `Value)) - filename = "movie-loop3.mng"; + if ((boolean) UI::QueryWidget(`id(`movie1), `Value)) + filename = "tests/movie1.mng"; + else if ((boolean) UI::QueryWidget(`id(`movie2), `Value)) + filename = "tests/movie2.mng"; + else if ((boolean) UI::QueryWidget(`id(`movie3), `Value)) + filename = "tests/movie3.mng"; + else if ((boolean) UI::QueryWidget(`id(`movie4), `Value)) + filename = "tests/movie4.mng"; + else if ((boolean) UI::QueryWidget(`id(`movie5), `Value)) + filename = "tests/movie5.mng"; + else if ((boolean) UI::QueryWidget(`id(`movie6), `Value)) + filename = "tests/movie6.mng"; + else if ((boolean) UI::QueryWidget(`id(`movie7), `Value)) + filename = "tests/movie7.mng"; else - filename = "movie-endless.mng"; + filename = "tests/movie8.mng"; + + // to test inline images, uncomment next line and pass it to `Image + //byteblock data = (byteblock) SCR::Read (.target.byte, filename); + UI::ReplaceWidget (`replace_image, `Image (`opt (`animated, effect_opt, zerowidth, zeroheight), filename, filename + " not found")); -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org