Added thumbnails, tooltips, and now the file routines don't use PACKFILE (just FILE from stdio).

This commit is contained in:
David Capello 2008-02-10 19:06:03 +00:00
parent 112bde13c8
commit 3290dfb7d5
52 changed files with 1574 additions and 908 deletions

View File

@ -1,3 +1,45 @@
2008-02-10 David A. Capello <dacap@users.sourceforge.net>
* src/widgets/fileview.c: Finished with thumbnails generation.
* src/commands/cmd_open_file.c (monitor_free): Added to join the
thread. This fix bugs when you close the program and there're
files loading: all threads are joined.
* src/modules/gui.c (remove_gui_monitor): Added.
(add_gui_monitor): Now it receives a 'free' routine too (to
destroy the 'data' of the monitor).
* src/test/test_errno.c: Added a test to check errno
thread-safety.
2008-02-09 David A. Capello <dacap@users.sourceforge.net>
* src/jinete/jmanager.c (jmanager_remove_msg_filter):
* src/raster/undo.c (chunk_set_mask_invert): Fixed more memory leaks.
2008-02-08 David A. Capello <dacap@users.sourceforge.net>
* src/modules/sprites.c (exit_module_sprites):
* src/core/core.c (core_exit):
* src/widgets/colbar.c (color_bar_msg_proc):
* src/raster/layer.c (layer_free):
* src/jinete/jaccel.c (jaccel_free):
* src/widgets/tabs.c (calculate_hot):
* src/core/dirs.c (dirs_cat_dirs): Fixed more memory leaks
(the leaks in exit routines aren't too critical, but the
other yes).
* src/jinete/jmanager.c (jmanager_generate_messages): Fixed a
memory leak when replacing the value of 'widgets' field of a
JMessage.
* src/jinete/jlist.c (jlist_free): Fixed a big memory leak (for
every linked list JList in the program, the 'list->end' field was
never freed).
* src/core/file_system.c (struct FileItem): Added thumbnail field.
2008-02-04 David A. Capello <dacap@users.sourceforge.net>
* src/dialogs/filesel.c: Done (navigation history added, and

View File

@ -35,3 +35,20 @@ UNINSTALLATION
===================================
Run "make uninstall".
===================================
SUBVERSION
===================================
If you're download ASE from the Subversion repository, after
updating I recommend you to do:
~/ase-trunk/$ make clean
~/ase-trunk/$ ./fix.sh
~/ase-trunk/$ make
Also, you can make dependencies of the files (if you are trying to
hack the ASE source code):
~/ase-trunk/$ sh misc/deps.sh

View File

@ -7,9 +7,12 @@ NEWS
+ Added support to load and save PNG files (through 'libpng').
+ Replaced the "List" menu with the tabs selector.
+ Better file selector.
+ Better file selector with thumbnails.
+ In Windows: now you can navigate through Desktop, My Documents,
My Computer, etc.
+ Optimized the loading/saving operations (using threads).
+ Restructured all the menus (more user friendly options).
- Temporaly removed a lot of complex functionality:
- Temporaly removed a lot of complex functionality:
Mask-Repository (but you can use .msk files yet), Draw-Text,
Layer-Sets and Linked-Cels.
+ New XML format for the menus.

View File

@ -3,8 +3,13 @@ High priority work
- search for TODO;
- rename jcombox.c to jcombobox.c
- remove the jfilesel.c
- remove USE_PRECOMPILED_HEADER
- fix copyright years (2001-2008)
- fix a bug in the film editor when move the separator (panel) outside
the screen (to left or right)
- 'jfile.c' should use 'jxml.c', because there are duplicate code:
two (precarious) XML parsers.
- the user_data of hook_signal should be void*.
- ver por el nuevo load_font de Allegro.
- complete palette operations, and palette editor (it needs a slider
@ -60,14 +65,11 @@ Wish-list
position from the starting point of movement;
+ make drawing the 'marching-ants-rectangle' a prioritaire thing to
draw (when move it).
- for Jinete:
+ add columns handle to list-boxes;
+ add icons handle to all widgets (mainly button, list-items, and labels);
+ add tree widget;
Low priority stuff
------------------
- add more unit-tests.
- test routines: load/save_pic_file, load/save_msk_file,
load/save_col_file.
- fix the fli reader (both Allegro and Gfli): when a frame hasn't

View File

@ -27,7 +27,7 @@
#define PACKAGE "ase"
#define VERSION "0.6"
#define WEBSITE "http://www.aseprite.org/"
#define BUGREPORT "ase-help@lists.sourceforge.net"
#define BUGREPORT "aseprite@googlegroups.com"
#define COPYRIGHT "Copyright (C) 2001-2008 David A. Capello"
#define PRINTF verbose_printf

View File

@ -7,10 +7,10 @@
<box vertical>
<box horizontal>
<box horizontal noborders>
<button text="" name="goback" bevel="2 0 2 0" />
<button text="" name="goforward" bevel="0 2 0 2" />
<button text="" name="goback" bevel="2 0 2 0" tooltip="Go back one folder" />
<button text="" name="goforward" bevel="0 2 0 2" tooltip="Go forward one folder" />
</box>
<button text="" name="goup" />
<button text="" name="goup" tooltip="Up to parent folder\n(Backspace)" />
<combobox name="location" expansive />
</box>
<box vertical expansive name="box" />
@ -23,7 +23,7 @@
<box horizontal expansive />
<box horizontal homogeneous>
<button text="&OK" name="ok" magnetic width="60" />
<button text="&Cancel" />
<button text="&Cancel" name="cancel" />
</box>
</box>
</box>

View File

@ -15,8 +15,8 @@
<label text="Height:" />
</box>
<box vertical homogeneous expansive>
<entry expansive name="width" maxsize=8 magnetic />
<entry expansive name="height" maxsize=8 />
<entry expansive name="width" maxsize=8 magnetic tooltip="Width of the new sprite (in pixels)" />
<entry expansive name="height" maxsize=8 tooltip="Height of the new sprite (in pixels)" />
</box>
</box>
</box>
@ -24,9 +24,9 @@
<box vertical>
<separator text="Color Mode:" left horizontal />
<box vertical homogeneous>
<radio name="radio1" text="&RGB Color" group=1 />
<radio name="radio2" text="&Grayscale" group=1 />
<radio name="radio3" text="&Indexed" group=1 />
<radio name="radio1" text="&RGB Color" group=1 tooltip="RGBA color mode\n(32 bits per pixel)" />
<radio name="radio2" text="&Grayscale" group=1 tooltip="Value and Alpha\n(16 bits per pixel)" />
<radio name="radio3" text="&Indexed" group=1 tooltip="Using a palette of 256 colors\n(8 bits per pixel)" />
</box>
</box>
</box>

View File

@ -7,21 +7,16 @@
Welcome to ASE 0.6
You can find help in ASE Wiki:
http://www.aseprite.org/wiki/
READ THIS!
Report bugs to:
ase-help@lists.sourceforge.net
**********************************************************************
\split
\image nodither.pcx
This is the old drawing method for RGB images. Without dithering.
\next
\image dither.pcx
Now, you can configure to use this new ordered dithering method.
\done
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See "Tool/Options" menu or press <Ctrl+Shift+O>.
Website: http://www.aseprite.org/
Report bugs to: aseprite@googlegroups.com
**********************************************************************
Use the <1>, <2>, <3>, <4>, <5> and <6> keys to set the zoom in the
current editor's viewport.
@ -116,6 +111,16 @@ change the coordinates manually) will be appears.
Select a color in the color-bar using the <Ctrl> key will show you
this mini-palette.
**********************************************************************
\split
\image nodither.pcx
A RGB image without dithering.
\next
\image dither.pcx
Ordered dithering method.
\done
See "Tool/Options" menu or press <Ctrl+Shift+O>.
**********************************************************************
\image lua.pcx
Do you want to write Lua scripts to generate images or create
@ -129,4 +134,4 @@ And remember look for updates in:
http://www.aseprite.org/
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 by David A. Capello
Copyright (C) 2001-2008 by David A. Capello

View File

@ -1,4 +1,4 @@
# Copyright (C) 2001-2005, 2007 by David A. Capello -*-Makefile-*-
# Copyright (C) 2001-2008 by David A. Capello -*-Makefile-*-
# Manual configuration
# (in Unix like systems you can use ./fix.sh script)
@ -12,6 +12,7 @@
#DEBUGMODE = 1
#PROFILE = 1
#MEMLEAK = 1
######################################################################
# Default Unix directory to look for ASE data (to this path will be

View File

@ -25,7 +25,7 @@ ifdef PROFILE
LFLAGS += -pg
else
ifdef DEBUGMODE
CFLAGS += -g3
CFLAGS += -g3 -DDEBUGMODE
LFLAGS += -g3
else
CFLAGS += -s -O3 -DNDEBUG
@ -33,6 +33,10 @@ else
endif
endif
ifdef MEMLEAK
CFLAGS += -DMEMLEAK
endif
ifdef DEFAULT_PREFIX
CFLAGS += -DDEFAULT_PREFIX="\"$(DEFAULT_PREFIX)\""
endif

View File

@ -150,6 +150,7 @@ COMMON_SOURCES = \
src/jinete/jtextbox.c \
src/jinete/jtheme.c \
src/jinete/jthread.c \
src/jinete/jtooltips.c \
src/jinete/jview.c \
src/jinete/jwidget.c \
src/jinete/jwindow.c \
@ -218,11 +219,6 @@ COMMON_SOURCES = \
src/widgets/target.c \
src/widgets/toolbar.c
ifdef WIN32
COMMON_SOURCES += src/core/file_system_win32.c
else
endif
ifdef USE_X86_INT_MULT
COMMON_SOURCES += src/raster/x86/int_mult.s
endif

View File

@ -22,6 +22,11 @@ ifdef DEBUGMODE
else
LFLAGS_LAST = -lalleg
endif
ifdef MEMLEAK
LFLAGS += -lpsapi
endif
WITHICON = 1
######################################################################

View File

@ -1,6 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
* 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -95,6 +95,7 @@ struct FileItem
char *keyname;
int attrib;
#endif
BITMAP *thumbnail;
};
/* the root of the file-system */
@ -275,11 +276,11 @@ bool fileitem_is_browsable(FileItem *fileitem)
assert(fileitem->filename != NULL);
#ifdef USE_PIDLS
return
IS_FOLDER(fileitem) &&
(fileitem->filename[0] != ':' ||
/* My Computer = {20D04FE0-3AEA-1069-A2D8-08002B30309D} */
ustrcmp(fileitem->filename, "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}") == 0);
return IS_FOLDER(fileitem)
&& (ustrcmp(get_extension(fileitem->filename), "zip") != 0)
&& (fileitem->filename[0] != ':' ||
/* My Computer = {20D04FE0-3AEA-1069-A2D8-08002B30309D} */
ustrcmp(fileitem->filename, "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}") == 0);
#else
return IS_FOLDER(fileitem);
#endif
@ -439,6 +440,23 @@ bool fileitem_has_extension(FileItem *fileitem, const char *list_of_extensions)
list_of_extensions);
}
BITMAP *fileitem_get_thumbnail(FileItem *fileitem)
{
assert(fileitem != NULL);
return fileitem->thumbnail;
}
void fileitem_set_thumbnail(FileItem *fileitem, BITMAP *thumbnail)
{
assert(fileitem != NULL);
if (fileitem->thumbnail)
destroy_bitmap(fileitem->thumbnail);
fileitem->thumbnail = thumbnail;
}
static FileItem *fileitem_new(FileItem *parent)
{
FileItem *fileitem = jnew(FileItem, 1);
@ -458,6 +476,7 @@ static FileItem *fileitem_new(FileItem *parent)
fileitem->keyname = NULL;
fileitem->attrib = 0;
#endif
fileitem->thumbnail = NULL;
return fileitem;
}
@ -495,6 +514,9 @@ static void fileitem_free(FileItem *fileitem)
if (fileitem->displayname)
jfree(fileitem->displayname);
if (fileitem->thumbnail)
destroy_bitmap(fileitem->thumbnail);
if (fileitem->children) {
JLink link, next;
JI_LIST_FOR_EACH_SAFE(fileitem->children, link, next) {

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,6 +21,7 @@
#include "jinete/jbase.h"
struct BITMAP;
struct FileItem;
typedef struct FileItem FileItem;
@ -42,5 +43,8 @@ JList fileitem_get_children(FileItem *fileitem);
bool filename_has_extension(const char *filename, const char *list_of_extensions);
bool fileitem_has_extension(FileItem *fileitem, const char *list_of_extensions);
struct BITMAP *fileitem_get_thumbnail(FileItem *fileitem);
void fileitem_set_thumbnail(FileItem *fileitem, struct BITMAP *thumbnail);
#endif /* CORE_FILE_SYSTEM_H */

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -29,6 +29,7 @@
#include "core/cfg.h"
#include "core/dirs.h"
#include "file/file.h"
#include "modules/gfx.h"
#include "modules/gui.h"
#include "widgets/fileview.h"
@ -40,7 +41,7 @@
#endif
#ifndef MAX_PATH
# define MAX_PATH 4096
# define MAX_PATH 4096 /* TODO this is needed for Linux, is it correct? */
#endif
/* Variables used only to maintain the history of navigation. */
@ -64,8 +65,11 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg);
static bool location_msg_proc(JWidget widget, JMessage msg);
static bool filetype_msg_proc(JWidget widget, JMessage msg);
/**
* The routine that shows the dialog to select a file in ASE.
/* Shows the dialog to select a file in ASE.
Mainly it uses:
* the 'core/file_system' routines.
* the 'widgets/fileview' widget.
*/
char *ase_file_selector(const char *message,
const char *init_path,
@ -162,6 +166,8 @@ char *ase_file_selector(const char *message,
jwidget_set_min_size(window, JI_SCREEN_W*9/10, JI_SCREEN_H*9/10);
jwindow_remap(window);
jwindow_center(window);
jwidget_add_tooltip_text(filetype, "hola\nchau");
}
else {
fileview = jwidget_find_name(window, "fileview");
@ -240,6 +246,7 @@ char *ase_file_selector(const char *message,
}
/* TODO why this doesn't work if I remove this? */
fileview_stop_threads(fileview);
jwidget_free(window);
window = NULL;
@ -431,6 +438,7 @@ static void goup_command(JWidget widget)
fileview_goup(fileview);
}
/* hook for the 'fileview' widget in the dialog */
static bool fileview_msg_proc(JWidget widget, JMessage msg)
{
if (msg->type == JM_SIGNAL) {
@ -450,10 +458,12 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg)
break;
}
/* when a file is accepted */
case SIGNAL_FILEVIEW_FILE_ACCEPT:
jwidget_close_window(widget);
break;
/* when the current folder change */
case SIGNAL_FILEVIEW_CURRENT_FOLDER_CHANGED: {
JWidget window = jwidget_get_window(widget);
@ -470,11 +480,14 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg)
return FALSE;
}
/* hook for the 'location' combo-box */
static bool location_msg_proc(JWidget widget, JMessage msg)
{
if (msg->type == JM_SIGNAL) {
switch (msg->signal.num) {
/* when the user change the location we have to set the
current-folder in the 'fileview' widget */
case JI_SIGNAL_COMBOBOX_SELECT: {
FileItem *fileitem =
jcombobox_get_data(widget,
@ -485,6 +498,10 @@ static bool location_msg_proc(JWidget widget, JMessage msg)
"fileview");
fileview_set_current_folder(fileview, fileitem);
/* refocus the 'fileview' (the focus in that widget is more
useful for the user) */
jmanager_set_focus(fileview);
}
break;
}
@ -493,11 +510,14 @@ static bool location_msg_proc(JWidget widget, JMessage msg)
return FALSE;
}
/* hook for the 'filetype' combo-box */
static bool filetype_msg_proc(JWidget widget, JMessage msg)
{
if (msg->type == JM_SIGNAL) {
switch (msg->signal.num) {
/* when the user select a new file-type (extension), we have to
change the file-extension in the 'filename' entry widget */
case JI_SIGNAL_COMBOBOX_SELECT: {
const char *ext = jcombobox_get_selected_string(widget);
JWidget window = jwidget_get_window(widget);

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -72,6 +72,7 @@ ConvMatr *convmatr_new(int w, int h)
if (!convmatr)
return NULL;
convmatr->name = NULL;
convmatr->w = w;
convmatr->h = h;
convmatr->cx = convmatr->w/2;
@ -102,6 +103,9 @@ ConvMatr *convmatr_new_string(const char *format)
void convmatr_free(ConvMatr *convmatr)
{
if (convmatr->name)
jfree(convmatr->name);
if (convmatr->data)
jfree(convmatr->data);

View File

@ -103,11 +103,6 @@ static void ase_file_write_cel_chunk(FILE *f, Cel *cel, Layer *layer, Sprite *sp
static Mask *ase_file_read_mask_chunk(FILE *f);
static void ase_file_write_mask_chunk(FILE *f, Mask *mask);
static int fgetw(FILE *file);
static long fgetl(FILE *file);
static int fputw(int w, FILE *file);
static int fputl(long l, FILE *file);
FileFormat format_ase =
{
"ase,aseprite",
@ -275,9 +270,16 @@ static bool load_ASE(FileOp *fop)
}
fop->sprite = sprite;
fclose(f);
return TRUE;
if (ferror(f)) {
fop_error(fop, _("Error reading file.\n"));
fclose(f);
return FALSE;
}
else {
fclose(f);
return TRUE;
}
}
static bool save_ASE(FileOp *fop)
@ -333,8 +335,16 @@ static bool save_ASE(FileOp *fop)
/* write the header */
ase_file_write_header(f, &header);
fclose(f);
return TRUE;
if (ferror(f)) {
fop_error(fop, _("Error writing file.\n"));
fclose(f);
return FALSE;
}
else {
fclose(f);
return TRUE;
}
}
static bool ase_file_read_header(FILE *f, ASE_Header *header)
@ -953,139 +963,3 @@ static void ase_file_write_mask_chunk(FILE *f, Mask *mask)
ase_file_write_close_chunk(f);
}
/* returns a word (16 bits) */
static int fgetw(FILE *file)
{
int b1, b2;
b1 = fgetc(file);
if (b1 == EOF)
return EOF;
b2 = fgetc(file);
if (b2 == EOF)
return EOF;
/* little endian */
return ((b2 << 8) | b1);
}
/* returns a dword (32 bits) */
static long fgetl(FILE *file)
{
int b1, b2, b3, b4;
b1 = fgetc(file);
if (b1 == EOF)
return EOF;
b2 = fgetc(file);
if (b2 == EOF)
return EOF;
b3 = fgetc(file);
if (b3 == EOF)
return EOF;
b4 = fgetc(file);
if (b4 == EOF)
return EOF;
/* little endian */
return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
}
/* returns 0 in success or -1 in error */
static int fputw(int w, FILE *file)
{
int b1, b2;
/* little endian */
b2 = (w & 0xFF00) >> 8;
b1 = w & 0x00FF;
if (fputc(b1, file) == b1)
if (fputc(b2, file) == b2)
return 0;
return -1;
}
/* returns 0 in success or -1 in error */
static int fputl(long l, FILE *file)
{
int b1, b2, b3, b4;
/* little endian */
b4 = (int)((l & 0xFF000000L) >> 24);
b3 = (int)((l & 0x00FF0000L) >> 16);
b2 = (int)((l & 0x0000FF00L) >> 8);
b1 = (int)l & 0x00FF;
if (fputc(b1, file) == b1)
if (fputc(b2, file) == b2)
if (fputc(b3, file) == b3)
if (fputc(b4, file) == b4)
return 0;
return -1;
}
#if 0
/* returns a floating point (32 bits) */
static float fgetf(FILE *file)
{
union {
float f;
long l;
} packet;
packet.l = fgetl(file);
return packet.f;
}
/* returns a floating point with double precision (64 bits) */
static double fgetd(FILE *file)
{
union {
double d;
long l[2];
} packet;
packet.l[0] = fgetl(file);
packet.l[1] = fgetl(file);
return packet.d;
}
/* returns 0 in success or -1 in error */
static int fputf(float c, FILE *file)
{
union {
float f;
long l;
} packet;
packet.f = c;
return fputl(packet.l, file);
}
/* returns 0 in success or -1 in error */
static int fputd(double c, FILE *file)
{
union {
double d;
long l[2];
} packet;
packet.d = c;
if (fputl(packet.l[0], file) == 0)
if (fputl(packet.l[1], file) == 0)
return 0;
return -1;
}
#endif

View File

@ -23,7 +23,6 @@
#ifndef USE_PRECOMPILED_HEADER
#include <allegro/color.h>
#include <allegro/file.h>
#include "file/file.h"
#include "raster/raster.h"
@ -98,13 +97,13 @@ typedef struct OS2BMPINFOHEADER /* size: 12 */
/* read_bmfileheader:
* Reads a BMP file header and check that it has the BMP magic number.
*/
static int read_bmfileheader(PACKFILE *f, BITMAPFILEHEADER *fileheader)
static int read_bmfileheader(FILE *f, BITMAPFILEHEADER *fileheader)
{
fileheader->bfType = pack_igetw(f);
fileheader->bfSize= pack_igetl(f);
fileheader->bfReserved1= pack_igetw(f);
fileheader->bfReserved2= pack_igetw(f);
fileheader->bfOffBits= pack_igetl(f);
fileheader->bfType = fgetw(f);
fileheader->bfSize= fgetl(f);
fileheader->bfReserved1= fgetw(f);
fileheader->bfReserved2= fgetw(f);
fileheader->bfOffBits= fgetl(f);
if (fileheader->bfType != 19778)
return -1;
@ -115,20 +114,20 @@ static int read_bmfileheader(PACKFILE *f, BITMAPFILEHEADER *fileheader)
/* read_win_bminfoheader:
* Reads information from a BMP file header.
*/
static int read_win_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader)
static int read_win_bminfoheader(FILE *f, BITMAPINFOHEADER *infoheader)
{
WINBMPINFOHEADER win_infoheader;
win_infoheader.biWidth = pack_igetl(f);
win_infoheader.biHeight = pack_igetl(f);
win_infoheader.biPlanes = pack_igetw(f);
win_infoheader.biBitCount = pack_igetw(f);
win_infoheader.biCompression = pack_igetl(f);
win_infoheader.biSizeImage = pack_igetl(f);
win_infoheader.biXPelsPerMeter = pack_igetl(f);
win_infoheader.biYPelsPerMeter = pack_igetl(f);
win_infoheader.biClrUsed = pack_igetl(f);
win_infoheader.biClrImportant = pack_igetl(f);
win_infoheader.biWidth = fgetl(f);
win_infoheader.biHeight = fgetl(f);
win_infoheader.biPlanes = fgetw(f);
win_infoheader.biBitCount = fgetw(f);
win_infoheader.biCompression = fgetl(f);
win_infoheader.biSizeImage = fgetl(f);
win_infoheader.biXPelsPerMeter = fgetl(f);
win_infoheader.biYPelsPerMeter = fgetl(f);
win_infoheader.biClrUsed = fgetl(f);
win_infoheader.biClrImportant = fgetl(f);
infoheader->biWidth = win_infoheader.biWidth;
infoheader->biHeight = win_infoheader.biHeight;
@ -141,14 +140,14 @@ static int read_win_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader)
/* read_os2_bminfoheader:
* Reads information from an OS/2 format BMP file header.
*/
static int read_os2_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader)
static int read_os2_bminfoheader(FILE *f, BITMAPINFOHEADER *infoheader)
{
OS2BMPINFOHEADER os2_infoheader;
os2_infoheader.biWidth = pack_igetw(f);
os2_infoheader.biHeight = pack_igetw(f);
os2_infoheader.biPlanes = pack_igetw(f);
os2_infoheader.biBitCount = pack_igetw(f);
os2_infoheader.biWidth = fgetw(f);
os2_infoheader.biHeight = fgetw(f);
os2_infoheader.biPlanes = fgetw(f);
os2_infoheader.biBitCount = fgetw(f);
infoheader->biWidth = os2_infoheader.biWidth;
infoheader->biHeight = os2_infoheader.biHeight;
@ -161,24 +160,24 @@ static int read_os2_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader)
/* read_bmicolors:
* Loads the color palette for 1,4,8 bit formats.
*/
static void read_bmicolors(FileOp *fop, int ncols, PACKFILE *f,int win_flag)
static void read_bmicolors(FileOp *fop, int ncols, FILE *f,int win_flag)
{
int i, r, g, b;
for (i=0; i<ncols; i++) {
b = pack_getc(f) / 4;
g = pack_getc(f) / 4;
r = pack_getc(f) / 4;
b = fgetc(f) / 4;
g = fgetc(f) / 4;
r = fgetc(f) / 4;
fop_sequence_set_color(fop, i, r, g, b);
if (win_flag)
pack_getc(f);
fgetc(f);
}
}
/* read_1bit_line:
* Support function for reading the 1 bit bitmap file format.
*/
static void read_1bit_line(int length, PACKFILE *f, Image *image, int line)
static void read_1bit_line(int length, FILE *f, Image *image, int line)
{
unsigned char b[32];
unsigned long n;
@ -188,7 +187,12 @@ static void read_1bit_line(int length, PACKFILE *f, Image *image, int line)
for (i=0; i<length; i++) {
j = i % 32;
if (j == 0) {
n = pack_mgetl(f);
n = fgetl(f);
n =
((n&0x000000ff)<<24) |
((n&0x0000ff00)<< 8) |
((n&0x00ff0000)>> 8) |
((n&0xff000000)>>24);
for (k=0; k<32; k++) {
b[31-k] = (char)(n & 1);
n = n >> 1;
@ -202,7 +206,7 @@ static void read_1bit_line(int length, PACKFILE *f, Image *image, int line)
/* read_4bit_line:
* Support function for reading the 4 bit bitmap file format.
*/
static void read_4bit_line(int length, PACKFILE *f, Image *image, int line)
static void read_4bit_line(int length, FILE *f, Image *image, int line)
{
unsigned char b[8];
unsigned long n;
@ -213,7 +217,7 @@ static void read_4bit_line(int length, PACKFILE *f, Image *image, int line)
for (i=0; i<length; i++) {
j = i % 8;
if (j == 0) {
n = pack_igetl(f);
n = fgetl(f);
for (k=0; k<4; k++) {
temp = n & 255;
b[k*2+1] = temp & 15;
@ -230,7 +234,7 @@ static void read_4bit_line(int length, PACKFILE *f, Image *image, int line)
/* read_8bit_line:
* Support function for reading the 8 bit bitmap file format.
*/
static void read_8bit_line(int length, PACKFILE *f, Image *image, int line)
static void read_8bit_line(int length, FILE *f, Image *image, int line)
{
unsigned char b[4];
unsigned long n;
@ -240,7 +244,7 @@ static void read_8bit_line(int length, PACKFILE *f, Image *image, int line)
for (i=0; i<length; i++) {
j = i % 4;
if (j == 0) {
n = pack_igetl(f);
n = fgetl(f);
for (k=0; k<4; k++) {
b[k] = (char)(n & 255);
n = n >> 8;
@ -255,7 +259,7 @@ static void read_8bit_line(int length, PACKFILE *f, Image *image, int line)
* Support function for reading the 24 bit bitmap file format, doing
* our best to convert it down to a 256 color palette.
*/
static void read_24bit_line(int length, PACKFILE *f, Image *image, int line)
static void read_24bit_line(int length, FILE *f, Image *image, int line)
{
int i, nbytes;
RGB c;
@ -263,9 +267,9 @@ static void read_24bit_line(int length, PACKFILE *f, Image *image, int line)
nbytes=0;
for (i=0; i<length; i++) {
c.b = pack_getc(f);
c.g = pack_getc(f);
c.r = pack_getc(f);
c.b = fgetc(f);
c.g = fgetc(f);
c.r = fgetc(f);
image_putpixel(image, i, line, _rgba(c.r, c.g, c.b, 255));
nbytes += 3;
}
@ -273,13 +277,13 @@ static void read_24bit_line(int length, PACKFILE *f, Image *image, int line)
nbytes = nbytes % 4;
if (nbytes != 0)
for (i=nbytes; i<4; i++)
pack_getc(f);
fgetc(f);
}
/* read_image:
* For reading the noncompressed BMP image format.
*/
static void read_image(PACKFILE *f, Image *image, AL_CONST BITMAPINFOHEADER *infoheader, FileOp *fop)
static void read_image(FILE *f, Image *image, AL_CONST BITMAPINFOHEADER *infoheader, FileOp *fop)
{
int i, line;
@ -306,13 +310,15 @@ static void read_image(PACKFILE *f, Image *image, AL_CONST BITMAPINFOHEADER *inf
}
fop_progress(fop, (float)(i+1) / (float)(infoheader->biHeight));
if (fop_is_stop(fop))
break;
}
}
/* read_RLE8_compressed_image:
* For reading the 8 bit RLE compressed BMP image format.
*/
static void read_RLE8_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMAPINFOHEADER *infoheader)
static void read_RLE8_compressed_image(FILE *f, Image *image, AL_CONST BITMAPINFOHEADER *infoheader)
{
unsigned char count, val, val0;
int j, pos, line;
@ -326,8 +332,8 @@ static void read_RLE8_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMA
eolflag = 0; /* end of line flag */
while ((eolflag == 0) && (eopicflag == 0)) {
count = pack_getc(f);
val = pack_getc(f);
count = fgetc(f);
val = fgetc(f);
if (count > 0) { /* repeat pixel count times */
for (j=0;j<count;j++) {
@ -347,21 +353,21 @@ static void read_RLE8_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMA
break;
case 2: /* displace picture */
count = pack_getc(f);
val = pack_getc(f);
count = fgetc(f);
val = fgetc(f);
pos += count;
line -= val;
break;
default: /* read in absolute mode */
for (j=0; j<val; j++) {
val0 = pack_getc(f);
val0 = fgetc(f);
image_putpixel(image, pos, line, val0);
pos++;
}
if (j%2 == 1)
val0 = pack_getc(f); /* align on word boundary */
val0 = fgetc(f); /* align on word boundary */
break;
}
@ -380,7 +386,7 @@ static void read_RLE8_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMA
/* read_RLE4_compressed_image:
* For reading the 4 bit RLE compressed BMP image format.
*/
static void read_RLE4_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMAPINFOHEADER *infoheader)
static void read_RLE4_compressed_image(FILE *f, Image *image, AL_CONST BITMAPINFOHEADER *infoheader)
{
unsigned char b[8];
unsigned char count;
@ -396,8 +402,8 @@ static void read_RLE4_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMA
eolflag = 0; /* end of line flag */
while ((eolflag == 0) && (eopicflag == 0)) {
count = pack_getc(f);
val = pack_getc(f);
count = fgetc(f);
val = fgetc(f);
if (count > 0) { /* repeat pixels count times */
b[1] = val & 15;
@ -419,8 +425,8 @@ static void read_RLE4_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMA
break;
case 2: /* displace image */
count = pack_getc(f);
val = pack_getc(f);
count = fgetc(f);
val = fgetc(f);
pos += count;
line -= val;
break;
@ -428,7 +434,7 @@ static void read_RLE4_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMA
default: /* read in absolute mode */
for (j=0; j<val; j++) {
if ((j%4) == 0) {
val0 = pack_igetw(f);
val0 = fgetw(f);
for (k=0; k<2; k++) {
b[2*k+1] = val0 & 15;
val0 = val0 >> 4;
@ -453,7 +459,7 @@ static void read_RLE4_compressed_image(PACKFILE *f, Image *image, AL_CONST BITMA
}
}
static void read_bitfields_image(PACKFILE *f, Image *image, int bpp, BITMAPINFOHEADER *infoheader)
static void read_bitfields_image(FILE *f, Image *image, int bpp, BITMAPINFOHEADER *infoheader)
{
int k, i;
int bytesPerPixel;
@ -467,7 +473,7 @@ static void read_bitfields_image(PACKFILE *f, Image *image, int bpp, BITMAPINFOH
for (i=0; i<(int)infoheader->biHeight; i++) {
for (k=0; k<(int)infoheader->biWidth; k++) {
pack_fread(&buffer, bytesPerPixel, f);
fread(&buffer, 1, bytesPerPixel, f);
if (bpp == 15) {
red = (buffer >> 10) & 0x1f;
@ -503,25 +509,25 @@ static bool load_BMP(FileOp *fop)
BITMAPFILEHEADER fileheader;
BITMAPINFOHEADER infoheader;
Image *image;
PACKFILE *f;
FILE *f;
int ncol;
unsigned long biSize;
int type, bpp = 0;
f = pack_fopen(fop->filename, F_READ);
f = fopen(fop->filename, "rb");
if (!f)
return FALSE;
if (read_bmfileheader(f, &fileheader) != 0) {
pack_fclose(f);
fclose(f);
return FALSE;
}
biSize = pack_igetl(f);
biSize = fgetl(f);
if (biSize == WININFOHEADERSIZE) {
if (read_win_bminfoheader(f, &infoheader) != 0) {
pack_fclose(f);
fclose(f);
return FALSE;
}
/* compute number of colors recorded */
@ -532,7 +538,7 @@ static bool load_BMP(FileOp *fop)
}
else if (biSize == OS2INFOHEADERSIZE) {
if (read_os2_bminfoheader(f, &infoheader) != 0) {
pack_fclose(f);
fclose(f);
return FALSE;
}
/* compute number of colors recorded */
@ -542,7 +548,7 @@ static bool load_BMP(FileOp *fop)
read_bmicolors(fop, ncol, f, 0);
}
else {
pack_fclose(f);
fclose(f);
return FALSE;
}
@ -554,9 +560,9 @@ static bool load_BMP(FileOp *fop)
if (infoheader.biCompression == BI_BITFIELDS) {
unsigned long redMask, bluMask;
redMask = pack_igetl(f);
pack_igetl(f);
bluMask = pack_igetl(f);
redMask = fgetl(f);
fgetl(f);
bluMask = fgetl(f);
if ((bluMask == 0x001f) && (redMask == 0x7C00))
bpp = 15;
@ -566,7 +572,7 @@ static bool load_BMP(FileOp *fop)
bpp = 32;
else {
/* Unrecognised bit masks/depth */
pack_fclose(f);
fclose(f);
return FALSE;
}
}
@ -575,7 +581,7 @@ static bool load_BMP(FileOp *fop)
infoheader.biWidth,
infoheader.biHeight);
if (!image) {
pack_fclose(f);
fclose(f);
return FALSE;
}
@ -603,18 +609,25 @@ static bool load_BMP(FileOp *fop)
break;
default:
pack_fclose(f);
fclose(f);
return FALSE;
}
pack_fclose(f);
return TRUE;
if (ferror(f)) {
fop_error(fop, _("Error reading file.\n"));
fclose(f);
return FALSE;
}
else {
fclose(f);
return TRUE;
}
}
static bool save_BMP(FileOp *fop)
{
Image *image = fop->seq.image;
PACKFILE *f;
FILE *f;
int bfSize;
int biSizeImage;
int bpp = (image->imgtype == IMAGE_RGB) ? 24 : 8;
@ -632,52 +645,50 @@ static bool save_BMP(FileOp *fop)
bfSize = 54 + biSizeImage; /* header + image data */
}
f = pack_fopen(fop->filename, F_WRITE);
f = fopen(fop->filename, "wb");
if (!f) {
fop_error(fop, _("Error creating file.\n"));
return FALSE;
}
*allegro_errno = 0;
/* file_header */
pack_iputw(0x4D42, f); /* bfType ("BM") */
pack_iputl(bfSize, f); /* bfSize */
pack_iputw(0, f); /* bfReserved1 */
pack_iputw(0, f); /* bfReserved2 */
fputw(0x4D42, f); /* bfType ("BM") */
fputl(bfSize, f); /* bfSize */
fputw(0, f); /* bfReserved1 */
fputw(0, f); /* bfReserved2 */
if (bpp == 8) /* bfOffBits */
pack_iputl(54+256*4, f);
if (bpp == 8) /* bfOffBits */
fputl(54+256*4, f);
else
pack_iputl(54, f);
fputl(54, f);
/* info_header */
pack_iputl(40, f); /* biSize */
pack_iputl(image->w, f); /* biWidth */
pack_iputl(image->h, f); /* biHeight */
pack_iputw(1, f); /* biPlanes */
pack_iputw(bpp, f); /* biBitCount */
pack_iputl(0, f); /* biCompression */
pack_iputl(biSizeImage, f); /* biSizeImage */
pack_iputl(0xB12, f); /* biXPelsPerMeter (0xB12 = 72 dpi) */
pack_iputl(0xB12, f); /* biYPelsPerMeter */
fputl(40, f); /* biSize */
fputl(image->w, f); /* biWidth */
fputl(image->h, f); /* biHeight */
fputw(1, f); /* biPlanes */
fputw(bpp, f); /* biBitCount */
fputl(0, f); /* biCompression */
fputl(biSizeImage, f); /* biSizeImage */
fputl(0xB12, f); /* biXPelsPerMeter (0xB12 = 72 dpi) */
fputl(0xB12, f); /* biYPelsPerMeter */
if (bpp == 8) {
pack_iputl(256, f); /* biClrUsed */
pack_iputl(256, f); /* biClrImportant */
fputl(256, f); /* biClrUsed */
fputl(256, f); /* biClrImportant */
/* palette */
for (i=0; i<256; i++) {
fop_sequence_get_color(fop, i, &r, &g, &b);
pack_putc(_rgb_scale_6[b], f);
pack_putc(_rgb_scale_6[g], f);
pack_putc(_rgb_scale_6[r], f);
pack_putc(0, f);
fputc(_rgb_scale_6[b], f);
fputc(_rgb_scale_6[g], f);
fputc(_rgb_scale_6[r], f);
fputc(0, f);
}
}
else {
pack_iputl(0, f); /* biClrUsed */
pack_iputl(0, f); /* biClrImportant */
fputl(0, f); /* biClrUsed */
fputl(0, f); /* biClrImportant */
}
/* image data */
@ -685,30 +696,31 @@ static bool save_BMP(FileOp *fop)
for (j=0; j<image->w; j++) {
if (bpp == 8) {
if (image->imgtype == IMAGE_INDEXED)
pack_putc(image->method->getpixel(image, j, i), f);
fputc(image->method->getpixel(image, j, i), f);
else if (image->imgtype == IMAGE_GRAYSCALE)
pack_putc(_graya_getk(image->method->getpixel(image, j, i)), f);
fputc(_graya_getk(image->method->getpixel(image, j, i)), f);
}
else {
c = image->method->getpixel(image, j, i);
pack_putc(_rgba_getb(c), f);
pack_putc(_rgba_getg(c), f);
pack_putc(_rgba_getr(c), f);
fputc(_rgba_getb(c), f);
fputc(_rgba_getg(c), f);
fputc(_rgba_getr(c), f);
}
}
for (j=0; j<filler; j++)
pack_putc(0, f);
fputc(0, f);
fop_progress(fop, (float)(image->h-i) / (float)image->h);
}
pack_fclose(f);
if (*allegro_errno) {
fop_error(fop, _("Error writing bytes.\n"));
if (ferror(f)) {
fop_error(fop, _("Error writing file.\n"));
fclose(f);
return FALSE;
}
else
else {
fclose(f);
return TRUE;
}
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -106,12 +106,14 @@ void get_writable_extensions(char *buf, int size)
Sprite *sprite_load(const char *filename)
{
Sprite *sprite;
FileOp *fop = fop_to_load_sprite(filename);
/* TODO add a option to configure what to do with the sequence */
FileOp *fop = fop_to_load_sprite(filename, FILE_LOAD_SEQUENCE_NONE);
if (!fop)
return NULL;
/* operate in this same thread */
fop_operate(fop);
fop_done(fop);
if (fop->error)
console_printf(fop->error);
@ -131,6 +133,7 @@ int sprite_save(Sprite *sprite)
/* operate in this same thread */
fop_operate(fop);
fop_done(fop);
if (fop->error)
console_printf(fop->error);
@ -141,7 +144,7 @@ int sprite_save(Sprite *sprite)
return ret;
}
FileOp *fop_to_load_sprite(const char *filename)
FileOp *fop_to_load_sprite(const char *filename, int flags)
{
char *extension;
FileOp *fop;
@ -172,51 +175,56 @@ FileOp *fop_to_load_sprite(const char *filename)
/* use the "sequence" interface */
if (fop->format->flags & FILE_SUPPORT_SEQUENCES) {
char buf[512], left[512], right[512];
int c, width, start_from;
/* prepare to load a sequence */
fop_prepare_for_sequence(fop);
/* first of all, we must generate the list of files to load in the
sequence... */
/* per now, we want load just one file */
jlist_append(fop->seq.filename_list, jstrdup(filename));
/* check is this could be a sequence */
start_from = split_filename(filename, left, right, &width);
if (start_from >= 0) {
/* try to get more file names */
for (c=start_from+1; ; c++) {
/* get the next file name */
usprintf(buf, "%s%0*d%s", left, width, c, right);
/* don't load the sequence (just the one file/one frame) */
if (!(flags & FILE_LOAD_SEQUENCE_NONE)) {
char buf[512], left[512], right[512];
int c, width, start_from;
/* if the file doesn't exist, we doesn't need more files to load */
if (!exists(buf))
break;
/* first of all, we must generate the list of files to load in the
sequence... */
/* add this file name to the list */
jlist_append(fop->seq.filename_list,
jstrdup(buf));
/* check is this could be a sequence */
start_from = split_filename(filename, left, right, &width);
if (start_from >= 0) {
/* try to get more file names */
for (c=start_from+1; ; c++) {
/* get the next file name */
usprintf(buf, "%s%0*d%s", left, width, c, right);
/* if the file doesn't exist, we doesn't need more files to load */
if (!exists(buf))
break;
/* add this file name to the list */
jlist_append(fop->seq.filename_list,
jstrdup(buf));
}
}
}
/* TODO add a better dialog to edit file-names */
if (is_interactive()) {
/* really want load all files? */
if ((jlist_length(fop->seq.filename_list) > 1) &&
(jalert(_("Notice"
"<<Possible animation with:"
"<<%s"
"<<Load the sequence of bitmaps?"
"||&Agree||&Skip"),
get_filename(filename)) != 1)) {
/* if the user replies "Skip", we need just one file name (the
first one) */
while (jlist_length(fop->seq.filename_list) > 1) {
JLink link = jlist_last(fop->seq.filename_list);
jfree(link->data);
jlist_delete_link(fop->seq.filename_list, link);
/* TODO add a better dialog to edit file-names */
if ((flags & FILE_LOAD_SEQUENCE_ASK) &&
is_interactive()) {
/* really want load all files? */
if ((jlist_length(fop->seq.filename_list) > 1) &&
(jalert(_("Notice"
"<<Possible animation with:"
"<<%s"
"<<Load the sequence of bitmaps?"
"||&Agree||&Skip"),
get_filename(filename)) != 1)) {
/* if the user replies "Skip", we need just one file name (the
first one) */
while (jlist_length(fop->seq.filename_list) > 1) {
JLink link = jlist_last(fop->seq.filename_list);
jfree(link->data);
jlist_delete_link(fop->seq.filename_list, link);
}
}
}
}
@ -224,6 +232,10 @@ FileOp *fop_to_load_sprite(const char *filename)
else
fop->filename = jstrdup(filename);
/* load just one frame */
if (flags & FILE_LOAD_ONE_FRAME)
fop->oneframe = TRUE;
done:;
jfree(extension);
return fop;
@ -414,7 +426,7 @@ FileOp *fop_to_save_sprite(Sprite *sprite)
* It can be called from a different thread of the one used
* by @ref fop_to_load_sprite or @ref fop_to_save_sprite.
*
* After operate you must to free the 'fop' calling @ref fop_free.
* After operate you must to mark the 'fop' as 'done' using @ref fop_done.
*/
void fop_operate(FileOp *fop)
{
@ -617,6 +629,15 @@ void fop_operate(FileOp *fop)
}
}
/* progress = 100% */
fop_progress(fop, 1.0f);
}
/**
* After mark the 'fop' as 'done' you must to free it calling @ref fop_free.
*/
void fop_done(FileOp *fop)
{
/* finally done */
jmutex_lock(fop->mutex);
{
@ -625,6 +646,16 @@ void fop_operate(FileOp *fop)
jmutex_unlock(fop->mutex);
}
void fop_stop(FileOp *fop)
{
jmutex_lock(fop->mutex);
{
if (!fop->done)
fop->stop = TRUE;
}
jmutex_unlock(fop->mutex);
}
void fop_free(FileOp *fop)
{
if (fop->filename)
@ -814,14 +845,16 @@ static FileOp *fop_new(FileOpType type)
return NULL;
fop->type = type;
fop->format = NULL;
fop->sprite = NULL;
fop->error = NULL;
fop->filename = NULL;
fop->mutex = jmutex_new();
fop->progress = 0.0f;
fop->error = NULL;
fop->done = FALSE;
fop->stop = FALSE;
fop->oneframe = FALSE;
fop->seq.filename_list = NULL;
fop->seq.palette = NULL;
@ -925,3 +958,94 @@ static int split_filename(const char *filename, char *left, char *right, int *wi
return ret;
}
/**
* Reads a WORD (16 bits) using in little-endian byte ordering.
*/
int fgetw(FILE *file)
{
int b1, b2;
b1 = fgetc(file);
if (b1 == EOF)
return EOF;
b2 = fgetc(file);
if (b2 == EOF)
return EOF;
/* little endian */
return ((b2 << 8) | b1);
}
/**
* Reads a DWORD (32 bits) using in little-endian byte ordering.
*/
long fgetl(FILE *file)
{
int b1, b2, b3, b4;
b1 = fgetc(file);
if (b1 == EOF)
return EOF;
b2 = fgetc(file);
if (b2 == EOF)
return EOF;
b3 = fgetc(file);
if (b3 == EOF)
return EOF;
b4 = fgetc(file);
if (b4 == EOF)
return EOF;
/* little endian */
return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
}
/**
* Writes a word using in little-endian byte ordering.
*
* @return 0 in success or -1 in error
*/
int fputw(int w, FILE *file)
{
int b1, b2;
/* little endian */
b2 = (w & 0xFF00) >> 8;
b1 = w & 0x00FF;
if (fputc(b1, file) == b1)
if (fputc(b2, file) == b2)
return 0;
return -1;
}
/**
* Writes DWORD a using in little-endian byte ordering.
*
* @return 0 in success or -1 in error
*/
int fputl(long l, FILE *file)
{
int b1, b2, b3, b4;
/* little endian */
b4 = (int)((l & 0xFF000000L) >> 24);
b3 = (int)((l & 0x00FF0000L) >> 16);
b2 = (int)((l & 0x0000FF00L) >> 8);
b1 = (int)l & 0x00FF;
if (fputc(b1, file) == b1)
if (fputc(b2, file) == b2)
if (fputc(b3, file) == b3)
if (fputc(b4, file) == b4)
return 0;
return -1;
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,6 +21,7 @@
#include "jinete/jbase.h"
#include <allegro/color.h>
#include <stdio.h>
#define FILE_SUPPORT_RGB (1<<0)
#define FILE_SUPPORT_RGBA (1<<1)
@ -34,6 +35,11 @@
#define FILE_SUPPORT_MASKS_REPOSITORY (1<<9)
#define FILE_SUPPORT_PATHS_REPOSITORY (1<<10)
#define FILE_LOAD_SEQUENCE_NONE (1<<0)
#define FILE_LOAD_SEQUENCE_ASK (1<<1)
#define FILE_LOAD_SEQUENCE_YES (1<<2)
#define FILE_LOAD_ONE_FRAME (1<<3)
struct Image;
struct Cel;
struct Layer;
@ -71,6 +77,9 @@ typedef struct FileOp
char *error; /* error string */
bool done : 1; /* true if the operation finished */
bool stop : 1; /* force the break of the operation */
bool oneframe : 1; /* load just one frame (in formats
that support animation like
GIF/FLI/ASE) */
/* data for sequences */
struct {
@ -99,9 +108,11 @@ int sprite_save(struct Sprite *sprite);
/* low-level routines to load/save sprites */
FileOp *fop_to_load_sprite(const char *filename);
FileOp *fop_to_load_sprite(const char *filename, int flags);
FileOp *fop_to_save_sprite(struct Sprite *sprite);
void fop_operate(FileOp *fop);
void fop_done(FileOp *fop);
void fop_stop(FileOp *fop);
void fop_free(FileOp *fop);
void fop_sequence_set_color(FileOp *fop, int index, int r, int g, int b);
@ -115,4 +126,9 @@ float fop_get_progress(FileOp *fop);
bool fop_is_done(FileOp *fop);
bool fop_is_stop(FileOp *fop);
int fgetw(FILE *file);
long fgetl(FILE *file);
int fputw(int w, FILE *file);
int fputl(long l, FILE *file);
#endif /* FILE_H */

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -64,8 +64,7 @@ static bool load_FLI(FileOp *fop)
unsigned char cmap[768];
unsigned char omap[768];
s_fli_header fli_header;
bool inc_frpos_out;
Image *bmp, *old;
Image *bmp, *old, *image;
Sprite *sprite;
Layer *layer;
PALETTE pal;
@ -73,6 +72,7 @@ static bool load_FLI(FileOp *fop)
int frpos_in;
int frpos_out;
int index = 0;
Cel *cel;
FILE *f;
/* open the file to read in binary mode */
@ -83,6 +83,12 @@ static bool load_FLI(FileOp *fop)
fli_read_header(f, &fli_header);
fseek(f, 128, SEEK_SET);
if (fli_header.magic == NO_HEADER) {
fop_error(fop, _("The file doesn't have a FLIC header\n"));
fclose(f);
return FALSE;
}
/* size by frame */
w = fli_header.width;
h = fli_header.height;
@ -91,7 +97,7 @@ static bool load_FLI(FileOp *fop)
bmp = image_new(IMAGE_INDEXED, w, h);
old = image_new(IMAGE_INDEXED, w, h);
if ((!bmp) || (!old)) {
fop_error(fop, _("Not enough memory for temporary bitmaps.\n"));
fop_error(fop, _("Not enough memory.\n"));
if (bmp) image_free(bmp);
if (old) image_free(old);
fclose(f);
@ -109,8 +115,6 @@ static bool load_FLI(FileOp *fop)
sprite_set_speed(sprite, fli_header.speed);
/* write frame by frame */
inc_frpos_out = FALSE;
for (frpos_in=frpos_out=0;
frpos_in<sprite->frames;
frpos_in++) {
@ -119,28 +123,58 @@ static bool load_FLI(FileOp *fop)
(unsigned char *)old->dat, omap,
(unsigned char *)bmp->dat, cmap);
/* first frame or the frames changes */
if ((frpos_in == 0) || (image_count_diff(old, bmp))) {
/* first frame, or the frames changes, or the palette changes */
if ((frpos_in == 0) ||
(image_count_diff(old, bmp))
#ifndef USE_LINK /* TODO this should be configurable through a check-box */
|| (memcmp(omap, cmap, 768) != 0)
#endif
) {
/* the image changes? */
if (frpos_in != 0)
frpos_out++;
/* add the new frame */
index = stock_add_image(sprite->stock, image_new_copy(bmp));
layer_add_cel(layer, cel_new(frpos_out, index));
image = image_new_copy(bmp);
if (!image) {
fop_error(fop, _("Not enough memory\n"));
break;
}
index = stock_add_image(sprite->stock, image);
if (index < 0) {
image_free(image);
fop_error(fop, _("Not enough memory\n"));
break;
}
cel = cel_new(frpos_out, index);
if (!cel) {
fop_error(fop, _("Not enough memory\n"));
break;
}
layer_add_cel(layer, cel);
/* first frame or the palette changes */
if ((frpos_in == 0) || (memcmp(omap, cmap, 768) != 0))
SETPAL();
}
#ifdef USE_LINK
/* the palette changes */
else if (memcmp(omap, cmap, 768) != 0) {
frpos_out++;
SETPAL();
/* add link */
layer_add_cel(layer, cel_new(frpos_out, index));
cel = cel_new(frpos_out, index);
if (!cel) {
fop_error(fop, _("Not enough memory\n"));
break;
}
layer_add_cel(layer, cel);
}
#endif
/* the palette and the image don't change: add duration to the last added frame */
else {
sprite_set_frlen(sprite,
@ -154,6 +188,12 @@ static bool load_FLI(FileOp *fop)
/* update progress */
fop_progress(fop, (float)(frpos_in+1) / (float)(sprite->frames));
if (fop_is_stop(fop))
break;
/* just one frame? */
if (fop->oneframe)
break;
}
/* update sprites frames */

View File

@ -1,11 +1,13 @@
#include <allegro.h>
#include "format.h"
#include "lzw.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <allegro.h>
#include "file/gif/format.h"
#include "file/gif/lzw.h"
#include "file/file.h"
GIF_ANIMATION *
gif_create_animation(int frames_count)
{
@ -24,37 +26,37 @@ gif_destroy_animation (GIF_ANIMATION *gif)
for (i = 0; i < gif->frames_count; i++)
{
GIF_FRAME *frame = gif->frames + i;
GIF_FRAME *frame = gif->frames + i;
if (frame->bitmap_8_bit)
free (frame->bitmap_8_bit);
if (frame->bitmap_8_bit)
free (frame->bitmap_8_bit);
}
free (gif->frames);
free (gif);
}
static void
write_palette (PACKFILE *file, GIF_PALETTE *palette, int bits)
write_palette (FILE *file, GIF_PALETTE *palette, int bits)
{
int i;
for (i = 0; i < (1 << bits); i++)
{
pack_putc (palette->colors[i].r, file);
pack_putc (palette->colors[i].g, file);
pack_putc (palette->colors[i].b, file);
fputc (palette->colors[i].r, file);
fputc (palette->colors[i].g, file);
fputc (palette->colors[i].b, file);
}
}
static void
read_palette (PACKFILE * file, GIF_PALETTE *palette)
read_palette (FILE * file, GIF_PALETTE *palette)
{
int i;
for (i = 0; i < palette->colors_count; i++)
{
palette->colors[i].r = pack_getc (file);
palette->colors[i].g = pack_getc (file);
palette->colors[i].b = pack_getc (file);
palette->colors[i].r = fgetc (file);
palette->colors[i].g = fgetc (file);
palette->colors[i].b = fgetc (file);
}
}
@ -91,92 +93,92 @@ gif_save_animation (const char *filename, GIF_ANIMATION *gif,
{
int frame;
int i, j;
PACKFILE *file;
FILE *file;
file = pack_fopen (filename, "w");
file = fopen (filename, "wb");
if (!file)
return -1;
return -1;
pack_fwrite ("GIF89a", 6, file);
pack_iputw (gif->width, file);
pack_iputw (gif->height, file);
fwrite ("GIF89a", 1, 6, file);
fputw (gif->width, file);
fputw (gif->height, file);
/* 7 global palette
* 456 color richness
* 3 sorted
* 012 palette bits
*/
for (i = 1, j = 0; i < gif->palette.colors_count; i *= 2, j++);
pack_putc ((j ? 128 : 0) + 64 + 32 + 16 + (j ? j - 1 : 0), file);
pack_putc (gif->background_index, file);
pack_putc (0, file); /* No aspect ratio. */
fputc ((j ? 128 : 0) + 64 + 32 + 16 + (j ? j - 1 : 0), file);
fputc (gif->background_index, file);
fputc (0, file); /* No aspect ratio. */
if (j)
write_palette (file, &gif->palette, j);
write_palette (file, &gif->palette, j);
if (gif->loop != -1)
/* Loop count extension. */
{
pack_putc (0x21, file); /* Extension Introducer. */
pack_putc (0xff, file); /* Application Extension. */
pack_putc (11, file); /* Size. */
pack_fwrite ("NETSCAPE2.0", 11, file);
pack_putc (3, file); /* Size. */
pack_putc (1, file);
pack_iputw (gif->loop, file);
pack_putc (0, file);
fputc (0x21, file); /* Extension Introducer. */
fputc (0xff, file); /* Application Extension. */
fputc (11, file); /* Size. */
fwrite ("NETSCAPE2.0", 1, 11, file);
fputc (3, file); /* Size. */
fputc (1, file);
fputw (gif->loop, file);
fputc (0, file);
}
progress(dp, 0.0f);
for (frame = 0; frame < gif->frames_count; frame++)
{
int w = gif->frames[frame].w;
int h = gif->frames[frame].h;
int w = gif->frames[frame].w;
int h = gif->frames[frame].h;
pack_putc (0x21, file); /* Extension Introducer. */
pack_putc (0xf9, file); /* Graphic Control Extension. */
pack_putc (4, file); /* Size. */
/* Disposal method, and enable transparency. */
i = gif->frames[frame].disposal_method << 2;
if (gif->frames[frame].transparent_index != -1)
i |= 1;
pack_putc (i, file);
pack_iputw (gif->frames[frame].duration, file); /* In 1/100th seconds. */
if (gif->frames[frame].transparent_index != -1)
pack_putc (gif->frames[frame].transparent_index, file); /* Transparent color index. */
else
pack_putc (0, file);
pack_putc (0x00, file); /* Terminator. */
fputc (0x21, file); /* Extension Introducer. */
fputc (0xf9, file); /* Graphic Control Extension. */
fputc (4, file); /* Size. */
/* Disposal method, and enable transparency. */
i = gif->frames[frame].disposal_method << 2;
if (gif->frames[frame].transparent_index != -1)
i |= 1;
fputc (i, file);
fputw (gif->frames[frame].duration, file); /* In 1/100th seconds. */
if (gif->frames[frame].transparent_index != -1)
fputc (gif->frames[frame].transparent_index, file); /* Transparent color index. */
else
fputc (0, file);
fputc (0x00, file); /* Terminator. */
pack_putc (0x2c, file); /* Image Descriptor. */
pack_iputw (gif->frames[frame].xoff, file);
pack_iputw (gif->frames[frame].yoff, file);
pack_iputw (w, file);
pack_iputw (h, file);
fputc (0x2c, file); /* Image Descriptor. */
fputw (gif->frames[frame].xoff, file);
fputw (gif->frames[frame].yoff, file);
fputw (w, file);
fputw (h, file);
/* 7: local palette
* 6: interlaced
* 5: sorted
* 012: palette bits
*/
/* 7: local palette
* 6: interlaced
* 5: sorted
* 012: palette bits
*/
for (i = 1, j = 0; i < gif->frames[frame].palette.colors_count; i *= 2, j++);
pack_putc ((j ? 128 : 0) + (j ? j - 1 : 0), file);
for (i = 1, j = 0; i < gif->frames[frame].palette.colors_count; i *= 2, j++);
fputc ((j ? 128 : 0) + (j ? j - 1 : 0), file);
if (j)
write_palette (file, &gif->frames[frame].palette, j);
if (j)
write_palette (file, &gif->frames[frame].palette, j);
LZW_encode (file, lzw_read_pixel, w * h,
gif->frames[frame].bitmap_8_bit);
LZW_encode (file, lzw_read_pixel, w * h,
gif->frames[frame].bitmap_8_bit);
pack_putc (0x00, file); /* Terminator. */
fputc (0x00, file); /* Terminator. */
progress(dp, (float)frame / (float)gif->frames_count);
}
progress(dp, 1.0f);
pack_putc (0x3b, file); /* Trailer. */
fputc (0x3b, file); /* Trailer. */
pack_fclose (file);
fclose (file);
return 0;
}
@ -187,26 +189,26 @@ deinterlace (unsigned char *bmp, int w, int h)
int y, i = 0;
for (y = 0; y < h; y += 8)
{
memcpy (temp, bmp + i++ * w, w);
memcpy (temp, bmp + i++ * w, w);
}
for (y = 4; y < h; y += 8)
{
memcpy (temp, bmp + i++ * w, w);
memcpy (temp, bmp + i++ * w, w);
}
for (y = 2; y < h; y += 4)
{
memcpy (temp, bmp + i++ * w, w);
memcpy (temp, bmp + i++ * w, w);
}
for (y = 1; y < h; y += 2)
{
memcpy (temp, bmp + i++ * w, w);
memcpy (temp, bmp + i++ * w, w);
}
memcpy (bmp, temp, w * h);
free(temp);
}
static GIF_ANIMATION *
load_object (PACKFILE * file, long size, void (*progress) (void *, float), void *dp)
load_object (FILE * file, long size, void (*progress) (void *, float), void *dp)
{
int version;
unsigned char *bmp = NULL;
@ -218,162 +220,162 @@ load_object (PACKFILE * file, long size, void (*progress) (void *, float), void
gif->frames_count = 0;
/* is it really a GIF? */
if (pack_getc (file) != 'G')
goto error;
if (pack_getc (file) != 'I')
goto error;
if (pack_getc (file) != 'F')
goto error;
if (pack_getc (file) != '8')
goto error;
if (fgetc (file) != 'G')
goto error;
if (fgetc (file) != 'I')
goto error;
if (fgetc (file) != 'F')
goto error;
if (fgetc (file) != '8')
goto error;
/* '7' or '9', for 87a or 89a. */
version = pack_getc (file);
version = fgetc (file);
if (version != '7' && version != '9')
goto error;
if (pack_getc (file) != 'a')
goto error;
goto error;
if (fgetc (file) != 'a')
goto error;
gif->width = pack_igetw (file);
gif->height = pack_igetw (file);
i = pack_getc (file);
gif->width = fgetw (file);
gif->height = fgetw (file);
i = fgetc (file);
/* Global color table? */
if (i & 128)
gif->palette.colors_count = 1 << ((i & 7) + 1);
gif->palette.colors_count = 1 << ((i & 7) + 1);
else
gif->palette.colors_count = 0;
gif->palette.colors_count = 0;
/* Background color is only valid with a global palette. */
gif->background_index = pack_getc (file);
gif->background_index = fgetc (file);
/* Skip aspect ratio. */
pack_fseek (file, 1);
fseek (file, 1, SEEK_CUR);
if (gif->palette.colors_count)
{
read_palette (file, &gif->palette);
have_global_palette = 1;
read_palette (file, &gif->palette);
have_global_palette = 1;
}
progress(dp, 0.0f);
do
{
i = pack_getc (file);
i = fgetc (file);
progress(dp, (float)i / (float)size);
switch (i)
{
case 0x2c: /* Image Descriptor */
{
int w, h;
int interlaced = 0;
switch (i)
{
case 0x2c: /* Image Descriptor */
{
int w, h;
int interlaced = 0;
frame.xoff = pack_igetw (file);
frame.yoff = pack_igetw (file);
w = pack_igetw (file);
h = pack_igetw (file);
bmp = calloc (w, h);
if (!bmp)
goto error;
frame.w = w;
frame.h = h;
i = pack_getc (file);
frame.xoff = fgetw (file);
frame.yoff = fgetw (file);
w = fgetw (file);
h = fgetw (file);
bmp = calloc (w, h);
if (!bmp)
goto error;
frame.w = w;
frame.h = h;
i = fgetc (file);
/* Local palette. */
if (i & 128)
{
frame.palette.colors_count = 1 << ((i & 7) + 1);
read_palette (file, &frame.palette);
}
else
{
frame.palette.colors_count = 0;
}
/* Local palette. */
if (i & 128)
{
frame.palette.colors_count = 1 << ((i & 7) + 1);
read_palette (file, &frame.palette);
}
else
{
frame.palette.colors_count = 0;
}
if (i & 64)
interlaced = 1;
if (i & 64)
interlaced = 1;
if (LZW_decode (file, lzw_write_pixel, bmp))
goto error;
if (LZW_decode (file, lzw_write_pixel, bmp))
goto error;
if (interlaced)
deinterlace (bmp, w, h);
if (interlaced)
deinterlace (bmp, w, h);
frame.bitmap_8_bit = bmp;
bmp = NULL;
frame.bitmap_8_bit = bmp;
bmp = NULL;
gif->frames_count++;
gif->frames =
realloc (gif->frames,
gif->frames_count * sizeof *gif->frames);
gif->frames[gif->frames_count - 1] = frame;
break;
}
case 0x21: /* Extension Introducer. */
j = pack_getc (file); /* Extension Type. */
i = pack_getc (file); /* Size. */
if (j == 0xf9) /* Graphic Control Extension. */
{
/* size must be 4 */
if (i != 4)
goto error;
i = pack_getc (file);
frame.disposal_method = (i >> 2) & 7;
frame.duration = pack_igetw (file);
if (i & 1) /* Transparency? */
{
frame.transparent_index = pack_getc (file);
}
else
{
pack_fseek (file, 1);
frame.transparent_index = -1;
}
i = pack_getc (file); /* Size. */
}
/* Application Extension. */
else if (j == 0xff)
{
if (i == 11)
{
char name[12];
pack_fread (name, 11, file);
i = pack_getc (file); /* Size. */
name[11] = '\0';
if (!strcmp (name, "NETSCAPE2.0"))
{
if (i == 3)
{
j = pack_getc (file);
gif->loop = pack_igetw (file);
if (j != 1)
gif->loop = 0;
i = pack_getc (file); /* Size. */
}
}
}
}
gif->frames_count++;
gif->frames =
realloc (gif->frames,
gif->frames_count * sizeof *gif->frames);
gif->frames[gif->frames_count - 1] = frame;
break;
}
case 0x21: /* Extension Introducer. */
j = fgetc (file); /* Extension Type. */
i = fgetc (file); /* Size. */
if (j == 0xf9) /* Graphic Control Extension. */
{
/* size must be 4 */
if (i != 4)
goto error;
i = fgetc (file);
frame.disposal_method = (i >> 2) & 7;
frame.duration = fgetw (file);
if (i & 1) /* Transparency? */
{
frame.transparent_index = fgetc (file);
}
else
{
fseek (file, 1, SEEK_CUR);
frame.transparent_index = -1;
}
i = fgetc (file); /* Size. */
}
/* Application Extension. */
else if (j == 0xff)
{
if (i == 11)
{
char name[12];
fread (name, 1, 11, file);
i = fgetc (file); /* Size. */
name[11] = '\0';
if (!strcmp (name, "NETSCAPE2.0"))
{
if (i == 3)
{
j = fgetc (file);
gif->loop = fgetw (file);
if (j != 1)
gif->loop = 0;
i = fgetc (file); /* Size. */
}
}
}
}
/* Possibly more blocks until terminator block (0). */
while (i)
{
pack_fseek (file, i);
i = pack_getc (file);
}
break;
case 0x3b:
/* GIF Trailer. */
pack_fclose (file);
/* Possibly more blocks until terminator block (0). */
while (i)
{
fseek (file, i, SEEK_CUR);
i = fgetc (file);
}
break;
case 0x3b:
/* GIF Trailer. */
fclose (file);
progress(dp, 1.0f);
return gif;
}
return gif;
}
}
while (TRUE);
error:
if (file)
pack_fclose (file);
fclose (file);
if (gif)
gif_destroy_animation (gif);
gif_destroy_animation (gif);
if (bmp)
free (bmp);
free (bmp);
return NULL;
}
@ -391,7 +393,7 @@ load_object (PACKFILE * file, long size, void (*progress) (void *, float), void
GIF_ANIMATION *
gif_load_animation (const char *filename, void (*progress) (void *, float), void *dp)
{
PACKFILE *file;
FILE *file;
GIF_ANIMATION *gif = NULL;
#if (MAKE_VERSION(4, 2, 1) >= MAKE_VERSION(ALLEGRO_VERSION, \
ALLEGRO_SUB_VERSION, \
@ -401,7 +403,7 @@ gif_load_animation (const char *filename, void (*progress) (void *, float), void
int size = file_size_ex(filename);
#endif
file = pack_fopen (filename, "r");
file = fopen (filename, "rb");
if (file)
gif = load_object (file, size, progress, dp);
return gif;
@ -412,4 +414,3 @@ gif_load_animation (const char *filename, void (*progress) (void *, float), void
/* { */
/* return makecol (rgb->r, rgb->g, rgb->b); */
/* } */

View File

@ -1,7 +1,7 @@
#include "lzw.h"
#include "file/gif/lzw.h"
static int
read_code (PACKFILE * file, unsigned char *buf, int *bit_pos, int bit_size)
read_code (FILE * file, unsigned char *buf, int *bit_pos, int bit_size)
{
int i;
int code = 0;
@ -13,7 +13,7 @@ read_code (PACKFILE * file, unsigned char *buf, int *bit_pos, int bit_size)
if (byte_pos == 0)
{
int data_len = pack_getc (file);
int data_len = fgetc (file);
if (data_len == 0)
{
@ -21,7 +21,7 @@ read_code (PACKFILE * file, unsigned char *buf, int *bit_pos, int bit_size)
//abort ();
return -1;
}
pack_fread (buf + 256 - data_len, data_len, file);
fread (buf + 256 - data_len, 1, data_len, file);
byte_pos = 256 - data_len;
*bit_pos = byte_pos << 3;
}
@ -34,7 +34,7 @@ read_code (PACKFILE * file, unsigned char *buf, int *bit_pos, int bit_size)
}
static void
write_code (PACKFILE * file, unsigned char *buf, int *bit_pos, int bit_size, int code)
write_code (FILE * file, unsigned char *buf, int *bit_pos, int bit_size, int code)
{
int i;
int pos = 1;
@ -50,8 +50,8 @@ write_code (PACKFILE * file, unsigned char *buf, int *bit_pos, int bit_size, int
(*bit_pos)++;
if (*bit_pos == 2040)
{
pack_putc (byte_pos + 1, file);
pack_fwrite (buf, byte_pos + 1, file);
fputc (byte_pos + 1, file);
fwrite (buf, 1, byte_pos + 1, file);
*bit_pos = 0;
}
pos += pos;
@ -59,7 +59,7 @@ write_code (PACKFILE * file, unsigned char *buf, int *bit_pos, int bit_size, int
}
int
LZW_decode (PACKFILE * file,
LZW_decode (FILE * file,
void (*write_pixel)(int pos, int code, unsigned char *data),
unsigned char *data)
{
@ -80,7 +80,7 @@ LZW_decode (PACKFILE * file,
int i, prev, code, c;
int out_pos = 0;
orig_bit_size = pack_getc (file);
orig_bit_size = fgetc (file);
n = 2 + (1 << orig_bit_size);
for (i = 0; i < n; i++)
@ -188,7 +188,7 @@ get_minimum_bitsize (int (*read_pixel)(int pos, unsigned char *data),
}
void
LZW_encode (PACKFILE * file, int (*read_pixel)(int pos, unsigned char *data),
LZW_encode (FILE * file, int (*read_pixel)(int pos, unsigned char *data),
int size, unsigned char *data)
{
unsigned char buf[256];
@ -221,7 +221,7 @@ LZW_encode (PACKFILE * file, int (*read_pixel)(int pos, unsigned char *data),
clear_marker = n - 2;
end_marker = n - 1;
pack_putc (orig_bit_size, file);
fputc (orig_bit_size, file);
bit_size = orig_bit_size + 1;
@ -283,7 +283,7 @@ LZW_encode (PACKFILE * file, int (*read_pixel)(int pos, unsigned char *data),
{
int byte_pos = (bit_pos + 7) / 8;
pack_putc (byte_pos, file);
pack_fwrite (buf, byte_pos, file);
fputc (byte_pos, file);
fwrite (buf, 1, byte_pos, file);
}
}

View File

@ -1,6 +1,6 @@
#ifndef _LZW_H_
#define _LZW_H_
#include <allegro/file.h>
int LZW_decode (PACKFILE *file, void (*write_pixel)(int pos, int code, unsigned char *data), unsigned char *data);
void LZW_encode (PACKFILE *file, int (*read_pixel)(int pos, unsigned char *data), int size, unsigned char *data);
#include <stdio.h>
int LZW_decode (FILE *file, void (*write_pixel)(int pos, int code, unsigned char *data), unsigned char *data);
void LZW_encode (FILE *file, int (*read_pixel)(int pos, unsigned char *data), int size, unsigned char *data);
#endif

View File

@ -23,7 +23,6 @@
#ifndef USE_PRECOMPILED_HEADER
#include <allegro/color.h>
#include <allegro/file.h>
#include "file/file.h"
#include "raster/raster.h"
@ -51,23 +50,23 @@ FileFormat format_ico =
static bool save_ICO(FileOp *fop)
{
PACKFILE *f;
FILE *f;
int depth, bpp, bw, bitsw;
int size, offset, n, i;
int c, x, y, b, m, v;
int num = fop->sprite->frames;
Image *bmp;
f = pack_fopen(fop->filename, F_WRITE);
f = fopen(fop->filename, "wb");
if (!f)
return FALSE;
offset = 6 + num * 16; /* ICONDIR + ICONDIRENTRYs */
/* ICONDIR */
pack_iputw(0, f); /* reserved */
pack_iputw(1, f); /* resource type: ICON */
pack_iputw(num, f); /* number of icons */
fputw(0, f); /* reserved */
fputw(1, f); /* resource type: ICON */
fputw(num, f); /* number of icons */
for(n = 0; n < num; n++) {
depth = 8;/* bitmap_color_depth(bmp[n]); */
@ -80,14 +79,14 @@ static bool save_ICO(FileOp *fop)
size += 256 * 4;
/* ICONDIRENTRY */
pack_putc(fop->sprite->w, f); /* width */
pack_putc(fop->sprite->h, f); /* height */
pack_putc(0, f); /* color count */
pack_putc(0, f); /* reserved */
pack_iputw(1, f); /* color planes */
pack_iputw(bpp, f); /* bits per pixel */
pack_iputl(size, f); /* size in bytes of image data */
pack_iputl(offset, f); /* file offset to image data */
fputc(fop->sprite->w, f); /* width */
fputc(fop->sprite->h, f); /* height */
fputc(0, f); /* color count */
fputc(0, f); /* reserved */
fputw(1, f); /* color planes */
fputw(bpp, f); /* bits per pixel */
fputl(size, f); /* size in bytes of image data */
fputl(offset, f); /* file offset to image data */
offset += size;
}
@ -110,29 +109,29 @@ static bool save_ICO(FileOp *fop)
size += 256 * 4;
/* BITMAPINFOHEADER */
pack_iputl(40, f); /* size */
pack_iputl(bmp->w, f); /* width */
pack_iputl(bmp->h * 2, f); /* height x 2 */
pack_iputw(1, f); /* planes */
pack_iputw(bpp, f); /* bitcount */
pack_iputl(0, f); /* unused for ico */
pack_iputl(size, f); /* size */
pack_iputl(0, f); /* unused for ico */
pack_iputl(0, f); /* unused for ico */
pack_iputl(0, f); /* unused for ico */
pack_iputl(0, f); /* unused for ico */
fputl(40, f); /* size */
fputl(bmp->w, f); /* width */
fputl(bmp->h * 2, f); /* height x 2 */
fputw(1, f); /* planes */
fputw(bpp, f); /* bitcount */
fputl(0, f); /* unused for ico */
fputl(size, f); /* size */
fputl(0, f); /* unused for ico */
fputl(0, f); /* unused for ico */
fputl(0, f); /* unused for ico */
fputl(0, f); /* unused for ico */
/* PALETTE */
if (bpp == 8) {
RGB *pal = sprite_get_palette(fop->sprite, n);
pack_iputl(0, f); /* color 0 is black, so the XOR mask works */
fputl(0, f); /* color 0 is black, so the XOR mask works */
for (i = 1; i<256; i++) {
pack_putc(_rgb_scale_6[pal[i].b], f);
pack_putc(_rgb_scale_6[pal[i].g], f);
pack_putc(_rgb_scale_6[pal[i].r], f);
pack_putc(0, f);
fputc(_rgb_scale_6[pal[i].b], f);
fputc(_rgb_scale_6[pal[i].g], f);
fputc(_rgb_scale_6[pal[i].r], f);
fputc(0, f);
}
}
@ -140,19 +139,19 @@ static bool save_ICO(FileOp *fop)
for (y = bmp->h - 1; y >= 0; y--) {
for (x = 0; x < bmp->w; x++) {
if (bpp == 8) {
pack_putc(image_getpixel(bmp, x, y), f);
fputc(image_getpixel(bmp, x, y), f);
}
else {
c = image_getpixel(bmp, x, y);
pack_putc(getb_depth(depth, c), f);
pack_putc(getg_depth(depth, c), f);
pack_putc(getr_depth(depth, c), f);
fputc(getb_depth(depth, c), f);
fputc(getg_depth(depth, c), f);
fputc(getr_depth(depth, c), f);
}
}
/* every scanline must be 32-bit aligned */
while (x&3) {
pack_putc(0, f);
fputc(0, f);
x++;
}
}
@ -170,19 +169,19 @@ static bool save_ICO(FileOp *fop)
v /= 2;
}
pack_putc(m, f);
fputc(m, f);
}
/* every scanline must be 32-bit aligned */
while (x&3) {
pack_putc(0, f);
fputc(0, f);
x++;
}
}
}
image_free(bmp);
pack_fclose(f);
fclose(f);
return TRUE;
}

View File

@ -208,6 +208,8 @@ static bool load_JPEG(FileOp *fop)
}
fop_progress(fop, (float)(cinfo.output_scanline+1) / (float)(cinfo.output_height));
if (fop_is_stop(fop))
break;
}
/* destroy all data */

View File

@ -23,7 +23,6 @@
#ifndef USE_PRECOMPILED_HEADER
#include <allegro/color.h>
#include <allegro/file.h>
#include "file/file.h"
#include "raster/raster.h"
@ -48,7 +47,7 @@ FileFormat format_pcx =
static bool load_PCX(FileOp *fop)
{
Image *image;
PACKFILE *f;
FILE *f;
int c, r, g, b;
int width, height;
int bpp, bytes_per_line;
@ -56,70 +55,68 @@ static bool load_PCX(FileOp *fop)
int x, y;
char ch = 0;
f = pack_fopen(fop->filename, F_READ);
f = fopen(fop->filename, "rb");
if (!f)
return FALSE;
pack_getc(f); /* skip manufacturer ID */
pack_getc(f); /* skip version flag */
pack_getc(f); /* skip encoding flag */
fgetc(f); /* skip manufacturer ID */
fgetc(f); /* skip version flag */
fgetc(f); /* skip encoding flag */
if (pack_getc(f) != 8) { /* we like 8 bit color planes */
if (fgetc(f) != 8) { /* we like 8 bit color planes */
fop_error(fop, _("This PCX doesn't have 8 bit color planes.\n"));
pack_fclose(f);
fclose(f);
return FALSE;
}
width = -(pack_igetw(f)); /* xmin */
height = -(pack_igetw(f)); /* ymin */
width += pack_igetw(f) + 1; /* xmax */
height += pack_igetw(f) + 1; /* ymax */
width = -(fgetw(f)); /* xmin */
height = -(fgetw(f)); /* ymin */
width += fgetw(f) + 1; /* xmax */
height += fgetw(f) + 1; /* ymax */
pack_igetl(f); /* skip DPI values */
fgetl(f); /* skip DPI values */
for (c=0; c<16; c++) { /* read the 16 color palette */
r = pack_getc(f) / 4;
g = pack_getc(f) / 4;
b = pack_getc(f) / 4;
for (c=0; c<16; c++) { /* read the 16 color palette */
r = fgetc(f) / 4;
g = fgetc(f) / 4;
b = fgetc(f) / 4;
fop_sequence_set_color(fop, c, r, g, b);
}
pack_getc(f);
fgetc(f);
bpp = pack_getc(f) * 8; /* how many color planes? */
bpp = fgetc(f) * 8; /* how many color planes? */
if ((bpp != 8) && (bpp != 24)) {
pack_fclose(f);
fclose(f);
return FALSE;
}
bytes_per_line = pack_igetw(f);
bytes_per_line = fgetw(f);
for (c=0; c<60; c++) /* skip some more junk */
pack_getc(f);
fgetc(f);
image = fop_sequence_image(fop, bpp == 8 ?
IMAGE_INDEXED:
IMAGE_RGB,
width, height);
if (!image) {
pack_fclose(f);
fclose(f);
return FALSE;
}
if (bpp == 24)
image_clear(image, _rgba(0, 0, 0, 255));
*allegro_errno = 0;
for (y=0; y<height; y++) { /* read RLE encoded PCX data */
x = xx = 0;
po = _rgba_r_shift;
while (x < bytes_per_line*bpp/8) {
ch = pack_getc(f);
ch = fgetc(f);
if ((ch & 0xC0) == 0xC0) {
c = (ch & 0x3F);
ch = pack_getc(f);
ch = fgetc(f);
}
else
c = 1;
@ -151,36 +148,41 @@ static bool load_PCX(FileOp *fop)
}
fop_progress(fop, (float)(y+1) / (float)(height));
if (fop_is_stop(fop))
break;
}
if (bpp == 8) { /* look for a 256 color palette */
while ((c = pack_getc(f)) != EOF) {
if (c == 12) {
for (c=0; c<256; c++) {
r = pack_getc(f) / 4;
g = pack_getc(f) / 4;
b = pack_getc(f) / 4;
fop_sequence_set_color(fop, c, r, g, b);
}
break;
if (!fop_is_stop(fop)) {
if (bpp == 8) { /* look for a 256 color palette */
while ((c = fgetc(f)) != EOF) {
if (c == 12) {
for (c=0; c<256; c++) {
r = fgetc(f) / 4;
g = fgetc(f) / 4;
b = fgetc(f) / 4;
fop_sequence_set_color(fop, c, r, g, b);
}
break;
}
}
}
}
if (*allegro_errno) {
fop_error(fop, _("Error reading bytes.\n"));
pack_fclose(f);
if (ferror(f)) {
fop_error(fop, _("Error reading file.\n"));
fclose(f);
return FALSE;
}
pack_fclose(f);
return TRUE;
else {
fclose(f);
return TRUE;
}
}
static bool save_PCX(FileOp *fop)
{
Image *image = fop->seq.image;
PACKFILE *f;
FILE *f;
int c, r, g, b;
int x, y;
int runcount;
@ -188,7 +190,7 @@ static bool save_PCX(FileOp *fop)
char runchar;
char ch = 0;
f = pack_fopen(fop->filename, F_WRITE);
f = fopen(fop->filename, "wb");
if (!f) {
fop_error(fop, _("Error creating file.\n"));
return FALSE;
@ -203,34 +205,32 @@ static bool save_PCX(FileOp *fop)
planes = 1;
}
*allegro_errno = 0;
pack_putc(10, f); /* manufacturer */
pack_putc(5, f); /* version */
pack_putc(1, f); /* run length encoding */
pack_putc(8, f); /* 8 bits per pixel */
pack_iputw(0, f); /* xmin */
pack_iputw(0, f); /* ymin */
pack_iputw(image->w-1, f); /* xmax */
pack_iputw(image->h-1, f); /* ymax */
pack_iputw(320, f); /* HDpi */
pack_iputw(200, f); /* VDpi */
fputc(10, f); /* manufacturer */
fputc(5, f); /* version */
fputc(1, f); /* run length encoding */
fputc(8, f); /* 8 bits per pixel */
fputw(0, f); /* xmin */
fputw(0, f); /* ymin */
fputw(image->w-1, f); /* xmax */
fputw(image->h-1, f); /* ymax */
fputw(320, f); /* HDpi */
fputw(200, f); /* VDpi */
for (c=0; c<16; c++) {
fop_sequence_get_color(fop, c, &r, &g, &b);
pack_putc(_rgb_scale_6[r], f);
pack_putc(_rgb_scale_6[g], f);
pack_putc(_rgb_scale_6[b], f);
fputc(_rgb_scale_6[r], f);
fputc(_rgb_scale_6[g], f);
fputc(_rgb_scale_6[b], f);
}
pack_putc(0, f); /* reserved */
pack_putc(planes, f); /* one or three color planes */
pack_iputw(image->w, f); /* number of bytes per scanline */
pack_iputw(1, f); /* color palette */
pack_iputw(image->w, f); /* hscreen size */
pack_iputw(image->h, f); /* vscreen size */
for (c=0; c<54; c++) /* filler */
pack_putc(0, f);
fputc(0, f); /* reserved */
fputc(planes, f); /* one or three color planes */
fputw(image->w, f); /* number of bytes per scanline */
fputw(1, f); /* color palette */
fputw(image->w, f); /* hscreen size */
fputw(image->h, f); /* vscreen size */
for (c=0; c<54; c++) /* filler */
fputc(0, f);
for (y=0; y<image->h; y++) { /* for each scanline... */
runcount = 0;
@ -265,8 +265,8 @@ static bool save_PCX(FileOp *fop)
else {
if ((ch != runchar) || (runcount >= 0x3f)) {
if ((runcount > 1) || ((runchar & 0xC0) == 0xC0))
pack_putc(0xC0 | runcount, f);
pack_putc(runchar, f);
fputc(0xC0 | runcount, f);
fputc(runchar, f);
runcount = 1;
runchar = ch;
}
@ -276,30 +276,31 @@ static bool save_PCX(FileOp *fop)
}
if ((runcount > 1) || ((runchar & 0xC0) == 0xC0))
pack_putc(0xC0 | runcount, f);
fputc(0xC0 | runcount, f);
pack_putc(runchar, f);
fputc(runchar, f);
fop_progress(fop, (float)(y+1) / (float)(image->h));
}
if (depth == 8) { /* 256 color palette */
pack_putc(12, f);
fputc(12, f);
for (c=0; c<256; c++) {
fop_sequence_get_color(fop, c, &r, &g, &b);
pack_putc(_rgb_scale_6[r], f);
pack_putc(_rgb_scale_6[g], f);
pack_putc(_rgb_scale_6[b], f);
fputc(_rgb_scale_6[r], f);
fputc(_rgb_scale_6[g], f);
fputc(_rgb_scale_6[b], f);
}
}
pack_fclose(f);
if (*allegro_errno) {
fop_error(fop, _("Error writing bytes.\n"));
if (ferror(f)) {
fop_error(fop, _("Error writing file.\n"));
fclose(f);
return FALSE;
}
else
else {
fclose(f);
return TRUE;
}
}

View File

@ -276,6 +276,9 @@ static bool load_PNG(FileOp *fop)
fop_progress(fop,
(float)((float)pass + (float)(y+1) / (float)(height))
/ (float)number_passes);
if (fop_is_stop(fop))
break;
}
}
png_free(png_ptr, row_pointer);

View File

@ -24,7 +24,6 @@
#ifndef USE_PRECOMPILED_HEADER
#include <allegro/color.h>
#include <allegro/file.h>
#include "jinete/jbase.h"
@ -52,18 +51,18 @@ FileFormat format_tga =
/* rle_tga_read:
* Helper for reading 256 color RLE data from TGA files.
*/
static void rle_tga_read(unsigned char *address, int w, int type, PACKFILE *f)
static void rle_tga_read(unsigned char *address, int w, int type, FILE *f)
{
unsigned char value;
int count, g;
int c = 0;
do {
count = pack_getc(f);
count = fgetc(f);
if (count & 0x80) {
count = (count & 0x7F) + 1;
c += count;
value = pack_getc(f);
value = fgetc(f);
while (count--) {
if (type == 1)
*(address++) = value;
@ -77,12 +76,12 @@ static void rle_tga_read(unsigned char *address, int w, int type, PACKFILE *f)
count++;
c += count;
if (type == 1) {
pack_fread(address, count, f);
fread(address, 1, count, f);
address += count;
}
else {
for (g=0; g<count; g++) {
*((ase_uint16 *)address) = pack_getc(f);
*((ase_uint16 *)address) = fgetc(f);
address += sizeof(ase_uint16);
}
}
@ -93,18 +92,18 @@ static void rle_tga_read(unsigned char *address, int w, int type, PACKFILE *f)
/* rle_tga_read32:
* Helper for reading 32 bit RLE data from TGA files.
*/
static void rle_tga_read32 (ase_uint32 *address, int w, PACKFILE *f)
static void rle_tga_read32 (ase_uint32 *address, int w, FILE *f)
{
unsigned char value[4];
int count;
int c = 0;
do {
count = pack_getc(f);
count = fgetc(f);
if (count & 0x80) {
count = (count & 0x7F) + 1;
c += count;
pack_fread(value, 4, f);
fread(value, 1, 4, f);
while (count--)
*(address++) = _rgba(value[2], value[1], value[0], value[3]);
}
@ -112,7 +111,7 @@ static void rle_tga_read32 (ase_uint32 *address, int w, PACKFILE *f)
count++;
c += count;
while (count--) {
pack_fread(value, 4, f);
fread(value, 1, 4, f);
*(address++) = _rgba(value[2], value[1], value[0], value[3]);
}
}
@ -122,18 +121,18 @@ static void rle_tga_read32 (ase_uint32 *address, int w, PACKFILE *f)
/* rle_tga_read24:
* Helper for reading 24 bit RLE data from TGA files.
*/
static void rle_tga_read24(ase_uint32 *address, int w, PACKFILE *f)
static void rle_tga_read24(ase_uint32 *address, int w, FILE *f)
{
unsigned char value[4];
int count;
int c = 0;
do {
count = pack_getc(f);
count = fgetc(f);
if (count & 0x80) {
count = (count & 0x7F) + 1;
c += count;
pack_fread(value, 3, f);
fread(value, 1, 3, f);
while (count--)
*(address++) = _rgba(value[2], value[1], value[0], 255);
}
@ -141,7 +140,7 @@ static void rle_tga_read24(ase_uint32 *address, int w, PACKFILE *f)
count++;
c += count;
while (count--) {
pack_fread(value, 3, f);
fread(value, 1, 3, f);
*(address++) = _rgba(value[2], value[1], value[0], 255);
}
}
@ -151,7 +150,7 @@ static void rle_tga_read24(ase_uint32 *address, int w, PACKFILE *f)
/* rle_tga_read16:
* Helper for reading 16 bit RLE data from TGA files.
*/
static void rle_tga_read16(ase_uint32 *address, int w, PACKFILE *f)
static void rle_tga_read16(ase_uint32 *address, int w, FILE *f)
{
unsigned int value;
ase_uint32 color;
@ -159,11 +158,11 @@ static void rle_tga_read16(ase_uint32 *address, int w, PACKFILE *f)
int c = 0;
do {
count = pack_getc(f);
count = fgetc(f);
if (count & 0x80) {
count = (count & 0x7F) + 1;
c += count;
value = pack_igetw(f);
value = fgetw(f);
color = _rgba(_rgb_scale_5[((value >> 10) & 0x1F)],
_rgb_scale_5[((value >> 5) & 0x1F)],
_rgb_scale_5[(value & 0x1F)], 255);
@ -175,7 +174,7 @@ static void rle_tga_read16(ase_uint32 *address, int w, PACKFILE *f)
count++;
c += count;
while (count--) {
value = pack_igetw(f);
value = fgetw(f);
color = _rgba(_rgb_scale_5[((value >> 10) & 0x1F)],
_rgb_scale_5[((value >> 5) & 0x1F)],
_rgb_scale_5[(value & 0x1F)], 255);
@ -200,36 +199,34 @@ static bool load_TGA(FileOp *fop)
unsigned int c, i, x, y, yc;
Image *image;
int compressed;
PACKFILE *f;
FILE *f;
int type;
f = pack_fopen(fop->filename, F_READ);
f = fopen(fop->filename, "rb");
if (!f)
return FALSE;
*allegro_errno = 0;
id_length = fgetc(f);
palette_type = fgetc(f);
image_type = fgetc(f);
first_color = fgetw(f);
palette_colors = fgetw(f);
palette_entry_size = fgetc(f);
left = fgetw(f);
top = fgetw(f);
image_width = fgetw(f);
image_height = fgetw(f);
bpp = fgetc(f);
descriptor_bits = fgetc(f);
id_length = pack_getc(f);
palette_type = pack_getc(f);
image_type = pack_getc(f);
first_color = pack_igetw(f);
palette_colors = pack_igetw(f);
palette_entry_size = pack_getc(f);
left = pack_igetw(f);
top = pack_igetw(f);
image_width = pack_igetw(f);
image_height = pack_igetw(f);
bpp = pack_getc(f);
descriptor_bits = pack_getc(f);
pack_fread(image_id, id_length, f);
fread(image_id, 1, id_length, f);
if (palette_type == 1) {
for (i=0; i<palette_colors; i++) {
switch (palette_entry_size) {
case 16:
c = pack_igetw(f);
c = fgetw(f);
image_palette[i][0] = (c & 0x1F) << 3;
image_palette[i][1] = ((c >> 5) & 0x1F) << 3;
image_palette[i][2] = ((c >> 10) & 0x1F) << 3;
@ -237,17 +234,17 @@ static bool load_TGA(FileOp *fop)
case 24:
case 32:
image_palette[i][0] = pack_getc(f);
image_palette[i][1] = pack_getc(f);
image_palette[i][2] = pack_getc(f);
image_palette[i][0] = fgetc(f);
image_palette[i][1] = fgetc(f);
image_palette[i][2] = fgetc(f);
if (palette_entry_size == 32)
pack_getc(f);
fgetc(f);
break;
}
}
}
else if (palette_type != 0) {
pack_fclose(f);
fclose(f);
return FALSE;
}
@ -268,7 +265,7 @@ static bool load_TGA(FileOp *fop)
/* paletted image */
case 1:
if ((palette_type != 1) || (bpp != 8)) {
pack_fclose(f);
fclose(f);
return FALSE;
}
@ -287,7 +284,7 @@ static bool load_TGA(FileOp *fop)
if ((palette_type != 0) ||
((bpp != 15) && (bpp != 16) &&
(bpp != 24) && (bpp != 32))) {
pack_fclose(f);
fclose(f);
return FALSE;
}
@ -297,7 +294,7 @@ static bool load_TGA(FileOp *fop)
/* grayscale image */
case 3:
if ((palette_type != 0) || (bpp != 8)) {
pack_fclose(f);
fclose(f);
return FALSE;
}
@ -310,13 +307,13 @@ static bool load_TGA(FileOp *fop)
default:
/* TODO add support for more TGA types? */
pack_fclose(f);
fclose(f);
return FALSE;
}
image = fop_sequence_image(fop, type, image_width, image_height);
if (!image) {
pack_fclose(f);
fclose(f);
return FALSE;
}
@ -330,11 +327,11 @@ static bool load_TGA(FileOp *fop)
if (compressed)
rle_tga_read(image->line[yc], image_width, image_type, f);
else if (image_type == 1)
pack_fread(image->line[yc], image_width, f);
fread(image->line[yc], 1, image_width, f);
else {
for (x=0; x<image_width; x++)
*(((ase_uint16 **)image->line)[yc]+x) =
_graya(pack_getc(f), 255);
_graya(fgetc(f), 255);
}
break;
@ -345,7 +342,7 @@ static bool load_TGA(FileOp *fop)
}
else {
for (x=0; x<image_width; x++) {
pack_fread(rgb, 4, f);
fread(rgb, 1, 4, f);
*(((ase_uint32 **)image->line)[yc]+x) =
_rgba(rgb[2], rgb[1], rgb[0], rgb[3]);
}
@ -357,7 +354,7 @@ static bool load_TGA(FileOp *fop)
}
else {
for (x=0; x<image_width; x++) {
pack_fread(rgb, 3, f);
fread(rgb, 1, 3, f);
*(((ase_uint32 **)image->line)[yc]+x) =
_rgba(rgb[2], rgb[1], rgb[0], 255);
}
@ -369,7 +366,7 @@ static bool load_TGA(FileOp *fop)
}
else {
for (x=0; x<image_width; x++) {
c = pack_igetw(f);
c = fgetw(f);
*(((ase_uint32 **)image->line)[yc]+x) =
_rgba(((c >> 10) & 0x1F),
((c >> 5) & 0x1F),
@ -380,18 +377,22 @@ static bool load_TGA(FileOp *fop)
break;
}
if (image_height > 1)
if (image_height > 1) {
fop_progress(fop, (float)(image_height-y) / (float)(image_height));
if (fop_is_stop(fop))
break;
}
}
if (*allegro_errno) {
fop_error(fop, _("Error reading bytes.\n"));
pack_fclose(f);
if (ferror(f)) {
fop_error(fop, _("Error reading file.\n"));
fclose(f);
return FALSE;
}
pack_fclose(f);
return TRUE;
else {
fclose(f);
return TRUE;
}
}
/* save_tga:
@ -405,33 +406,31 @@ static bool save_TGA(FileOp *fop)
int x, y, c, r, g, b;
int depth = (image->imgtype == IMAGE_RGB) ? 32 : 8;
bool need_pal = (image->imgtype == IMAGE_INDEXED)? TRUE: FALSE;
PACKFILE *f;
FILE *f;
f = pack_fopen(fop->filename, F_WRITE);
f = fopen(fop->filename, "wb");
if (!f) {
fop_error(fop, _("Error creating file.\n"));
return FALSE;
}
*allegro_errno = 0;
pack_putc(0, f); /* id length (no id saved) */
pack_putc((need_pal) ? 1 : 0, f); /* palette type */
fputc(0, f); /* id length (no id saved) */
fputc((need_pal) ? 1 : 0, f); /* palette type */
/* image type */
pack_putc((image->imgtype == IMAGE_RGB ) ? 2 :
(image->imgtype == IMAGE_GRAYSCALE) ? 3 :
(image->imgtype == IMAGE_INDEXED ) ? 1 : 0, f);
pack_iputw(0, f); /* first colour */
pack_iputw((need_pal) ? 256 : 0, f); /* number of colours */
pack_putc((need_pal) ? 24 : 0, f); /* palette entry size */
pack_iputw(0, f); /* left */
pack_iputw(0, f); /* top */
pack_iputw(image->w, f); /* width */
pack_iputw(image->h, f); /* height */
pack_putc(depth, f); /* bits per pixel */
fputc((image->imgtype == IMAGE_RGB ) ? 2 :
(image->imgtype == IMAGE_GRAYSCALE) ? 3 :
(image->imgtype == IMAGE_INDEXED ) ? 1 : 0, f);
fputw(0, f); /* first colour */
fputw((need_pal) ? 256 : 0, f); /* number of colours */
fputc((need_pal) ? 24 : 0, f); /* palette entry size */
fputw(0, f); /* left */
fputw(0, f); /* top */
fputw(image->w, f); /* width */
fputw(image->h, f); /* height */
fputc(depth, f); /* bits per pixel */
/* descriptor (bottom to top, 8-bit alpha) */
pack_putc(image->imgtype == IMAGE_RGB ? 8: 0, f);
fputc(image->imgtype == IMAGE_RGB ? 8: 0, f);
if (need_pal) {
for (y=0; y<256; y++) {
@ -440,7 +439,7 @@ static bool save_TGA(FileOp *fop)
image_palette[y][1] = _rgb_scale_6[g];
image_palette[y][0] = _rgb_scale_6[b];
}
pack_fwrite(image_palette, 768, f);
fwrite(image_palette, 1, 768, f);
}
switch (image->imgtype) {
@ -449,10 +448,10 @@ static bool save_TGA(FileOp *fop)
for (y=image->h-1; y>=0; y--) {
for (x=0; x<image->w; x++) {
c = image_getpixel(image, x, y);
pack_putc(_rgba_getb(c), f);
pack_putc(_rgba_getg(c), f);
pack_putc(_rgba_getr(c), f);
pack_putc(_rgba_geta(c), f);
fputc(_rgba_getb(c), f);
fputc(_rgba_getg(c), f);
fputc(_rgba_getr(c), f);
fputc(_rgba_geta(c), f);
}
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
@ -462,7 +461,7 @@ static bool save_TGA(FileOp *fop)
case IMAGE_GRAYSCALE:
for (y=image->h-1; y>=0; y--) {
for (x=0; x<image->w; x++)
pack_putc(_graya_getk(image_getpixel(image, x, y)), f);
fputc(_graya_getk(image_getpixel(image, x, y)), f);
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
}
@ -471,19 +470,20 @@ static bool save_TGA(FileOp *fop)
case IMAGE_INDEXED:
for (y=image->h-1; y>=0; y--) {
for (x=0; x<image->w; x++)
pack_putc(image_getpixel(image, x, y), f);
fputc(image_getpixel(image, x, y), f);
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
}
break;
}
pack_fclose(f);
if (*allegro_errno) {
fop_error(fop, _("Error writing bytes.\n"));
if (ferror(f)) {
fop_error(fop, _("Error writing file.\n"));
fclose(f);
return FALSE;
}
else
else {
fclose(f);
return TRUE;
}
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -43,6 +43,10 @@ int main(int argc, char *argv[])
/* set_uformat(U_UTF8); */
set_uformat(U_ASCII);
#if defined MEMLEAK
jmemleak_init();
#endif
/* initialises the application */
if (!app_init(argc, argv))
return 1;
@ -50,6 +54,10 @@ int main(int argc, char *argv[])
app_loop();
app_exit();
#if defined MEMLEAK
jmemleak_exit();
#endif
allegro_exit();
return 0;
}

View File

@ -558,6 +558,24 @@ void rectshade(BITMAP *bmp, int x1, int y1, int x2, int y2, int top, int bottom)
}
}
void draw_emptyset_symbol(JRect rc, int color)
{
int cx, cy, x1, y1, x2, y2, size;
size = MIN(jrect_w(rc), jrect_h(rc)) - 8;
size = MID(4, size, 64);
cx = (rc->x1+rc->x2)/2;
cy = (rc->y1+rc->y2)/2;
x1 = cx-size/2;
y1 = cy-size/2;
x2 = x1+size-1;
y2 = y1+size-1;
circle(ji_screen, cx, cy, size/2, color);
line(ji_screen, x1, y2, x2, y1, color);
}
/************************************************************************/

View File

@ -19,6 +19,8 @@
#ifndef MODULES_GFX_H
#define MODULES_GFX_H
#include "jinete/jbase.h"
struct FONT;
struct BITMAP;
@ -113,6 +115,8 @@ void rectgrid(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int w, int h);
void rectfill_exclude(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int ex1, int ey1, int ex2, int ey2, int color);
void rectshade(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int top, int bottom);
void draw_emptyset_symbol(JRect rc, int color);
int character_length(struct FONT *font, int chr);
void render_character(struct BITMAP *bmp, struct FONT *font, int chr, int x, int y, int fg, int bg);

View File

@ -1,6 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
* 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,6 +20,7 @@
#ifndef USE_PRECOMPILED_HEADER
#include <assert.h>
#include <allegro.h>
#include <allegro/internal/aintern.h>
@ -65,7 +65,8 @@
# define DEF_SCALE 1
#endif
static struct {
static struct
{
int width;
int height;
int scale;
@ -80,17 +81,26 @@ static int try_depths[] = { 32, 24, 16, 15, 8 };
/**************************************************************/
typedef struct Monitor {
/**
* Returns true when the job is done and the monitor can be removed.
*/
bool (*proc)(void *);
typedef struct ExitHook
{
void (*proc)(void *);
void *data;
bool lock;
} Monitor;
} ExitHook;
struct Monitor
{
/* returns true when the job is done and the monitor can be removed */
void (*proc)(void *);
void (*free)(void *);
void *data;
bool lock : 1;
bool deleted : 1;
};
static JWidget manager = NULL;
static JList exit_hooks;
static int monitor_timer = -1;
static JList monitors;
@ -103,7 +113,11 @@ static JList icon_buttons;
static bool double_buffering;
static int screen_scaling;
static Monitor *monitor_new(bool (*proc)(void *), void *data);
static ExitHook *exithook_new(void (*proc)(void *), void *data);
static void exithook_free(ExitHook *exithook);
static Monitor *monitor_new(void (*proc)(void *),
void (*free)(void *), void *data);
static void monitor_free(Monitor *monitor);
/* load & save graphics configuration */
@ -236,6 +250,7 @@ int init_module_gui(void)
}
gfx_done:;
exit_hooks = jlist_new();
monitors = jlist_new();
/* create the default-manager */
@ -279,6 +294,16 @@ void exit_module_gui(void)
{
JLink link;
/* call the ExitHooks */
JI_LIST_FOR_EACH(exit_hooks, link) {
ExitHook *exithook = link->data;
(*exithook->proc)(exithook->data);
exithook_free(link->data);
}
jlist_free(exit_hooks);
exit_hooks = NULL;
/* destroy monitors */
JI_LIST_FOR_EACH(monitors, link) {
monitor_free(link->data);
}
@ -305,21 +330,44 @@ void exit_module_gui(void)
remove_timer();
}
static Monitor *monitor_new(bool (*proc)(void *), void *data)
static ExitHook *exithook_new(void (*proc)(void *), void *data)
{
ExitHook *exithook = jnew(ExitHook, 1);
if (!exithook)
return NULL;
exithook->proc = proc;
exithook->data = data;
return exithook;
}
static void exithook_free(ExitHook *exithook)
{
jfree(exithook);
}
static Monitor *monitor_new(void (*proc)(void *),
void (*free)(void *), void *data)
{
Monitor *monitor = jnew(Monitor, 1);
if (!monitor)
return NULL;
monitor->proc = proc;
monitor->free = free;
monitor->data = data;
monitor->lock = FALSE;
monitor->deleted = FALSE;
return monitor;
}
static void monitor_free(Monitor *monitor)
{
if (monitor->free)
(*monitor->free)(monitor->data);
jfree(monitor);
}
@ -721,14 +769,53 @@ JWidget check_button_new(const char *text, int b1, int b2, int b3, int b4)
return widget;
}
void add_gui_monitor(bool (*proc)(void *data), void *data)
/**
* Adds a routine to be called when the @ref exit_module_gui is called.
*/
void add_gui_exit_hook(void (*proc)(void *data), void *data)
{
jlist_append(monitors, monitor_new(proc, data));
assert(proc != NULL);
assert(exit_hooks != NULL);
jlist_append(exit_hooks, exithook_new(proc, data));
}
/**
* Adds a routine to be called each 100 milliseconds to monitor
* whatever you want. It's mainly used to monitor the progress of a
* file-operation (see @ref fop_operate)
*/
Monitor *add_gui_monitor(void (*proc)(void *),
void (*free)(void *), void *data)
{
Monitor *monitor = monitor_new(proc, free, data);
jlist_append(monitors, monitor);
if (monitor_timer < 0)
monitor_timer = jmanager_add_timer(manager, 100);
jmanager_start_timer(monitor_timer);
return monitor;
}
/**
* Removes a previously added monitor.
*/
void remove_gui_monitor(Monitor *monitor)
{
JLink link = jlist_find(monitors, monitor);
assert(link != NULL);
if (!monitor->lock)
monitor_free(monitor);
else
monitor->deleted = TRUE;
jlist_delete_link(monitors, link);
if (jlist_empty(monitors))
jmanager_stop_timer(monitor_timer);
}
/**********************************************************************/
@ -752,13 +839,11 @@ static bool manager_msg_proc(JWidget widget, JMessage msg)
if (!monitor->lock) {
/* call the monitor procedure */
monitor->lock = TRUE;
if ((*monitor->proc)(monitor->data)) {
/* the function returns true, the job is done... remove the monitor */
monitor_free(link->data);
jlist_delete_link(monitors, link);
}
else
monitor->lock = FALSE;
(*monitor->proc)(monitor->data);
monitor->lock = FALSE;
if (monitor->deleted)
monitor_free(monitor);
}
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -25,6 +25,9 @@
hook_signal((widget), (signal), (signal_handler), (int)(user_data))
struct Sprite;
struct Monitor;
typedef struct Monitor Monitor;
int init_module_gui(void);
void exit_module_gui(void);
@ -61,6 +64,16 @@ JWidget radio_button_new(int radio_group, int b1, int b2, int b3, int b4);
JWidget check_button_new(const char *text, int b1, int b2, int b3, int b4);
/* void change_to_button_style(JWidget widget, int b1, int b2, int b3, int b4); */
void add_gui_monitor(bool (*proc)(void *data), void *data);
/********************************************************************/
/* exit-hooks */
void add_gui_exit_hook(void (*proc)(void *data), void *data);
/********************************************************************/
/* monitors */
Monitor *add_gui_monitor(void (*proc)(void *),
void (*free)(void *), void *data);
void remove_gui_monitor(Monitor *monitor);
#endif /* MODULES_GUI_H */

View File

@ -1,6 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007,
* 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -54,19 +53,18 @@ static void apply_shortcut_to_menuitems_with_command(JWidget menu, Command *comm
int init_module_rootmenu(void)
{
root_menu = 0;
root_menu = NULL;
layer_popup_menu = NULL;
frame_popup_menu = NULL;
cel_popup_menu = NULL;
filters_popup_menu = NULL;
recent_list_menuitem = NULL;
return load_root_menu();
}
void exit_module_rootmenu(void)
{
recent_list_menuitem = NULL;
layer_popup_menu = NULL;
frame_popup_menu = NULL;
cel_popup_menu = NULL;
filters_popup_menu = NULL;
command_reset_keys();
jwidget_free(root_menu);
@ -231,10 +229,10 @@ static JWidget load_menu_by_id(JXml xml, const char *id, const char *filename)
menu = convert_xmlelem_to_menu(elem);
}
else
PRINTF("Invalid element with id=\"main_menu\" in \"%s\"\n", filename);
PRINTF("Invalid element with id=\"%s\" in \"%s\"\n", id, filename);
}
else
PRINTF("\"main_menu\" element couldn't be found...\n");
PRINTF("\"%s\" element couldn't be found...\n", id);
return menu;
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -63,11 +63,16 @@ int init_module_sprites(void)
void exit_module_sprites(void)
{
JLink link;
if (clipboard_sprite) {
sprite_free(clipboard_sprite);
clipboard_sprite = NULL;
}
JI_LIST_FOR_EACH(sprites_list, link) {
sprite_free(link->data);
}
jlist_free(sprites_list);
sprites_list = NULL;

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -22,53 +22,53 @@
#define BYTES(image) ((ase_uint32 *)image->dat)
#define LINES(image) ((ase_uint32 **)image->line)
static int rgb_regenerate_lines (Image *image)
static int rgb_regenerate_lines(Image *image)
{
ase_uint32 *address = BYTES (image);
ase_uint32 *address = BYTES(image);
int y;
if (LINES (image))
jfree (LINES (image));
if (LINES(image))
jfree (LINES(image));
image->line = jmalloc(sizeof(ase_uint32 *) * image->h);
if (!LINES (image))
if (!LINES(image))
return -1;
for (y=0; y<image->h; y++) {
LINES (image)[y] = address;
LINES(image)[y] = address;
address += image->w;
}
return 0;
}
static int rgb_init (Image *image)
static int rgb_init(Image *image)
{
image->dat = jmalloc(sizeof(ase_uint32) * image->w * image->h);
if (!BYTES (image))
if (!BYTES(image))
return -1;
if (rgb_regenerate_lines (image) < 0) {
jfree (BYTES (image));
if (rgb_regenerate_lines(image) < 0) {
jfree(BYTES(image));
return -1;
}
return 0;
}
static int rgb_getpixel (const Image *image, int x, int y)
static int rgb_getpixel(const Image *image, int x, int y)
{
return *(LINES (image)[y]+x);
return *(LINES(image)[y]+x);
}
static void rgb_putpixel (Image *image, int x, int y, int color)
static void rgb_putpixel(Image *image, int x, int y, int color)
{
*(LINES (image)[y]+x) = color;
*(LINES(image)[y]+x) = color;
}
static void rgb_clear (Image *image, int color)
static void rgb_clear(Image *image, int color)
{
ase_uint32 *address = BYTES (image);
ase_uint32 *address = BYTES(image);
unsigned int c, size = image->w * image->h;
for (c=0; c<size; c++)
@ -118,15 +118,15 @@ static void rgb_copy(Image *dst, const Image *src, int x, int y)
bytes = (xend - xbeg + 1) << 2;
for (ydst=ybeg; ydst<=yend; ydst++, ysrc++) {
src_address = LINES (src)[ysrc]+xsrc;
dst_address = LINES (dst)[ydst]+xbeg;
src_address = LINES(src)[ysrc]+xsrc;
dst_address = LINES(dst)[ydst]+xbeg;
memcpy (dst_address, src_address, bytes);
memcpy(dst_address, src_address, bytes);
}
}
static void rgb_merge (Image *dst, const Image *src,
int x, int y, int opacity, int blend_mode)
static void rgb_merge(Image *dst, const Image *src,
int x, int y, int opacity, int blend_mode)
{
BLEND_COLOR blender = _rgba_blenders[blend_mode];
ase_uint32 *src_address;
@ -171,11 +171,11 @@ static void rgb_merge (Image *dst, const Image *src,
/* merge process */
for (ydst=ybeg; ydst<=yend; ydst++, ysrc++) {
src_address = LINES (src)[ysrc]+xsrc;
dst_address = LINES (dst)[ydst]+xbeg;
src_address = LINES(src)[ysrc]+xsrc;
dst_address = LINES(dst)[ydst]+xbeg;
for (xdst=xbeg; xdst<=xend; xdst++) {
*dst_address = (*blender) (*dst_address, *src_address, opacity);
*dst_address = (*blender)(*dst_address, *src_address, opacity);
dst_address++;
src_address++;
@ -183,28 +183,28 @@ static void rgb_merge (Image *dst, const Image *src,
}
}
static void rgb_hline (Image *image, int x1, int y, int x2, int color)
static void rgb_hline(Image *image, int x1, int y, int x2, int color)
{
ase_uint32 *address = LINES (image)[y]+x1;
ase_uint32 *address = LINES(image)[y]+x1;
int x;
for (x=x1; x<=x2; x++)
*(address++) = color;
}
static void rgb_rectfill (Image *image, int x1, int y1, int x2, int y2, int color)
static void rgb_rectfill(Image *image, int x1, int y1, int x2, int y2, int color)
{
ase_uint32 *address;
int x, y;
for (y=y1; y<=y2; y++) {
address = LINES (image)[y]+x1;
address = LINES(image)[y]+x1;
for (x=x1; x<=x2; x++)
*(address++) = color;
}
}
static void rgb_to_allegro (const Image *image, BITMAP *bmp, int _x, int _y)
static void rgb_to_allegro(const Image *image, BITMAP *bmp, int _x, int _y)
{
ase_uint32 *address = BYTES(image);
unsigned long bmp_address;
@ -332,7 +332,7 @@ static void rgb_to_allegro (const Image *image, BITMAP *bmp, int _x, int _y)
break;
}
bmp_unwrite_line (bmp);
bmp_unwrite_line(bmp);
}
static ImageMethods rgb_methods =

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -162,6 +162,7 @@ void layer_free(Layer *layer)
JLink link;
JI_LIST_FOR_EACH(layer->layers, link)
layer_free(link->data);
jlist_free(layer->layers);
break;
}
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -1163,14 +1163,10 @@ static void chunk_set_mask_invert(UndoStream *stream, UndoChunk *chunk, int stat
if (sprite) {
Mask *mask = undo_chunk_read_mask(chunk);
/* ji_assert(mask); */
chunk_set_mask(stream, sprite);
mask_copy(sprite->mask, mask);
/* change the sprite mask directly */
/* mask_free(sprite->mask); */
/* sprite->mask = mask; */
mask_free(mask);
}
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

55
src/test/test_errno.c Normal file
View File

@ -0,0 +1,55 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "test/test.h"
#include <errno.h>
#include <allegro.h>
#include "jinete/jthread.h"
static JThread thread;
static void run_thread(void *data)
{
errno = 0;
trace("[second thread] errno: %d\n", errno);
assert(errno == 0);
}
int main(int argc, char *argv[])
{
allegro_init();
errno = 1;
trace("[main thread] errno: %d\n", errno);
assert(errno == 1);
thread = jthread_new(run_thread, NULL);
jthread_join(thread);
trace("[main thread] errno: %d\n", errno);
assert(errno == 1);
trace("OK: errno is thread safe\n");
allegro_exit();
return 0;
}
END_OF_MAIN();

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008 David A. Capello
* Copyright (C) 2001-2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -20,8 +20,10 @@
#ifndef USE_PRECOMPILED_HEADER
#include <stdio.h>
#include <allegro.h>
#include "file/file.h"
#include "raster/image.h"
#endif
@ -40,12 +42,12 @@ RGB *load_col_file(const char *filename)
div_t d = div(size-8, 3);
RGB *palette = NULL;
int c, r, g, b;
PACKFILE *f;
FILE *f;
if (!(size) || (pro && d.rem)) /* invalid format */
return NULL;
f = pack_fopen(filename, F_READ);
f = fopen(filename, "rb");
if (!f)
return NULL;
@ -54,9 +56,9 @@ RGB *load_col_file(const char *filename)
palette = jmalloc(sizeof (PALETTE));
for (c=0; c<256; c++) {
r = pack_getc(f);
g = pack_getc(f);
b = pack_getc(f);
r = fgetc(f);
g = fgetc(f);
b = fgetc(f);
palette[c].r = MID(0, r, 63);
palette[c].g = MID(0, g, 63);
palette[c].b = MID(0, b, 63);
@ -66,22 +68,22 @@ RGB *load_col_file(const char *filename)
else {
int magic, version;
pack_igetl(f); /* skip file size */
magic = pack_igetw(f); /* file format identifier */
version = pack_igetw(f); /* version file */
fgetl(f); /* skip file size */
magic = fgetw(f); /* file format identifier */
version = fgetw(f); /* version file */
/* unknown format */
if (magic != 0xB123 || version != 0) {
pack_fclose (f);
fclose (f);
return NULL;
}
palette = jmalloc(sizeof (PALETTE));
for (c=0; c<d.quot && c<256; c++) {
r = pack_getc(f);
g = pack_getc(f);
b = pack_getc(f);
r = fgetc(f);
g = fgetc(f);
b = fgetc(f);
palette[c].r = MID(0, r, 255)>>2;
palette[c].g = MID(0, g, 255)>>2;
palette[c].b = MID(0, b, 255)>>2;
@ -91,30 +93,30 @@ RGB *load_col_file(const char *filename)
palette[c].r = palette[c].g = palette[c].b = 0;
}
pack_fclose(f);
fclose(f);
return palette;
}
/* saves an Animator Pro COL file */
int save_col_file(RGB *palette, const char *filename)
{
PACKFILE *f;
FILE *f;
int c;
f = pack_fopen(filename, F_WRITE);
f = fopen(filename, "wb");
if (!f)
return -1;
pack_iputl(8+768, f); /* file size */
pack_iputw(0xB123, f); /* file format identifier */
pack_iputw(0, f); /* version file */
fputl(8+768, f); /* file size */
fputw(0xB123, f); /* file format identifier */
fputw(0, f); /* version file */
for (c=0; c<256; c++) {
pack_putc(_rgb_scale_6[palette[c].r], f);
pack_putc(_rgb_scale_6[palette[c].g], f);
pack_putc(_rgb_scale_6[palette[c].b], f);
fputc(_rgb_scale_6[palette[c].r], f);
fputc(_rgb_scale_6[palette[c].g], f);
fputc(_rgb_scale_6[palette[c].b], f);
}
pack_fclose(f);
fclose(f);
return 0;
}

View File

@ -988,25 +988,10 @@ static bool editor_msg_proc(JWidget widget, JMessage msg)
if (!editor->sprite) {
JWidget view = jwidget_get_view(widget);
JRect vp = jview_get_viewport_position(view);
int size, x1, y1, x2, y2, cx, cy;
int bg = makecol(128, 128, 128);
int fg = makecol(64, 64, 64);
jdraw_rectfill(vp, bg);
size = MIN(jrect_w(vp), jrect_h(vp)) - 8;
size = MID(4, size, 64);
cx = (vp->x1+vp->x2)/2;
cy = (vp->y1+vp->y2)/2;
x1 = (vp->x1+vp->x2)/2-size/2;
y1 = (vp->y1+vp->y2)/2-size/2;
x2 = x1+size-1;
y2 = y1+size-1;
circle(ji_screen, cx, cy, size/2, fg);
line(ji_screen, x1, y2, x2, y1, fg);
jdraw_rectfill(vp, makecol(128, 128, 128));
draw_emptyset_symbol(vp, makecol(64, 64, 64));
jrect_free(vp);
}
/* draw the sprite */

View File

@ -18,17 +18,30 @@
#include "config.h"
#ifndef USE_PRECOMPILED_HEADER
#include <assert.h>
#include <allegro.h>
#include "jinete/jinete.h"
#include "commands/commands.h"
#include "console/console.h"
#include "core/app.h"
#include "dialogs/filesel.h"
#include "file/file.h"
#include "modules/editors.h"
#include "modules/gfx.h"
#include "modules/gui.h"
#include "modules/palette.h"
#include "modules/recent.h"
#include "modules/sprites.h"
#include "raster/image.h"
#include "raster/rotate.h"
#include "raster/sprite.h"
#include "widgets/fileview.h"
#include "widgets/statebar.h"
#endif
#define MAX_THUMBNAIL_SIZE 128
#define MAX_THREADS_TO_GEN_THUMBNAILS 1
typedef struct FileView
{
@ -38,8 +51,24 @@ typedef struct FileView
int req_w, req_h;
FileItem *selected;
const char *exts;
/* round-robin thumbnail generation process */
JLink item_to_generate_thumbnail; /* current item in the round-robin */
int round_timer_id;
JList monitors; /* list of monitors watching threads */
} FileView;
typedef struct ThumbnailData
{
Monitor *monitor;
FileOp *fop;
FileItem *fileitem;
JWidget fileview;
Image *thumbnail;
JThread thread;
PALETTE pal;
} ThumbnailData;
static FileView *fileview_data(JWidget widget);
static bool fileview_msg_proc(JWidget widget, JMessage msg);
static void fileview_get_fileitem_size(JWidget widget, FileItem *fi, int *w, int *h);
@ -47,6 +76,13 @@ static void fileview_make_selected_fileitem_visible(JWidget widget);
static void fileview_regenerate_list(JWidget widget);
static int fileview_get_selected_index(JWidget widget);
static void fileview_select_index(JWidget widget, int index);
static void fileview_selected_item_to_generate_thumbnail(JWidget widget);
static void fileview_generate_all_thumbnails(JWidget widget);
static bool fileview_generate_thumbnail(JWidget widget, FileItem *fileitem);
static void openfile_bg(void *data);
static void monitor_thumbnail_generation(void *data);
static void monitor_free_thumbnail_generation(void *data);
JWidget fileview_new(FileItem *start_folder, const char *exts)
{
@ -72,6 +108,10 @@ JWidget fileview_new(FileItem *start_folder, const char *exts)
fileview->selected = NULL;
fileview->exts = exts;
fileview->item_to_generate_thumbnail = NULL;
fileview->round_timer_id = jmanager_add_timer(widget, 200);
fileview->monitors = jlist_new();
fileview_regenerate_list(widget);
return widget;
@ -131,6 +171,23 @@ void fileview_goup(JWidget widget)
}
}
void fileview_stop_threads(JWidget widget)
{
FileView *fileview = fileview_data(widget);
JLink link, next;
/* stop the generation of threads */
jmanager_stop_timer(fileview->round_timer_id);
/* join all threads (removing all monitors) */
JI_LIST_FOR_EACH_SAFE(fileview->monitors, link, next) {
remove_gui_monitor(link->data);
}
/* clear the list of monitors */
jlist_clear(fileview->monitors);
}
static FileView *fileview_data(JWidget widget)
{
return jwidget_get_data(widget, fileview_type());
@ -143,6 +200,11 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg)
switch (msg->type) {
case JM_DESTROY:
/* at this point, can't be threads running in background */
assert(jlist_empty(fileview->monitors));
jlist_free(fileview->monitors);
jmanager_remove_timer(fileview->round_timer_id);
jfree(fileview);
break;
@ -173,6 +235,8 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg)
return TRUE;
case JM_DRAW: {
JWidget view = jwidget_get_view(widget);
JRect vp = jview_get_viewport_position(view);
FileItem *fi;
JLink link;
int iw, ih;
@ -181,6 +245,8 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg)
int row = 0;
int bgcolor;
int fgcolor;
BITMAP *thumbnail = NULL;
int thumbnail_y;
jdraw_rectfill(widget->rc, makecol(255, 255, 255));
@ -217,14 +283,40 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg)
x += ji_font_text_len(widget->text_font, "[+]")+2;
}
/* item name */
jdraw_text(widget->text_font,
fileitem_get_displayname(fi), x, y+2,
fgcolor, 0, FALSE);
/* thumbnail position */
if (fi == fileview->selected) {
thumbnail = fileitem_get_thumbnail(fi);
if (thumbnail)
thumbnail_y = y + ih/2;
}
y += ih;
row ^= 1;
}
/* draw the thumbnail */
if (thumbnail) {
x = vp->x2-2-thumbnail->w;
y = thumbnail_y-thumbnail->h/2;
y = MID(vp->y1+2, y, vp->y2-3-thumbnail->h);
draw_sprite(ji_screen, thumbnail, x, y);
rect(ji_screen,
x-1, y-1, x+thumbnail->w, y+thumbnail->h,
makecol(0, 0, 0));
}
/* is the current folder empty? */
if (jlist_empty(fileview->list))
draw_emptyset_symbol(vp, makecol(194, 194, 194));
jrect_free(vp);
break;
}
@ -258,6 +350,8 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg)
}
if (old_selected != fileview->selected) {
fileview_selected_item_to_generate_thumbnail(widget);
jwidget_dirty(widget);
jwidget_emit_signal(widget, SIGNAL_FILEVIEW_FILE_SELECTED);
}
@ -370,6 +464,33 @@ static bool fileview_msg_proc(JWidget widget, JMessage msg)
}
break;
case JM_TIMER:
/* is time to generate the next thumbnail in the round-robin? */
if (msg->timer.timer_id == fileview->round_timer_id &&
jlist_length(fileview->monitors) < MAX_THREADS_TO_GEN_THUMBNAILS) {
JLink link = fileview->item_to_generate_thumbnail;
JLink start = link;
while (link != fileview->list->end) {
FileItem *fileitem = link->data;
link = link->next != fileview->list->end ? link->next:
link->next->next;
if (fileview_generate_thumbnail(widget, fileitem))
break;
if (link == start)
break;
}
/* did we do all the round? */
if (link == start)
jmanager_stop_timer(fileview->round_timer_id);
fileview->item_to_generate_thumbnail = link;
}
break;
}
return FALSE;
@ -457,6 +578,9 @@ static void fileview_regenerate_list(JWidget widget)
}
else
fileview->list = jlist_new();
/* generate all thumbnails */
fileview_generate_all_thumbnails(widget);
}
static int fileview_get_selected_index(JWidget widget)
@ -482,8 +606,183 @@ static void fileview_select_index(JWidget widget, int index)
fileview->selected = jlist_nth_data(fileview->list, index);
if (old_selected != fileview->selected) {
fileview_make_selected_fileitem_visible(widget);
jwidget_dirty(widget);
jwidget_emit_signal(widget, SIGNAL_FILEVIEW_FILE_SELECTED);
}
fileview_selected_item_to_generate_thumbnail(widget);
}
/* puts the selected file-item as the next item to be processed by the
round-robin that generate thumbnails */
static void fileview_selected_item_to_generate_thumbnail(JWidget widget)
{
FileView *fileview = fileview_data(widget);
if (fileview->selected &&
!fileitem_is_folder(fileview->selected) &&
!fileitem_get_thumbnail(fileview->selected)) {
fileview->item_to_generate_thumbnail =
jlist_find(fileview->list, fileview->selected);
}
}
static void fileview_generate_all_thumbnails(JWidget widget)
{
FileView *fileview = fileview_data(widget);
fileview->item_to_generate_thumbnail = jlist_first(fileview->list);
jmanager_start_timer(fileview->round_timer_id);
}
/* returns true if it does some hard work like access to the disk */
static bool fileview_generate_thumbnail(JWidget widget, FileItem *fileitem)
{
FileOp *fop;
if (fileitem_is_browsable(fileitem) ||
fileitem_get_thumbnail(fileitem) != NULL)
return FALSE;
fop = fop_to_load_sprite(fileitem_get_filename(fileitem),
FILE_LOAD_SEQUENCE_NONE |
FILE_LOAD_ONE_FRAME);
if (!fop)
return TRUE;
if (fop->error) {
fop_free(fop);
}
else {
ThumbnailData *data = jnew(ThumbnailData, 1);
data->fop = fop;
data->fileitem = fileitem;
data->fileview = widget;
data->thumbnail = NULL;
data->thread = jthread_new(openfile_bg, data);
if (data->thread) {
/* add a monitor to check the loading (FileOp) progress */
data->monitor = add_gui_monitor(monitor_thumbnail_generation,
monitor_free_thumbnail_generation, data);
jlist_append(fileview_data(widget)->monitors, data->monitor);
}
else {
fop_free(fop);
jfree(data);
}
}
return TRUE;
}
/**
* Thread to do the hard work: load the file from the disk (in
* background).
*
* [loading thread]
*/
static void openfile_bg(void *_data)
{
ThumbnailData *data = (ThumbnailData *)_data;
FileOp *fop = (FileOp *)data->fop;
Sprite *sprite;
int thumb_w, thumb_h;
Image *image;
/* load the file */
fop_operate(fop);
sprite = fop->sprite;
if (sprite) {
if (fop_is_stop(fop))
sprite_free(fop->sprite);
else {
/* the palette to convert the Image to a BITMAP */
palette_copy(data->pal, sprite_get_palette(sprite, 0));
/* render the 'sprite' in one plain 'image' */
image = image_new(sprite->imgtype, sprite->w, sprite->h);
image_clear(image, 0);
sprite_render(sprite, image, 0, 0);
sprite_free(sprite);
/* calculate the thumbnail size */
thumb_w = MAX_THUMBNAIL_SIZE * image->w / MAX(image->w, image->h);
thumb_h = MAX_THUMBNAIL_SIZE * image->h / MAX(image->w, image->h);
if (MAX(thumb_w, thumb_h) > MAX(image->w, image->h)) {
thumb_w = image->w;
thumb_h = image->h;
}
thumb_w = MID(1, thumb_w, MAX_THUMBNAIL_SIZE);
thumb_h = MID(1, thumb_h, MAX_THUMBNAIL_SIZE);
/* stretch the 'image' */
data->thumbnail = image_new(image->imgtype, thumb_w, thumb_h);
image_clear(data->thumbnail, 0);
image_scale(data->thumbnail, image, 0, 0, thumb_w, thumb_h);
image_free(image);
}
}
fop_done(fop);
}
/**
* Called by the gui-monitor (a timer in the gui module that is called
* every 100 milliseconds).
*
* [main thread]
*/
static void monitor_thumbnail_generation(void *_data)
{
ThumbnailData *data = (ThumbnailData *)_data;
FileOp *fop = (FileOp *)data->fop;
/* is done? ...ok, now the thumbnail is in the main thread only... */
if (fop_is_done(fop)) {
/* set the thumbnail of the file-item */
if (data->thumbnail) {
BITMAP *bmp = create_bitmap(data->thumbnail->w,
data->thumbnail->h);
select_palette(data->pal);
image_to_allegro(data->thumbnail, bmp, 0, 0);
unselect_palette();
image_free(data->thumbnail);
fileitem_set_thumbnail(data->fileitem, bmp);
/* is the selected file-item the one that now has a thumbnail? */
if (fileview_get_selected(data->fileview) == data->fileitem) {
/* we have to dirty the file-view to show the thumbnail */
jwidget_dirty(data->fileview);
}
}
remove_gui_monitor(data->monitor);
}
}
/**
* [main thread]
*/
static void monitor_free_thumbnail_generation(void *_data)
{
ThumbnailData *data = (ThumbnailData *)_data;
FileOp *fop = (FileOp *)data->fop;
fop_stop(fop);
jthread_join(data->thread);
jlist_remove(fileview_data(data->fileview)->monitors,
data->monitor);
fop_free(fop);
jfree(data);
}

View File

@ -36,5 +36,6 @@ FileItem *fileview_get_selected(JWidget fileview);
void fileview_set_current_folder(JWidget widget, FileItem *folder);
void fileview_goup(JWidget fileview);
void fileview_stop_threads(JWidget fileview);
#endif /* WIDGETS_FILEVIEW_H */