New: Picture effects screen, resizes / mirrors / rotates image (Issue 73)

New: Distort brush (Issue 34)
New: Pixel scaler "Triple" for 3x3 zoom (Issue 147)
New: Pixel scaler "Quadruple" for 4x4 zoom (Issue 151)
New: Pixel scaler "Wide2" for 4x2 zoom (Issue 148)
New: Pixel scaler "Tall2" for 2x4 zoom (Issue 149)
Fix of very old bug: Resizing the image didn't mark the image 'modified since last save'

git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@763 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud 2009-05-02 16:44:06 +00:00
parent c1a1d88592
commit e5f948076b
37 changed files with 3952 additions and 481 deletions

View File

@ -236,7 +236,7 @@ endif
.PHONY : all debug release clean depend zip version force install uninstall .PHONY : all debug release clean depend zip version force install uninstall
# This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically.
OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o
all : $(BIN) all : $(BIN)

View File

@ -1,6 +1,6 @@
$(OBJDIR)/SFont.o: SFont.c SFont.h $(OBJDIR)/SFont.o: SFont.c SFont.h
$(OBJDIR)/brush.o: brush.c global.h struct.h const.h graph.h misc.h errors.h \ $(OBJDIR)/brush.o: brush.c global.h struct.h const.h graph.h misc.h errors.h \
windows.h sdlscreen.h windows.h sdlscreen.h brush.h
$(OBJDIR)/buttons.o: buttons.c const.h struct.h global.h misc.h graph.h engine.h \ $(OBJDIR)/buttons.o: buttons.c const.h struct.h global.h misc.h graph.h engine.h \
readline.h filesel.h loadsave.h init.h buttons.h operatio.h pages.h \ readline.h filesel.h loadsave.h init.h buttons.h operatio.h pages.h \
errors.h readini.h saveini.h shade.h io.h help.h text.h sdlscreen.h \ errors.h readini.h saveini.h shade.h io.h help.h text.h sdlscreen.h \
@ -10,21 +10,21 @@ $(OBJDIR)/engine.o: engine.c const.h struct.h global.h graph.h misc.h special.h
input.h engine.h input.h engine.h
$(OBJDIR)/filesel.o: filesel.c const.h struct.h global.h misc.h errors.h io.h \ $(OBJDIR)/filesel.o: filesel.c const.h struct.h global.h misc.h errors.h io.h \
windows.h sdlscreen.h loadsave.h mountlist.h engine.h readline.h \ windows.h sdlscreen.h loadsave.h mountlist.h engine.h readline.h \
input.h help.h input.h help.h filesel.h
$(OBJDIR)/graph.o: graph.c global.h struct.h const.h engine.h buttons.h pages.h \ $(OBJDIR)/graph.o: graph.c global.h struct.h const.h engine.h buttons.h pages.h \
errors.h sdlscreen.h graph.h misc.h pxsimple.h pxtall.h pxwide.h \ errors.h sdlscreen.h graph.h misc.h pxsimple.h pxtall.h pxwide.h \
pxdouble.h windows.h pxdouble.h pxtriple.h pxwide2.h pxtall2.h pxquad.h windows.h
$(OBJDIR)/help.o: help.c const.h struct.h global.h misc.h engine.h helpfile.h \ $(OBJDIR)/help.o: help.c const.h struct.h global.h misc.h engine.h helpfile.h \
help.h sdlscreen.h text.h keyboard.h windows.h input.h hotkeys.h \ help.h sdlscreen.h text.h keyboard.h windows.h input.h hotkeys.h \
errors.h errors.h
$(OBJDIR)/hotkeys.o: hotkeys.c struct.h const.h global.h hotkeys.h $(OBJDIR)/hotkeys.o: hotkeys.c struct.h const.h global.h hotkeys.h
$(OBJDIR)/init.o: init.c const.h struct.h global.h graph.h buttons.h palette.h \ $(OBJDIR)/init.o: init.c const.h struct.h global.h graph.h buttons.h palette.h \
help.h operatio.h misc.h errors.h keyboard.h io.h hotkeys.h setup.h \ help.h operatio.h misc.h errors.h keyboard.h io.h hotkeys.h setup.h \
windows.h sdlscreen.h mountlist.h loadsave.h windows.h sdlscreen.h mountlist.h loadsave.h init.h transform.h
$(OBJDIR)/input.o: input.c global.h struct.h const.h keyboard.h sdlscreen.h \ $(OBJDIR)/input.o: input.c global.h struct.h const.h keyboard.h sdlscreen.h \
windows.h errors.h misc.h input.h windows.h errors.h misc.h input.h
$(OBJDIR)/io.o: io.c struct.h const.h io.h realpath.h $(OBJDIR)/io.o: io.c struct.h const.h io.h realpath.h
$(OBJDIR)/keyboard.o: keyboard.c global.h struct.h const.h $(OBJDIR)/keyboard.o: keyboard.c global.h struct.h const.h keyboard.h
$(OBJDIR)/loadsave.o: loadsave.c buttons.h struct.h const.h errors.h global.h io.h \ $(OBJDIR)/loadsave.o: loadsave.c buttons.h struct.h const.h errors.h global.h io.h \
loadsave.h misc.h op_c.h pages.h palette.h sdlscreen.h windows.h loadsave.h misc.h op_c.h pages.h palette.h sdlscreen.h windows.h
$(OBJDIR)/main.o: main.c const.h struct.h global.h graph.h misc.h init.h buttons.h \ $(OBJDIR)/main.o: main.c const.h struct.h global.h graph.h misc.h init.h buttons.h \
@ -39,27 +39,40 @@ $(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h graph
$(OBJDIR)/pages.o: pages.c global.h struct.h const.h pages.h errors.h misc.h \ $(OBJDIR)/pages.o: pages.c global.h struct.h const.h pages.h errors.h misc.h \
windows.h windows.h
$(OBJDIR)/palette.o: palette.c const.h struct.h global.h misc.h engine.h readline.h \ $(OBJDIR)/palette.o: palette.c const.h struct.h global.h misc.h engine.h readline.h \
buttons.h pages.h help.h sdlscreen.h errors.h op_c.h windows.h input.h buttons.h pages.h help.h sdlscreen.h errors.h op_c.h windows.h input.h \
palette.h
$(OBJDIR)/pxdouble.o: pxdouble.c global.h struct.h const.h sdlscreen.h misc.h \ $(OBJDIR)/pxdouble.o: pxdouble.c global.h struct.h const.h sdlscreen.h misc.h \
pxwide.h pxdouble.h pxwide.h
$(OBJDIR)/pxsimple.o: pxsimple.c global.h struct.h const.h sdlscreen.h misc.h $(OBJDIR)/pxquad.o: pxquad.c global.h struct.h const.h sdlscreen.h misc.h pxquad.h
$(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h sdlscreen.h misc.h \ $(OBJDIR)/pxsimple.o: pxsimple.c global.h struct.h const.h sdlscreen.h misc.h \
pxsimple.h pxsimple.h
$(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h sdlscreen.h misc.h $(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h sdlscreen.h misc.h pxtall.h \
$(OBJDIR)/readini.o: readini.c const.h global.h struct.h misc.h pxsimple.h
$(OBJDIR)/pxtall2.o: pxtall2.c global.h struct.h const.h sdlscreen.h misc.h \
pxtall2.h
$(OBJDIR)/pxtriple.o: pxtriple.c global.h struct.h const.h sdlscreen.h misc.h \
pxtriple.h
$(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h sdlscreen.h misc.h pxwide.h
$(OBJDIR)/pxwide2.o: pxwide2.c global.h struct.h const.h sdlscreen.h misc.h \
pxwide2.h
$(OBJDIR)/readini.o: readini.c const.h global.h struct.h misc.h readini.h
$(OBJDIR)/readline.o: readline.c const.h struct.h global.h misc.h errors.h \ $(OBJDIR)/readline.o: readline.c const.h struct.h global.h misc.h errors.h \
sdlscreen.h readline.h windows.h input.h sdlscreen.h readline.h windows.h input.h
$(OBJDIR)/realpath.o: realpath.c $(OBJDIR)/realpath.o: realpath.c
$(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h readini.h io.h errors.h \ $(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h readini.h io.h errors.h \
misc.h misc.h saveini.h
$(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h sdlscreen.h errors.h \ $(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h sdlscreen.h errors.h \
misc.h misc.h
$(OBJDIR)/setup.o: setup.c struct.h const.h io.h $(OBJDIR)/setup.o: setup.c struct.h const.h io.h setup.h
$(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h misc.h \ $(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h misc.h \
readline.h help.h sdlscreen.h windows.h input.h readline.h help.h sdlscreen.h windows.h input.h shade.h
$(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h windows.h $(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h windows.h \
special.h
$(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.h \ $(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.h \
errors.h errors.h
$(OBJDIR)/transform.o: transform.c global.h struct.h const.h transform.h engine.h \
sdlscreen.h windows.h input.h help.h misc.h readline.h buttons.h \
pages.h
$(OBJDIR)/version.o: version.c $(OBJDIR)/version.o: version.c
$(OBJDIR)/windows.o: windows.c windows.h struct.h const.h global.h graph.h engine.h \ $(OBJDIR)/windows.o: windows.c windows.h struct.h const.h global.h graph.h engine.h \
misc.h sdlscreen.h errors.h misc.h sdlscreen.h errors.h

285
brush.c
View File

@ -718,7 +718,7 @@ void Rotate_90_deg()
new_brush=(byte *)malloc(((long)Brush_height)*Brush_width); new_brush=(byte *)malloc(((long)Brush_height)*Brush_width);
if (new_brush) if (new_brush)
{ {
Rotate_90_deg_lowlevel(Brush,new_brush); Rotate_90_deg_lowlevel(Brush,new_brush,Brush_width,Brush_height);
free(Brush); free(Brush);
Brush=new_brush; Brush=new_brush;
@ -1149,75 +1149,32 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear)
void Stretch_brush(short x1, short y1, short x2, short y2) void Stretch_brush(short x1, short y1, short x2, short y2)
{ {
int offset,line,column;
byte * new_brush; byte * new_brush;
int new_brush_width; // Width de la nouvelle brosse int new_brush_width; // Width de la nouvelle brosse
int new_brush_height; // Height de la nouvelle brosse int new_brush_height; // Height de la nouvelle brosse
int x_flipped, y_flipped;
int x_pos_in_brush; // Position courante dans l'ancienne brosse
int y_pos_in_brush; // Compute new brush dimensions
int delta_x_in_brush; // "Vecteur incrémental" du point précédent
int delta_y_in_brush;
int initial_x_pos; // Position X de début de parcours de ligne
int dx,dy;
dx=(x1<x2)?1:-1;
dy=(y1<y2)?1:-1;
// Calcul des nouvelles dimensions de la brosse:
if ((new_brush_width=x1-x2)<0) if ((new_brush_width=x1-x2)<0)
{
x_flipped=1;
new_brush_width=-new_brush_width; new_brush_width=-new_brush_width;
}
new_brush_width++; new_brush_width++;
if ((new_brush_height=y1-y2)<0) if ((new_brush_height=y1-y2)<0)
{
y_flipped=1;
new_brush_height=-new_brush_height; new_brush_height=-new_brush_height;
}
new_brush_height++; new_brush_height++;
// Calcul des anciennes dimensions de la brosse: // Free some memory
free(Smear_brush);
// Calcul du "vecteur incrémental":
delta_x_in_brush=(Brush_width<<16)/(x2-x1+dx);
delta_y_in_brush=(Brush_height<<16)/(y2-y1+dy);
// Calcul de la valeur initiale de x_pos pour chaque ligne:
if (dx>=0)
initial_x_pos = 0; // Pas d'inversion en X de la brosse
else
initial_x_pos = (Brush_width<<16)-1; // Inversion en X de la brosse
free(Smear_brush); // On libère un peu de mémoire
if ((new_brush=((byte *)malloc(new_brush_width*new_brush_height)))) if ((new_brush=((byte *)malloc(new_brush_width*new_brush_height))))
{ {
offset=0; Rescale(Brush, Brush_width, Brush_height, new_brush, new_brush_width, new_brush_height, x2<x1, y2<y1);
// Calcul de la valeur initiale de y_pos:
if (dy>=0)
y_pos_in_brush=0; // Pas d'inversion en Y de la brosse
else
y_pos_in_brush=(Brush_height<<16)-1; // Inversion en Y de la brosse
// Pour chaque ligne
for (line=0;line<new_brush_height;line++)
{
// On repart du début de la ligne:
x_pos_in_brush=initial_x_pos;
// Pour chaque colonne:
for (column=0;column<new_brush_width;column++)
{
// On copie le pixel:
new_brush[offset]=Read_pixel_from_brush(x_pos_in_brush>>16,y_pos_in_brush>>16);
// On passe à la colonne de brosse suivante:
x_pos_in_brush+=delta_x_in_brush;
// On passe au pixel suivant de la nouvelle brosse:
offset++;
}
// On passe à la ligne de brosse suivante:
y_pos_in_brush+=delta_y_in_brush;
}
free(Brush); free(Brush);
Brush=new_brush; Brush=new_brush;
@ -1248,7 +1205,7 @@ void Stretch_brush(short x1, short y1, short x2, short y2)
} }
else else
{ {
// Ici la libération de mémoire n'a pas suffit donc on remet dans l'état // Ici la libération de mémoire n'a pas suffi donc on remet dans l'état
// où c'etait avant. On a juste à réallouer la Smear_brush car il y a // où c'etait avant. On a juste à réallouer la Smear_brush car il y a
// normalement la place pour elle puisque rien d'autre n'a pu être alloué // normalement la place pour elle puisque rien d'autre n'a pu être alloué
// entre temps. // entre temps.
@ -1335,7 +1292,221 @@ void Stretch_brush_preview(short x1, short y1, short x2, short y2)
Update_part_of_screen(initial_dest_x_pos,initial_dest_y_pos,dest_width,dest_height); Update_part_of_screen(initial_dest_x_pos,initial_dest_y_pos,dest_width,dest_height);
} }
/// Returns the minimum of 4 integers.
inline int Min4(int a,int b,int c,int d)
{
if (a<b)
if (c<d)
return a<c?a:c;
else
return a<d?a:d;
else
if (c<d)
return b<c?b:c;
else
return b<d?b:d;
}
//-------------------- Brush distort -------------------------------
// That's a lot of globals, but it saves stack space in the recursive calls.
static Func_pixel Pixel_for_distort;
static byte * Distort_buffer;
static short Distort_buffer_width;
/// Draw a pixel in the target buffer. No clipping.
void Pixel_in_distort_buffer(word x_pos,word y_pos,byte color)
{
*(Distort_buffer+y_pos*Distort_buffer_width+x_pos)=color;
}
/// Returns the maximum of 4 integers.
inline int Max4(int a,int b,int c,int d)
{
if (a>b)
if (c>d)
return a>c?a:c;
else
return a>d?a:d;
else
if (c>d)
return b>c?b:c;
else
return b>d?b:d;
}
// Recursive function for linear distortion.
void Draw_brush_linear_distort(long int tex_min_x,
long int tex_min_y,
long int tex_max_x,
long int tex_max_y,
long int x1,
long int y1,
long int x2,
long int y2,
long int x3,
long int y3,
long int x4,
long int y4)
{
static byte color;
// bounding rectangle
static long int min_x, max_x, min_y, max_y;
min_x=Min4(x1,x2,x3,x4);
max_x=Max4(x1,x2,x3,x4);
min_y=Min4(y1,y2,y3,y4);
max_y=Max4(y1,y2,y3,y4);
if ((max_x>>16) - (min_x>>16) <= 1 && (max_y>>16) - (min_y>>16) <= 1)
//if (max_x - min_x <= 1<<16 && max_y - min_y <= 1<<16)
{
if ((min_x<(max_x&0x7FFF0000)) && (min_y<(max_y&0x7FFF0000)))
{
color=Read_pixel_from_brush((tex_min_x)>>16,(tex_min_y)>>16);
if (color!=Back_color)
Pixel_for_distort(min_x>>16,min_y>>16,color);
}
return;
}
// Cut in 4 quarters and repeat
// "top left"
Draw_brush_linear_distort(tex_min_x,
tex_min_y,
(tex_min_x+tex_max_x)>>1,
(tex_min_y+tex_max_y)>>1,
x1,
y1,
(x1+x2)>>1,
(y1+y2)>>1,
(x1+x2+x3+x4)>>2,
(y1+y2+y3+y4)>>2,
(x1+x4)>>1,
(y1+y4)>>1);
// "top right"
Draw_brush_linear_distort((tex_min_x+tex_max_x)>>1,
tex_min_y,
tex_max_x,
(tex_min_y+tex_max_y)>>1,
(x1+x2)>>1,
(y1+y2)>>1,
x2,
y2,
(x2+x3)>>1,
(y2+y3)>>1,
(x1+x2+x3+x4)>>2,
(y1+y2+y3+y4)>>2);
// "bottom right"
Draw_brush_linear_distort((tex_min_x+tex_max_x)>>1,
(tex_min_y+tex_max_y)>>1,
tex_max_x,
tex_max_y,
(x1+x2+x3+x4)>>2,
(y1+y2+y3+y4)>>2,
(x2+x3)>>1,
(y2+y3)>>1,
x3,
y3,
(x3+x4)>>1,
(y3+y4)>>1);
// "bottom left"
Draw_brush_linear_distort(tex_min_x,
(tex_min_y+tex_max_y)>>1,
(tex_min_x+tex_max_x)>>1,
tex_max_y,
(x1+x4)>>1,
(y1+y4)>>1,
(x1+x2+x3+x4)>>2,
(y1+y2+y3+y4)>>2,
(x3+x4)>>1,
(y3+y4)>>1,
x4,
y4);
return;
}
/// Draws a distorted version of the brush, mapped over the given quad (picture coordinates).
void Distort_brush_preview(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4)
{
Pixel_for_distort=Pixel_figure_preview;
Draw_brush_linear_distort(0, 0, (Brush_width<<16), (Brush_height<<16), (x1<<16), (y1<<16), (x2<<16), (y2<<16), (x3<<16), (y3<<16), (x4<<16), (y4<<16));
}
/// Modifies the current brush, mapping it over the given quad.
void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4)
{
short min_x, max_x, min_y, max_y;
short width, height;
byte * new_brush;
byte * new_smear_brush;
short new_smear_brush_width;
short new_smear_brush_height;
// Move all coordinates to start on (0,0)
min_x=Min4(x1,x2,x3,x4);
max_x=Max4(x1,x2,x3,x4);
min_y=Min4(y1,y2,y3,y4);
max_y=Max4(y1,y2,y3,y4);
x1-=min_x;
x2-=min_x;
x3-=min_x;
x4-=min_x;
y1-=min_y;
y2-=min_y;
y3-=min_y;
y4-=min_y;
width=Max(max_x-min_x, 1);
height=Max(max_y-min_y, 1);
new_smear_brush_width=(width>MAX_PAINTBRUSH_SIZE)?width:MAX_PAINTBRUSH_SIZE;
new_smear_brush_height=(height>MAX_PAINTBRUSH_SIZE)?height:MAX_PAINTBRUSH_SIZE;
new_smear_brush=(byte *)malloc(((long)new_smear_brush_height)*new_smear_brush_width);
if (! new_smear_brush)
{
// Out of memory while allocating new smear brush
Error(0);
return;
}
new_brush=((byte *)malloc((long)width*height));
if (!new_brush)
{
// Out of memory while allocating new brush
Error(0);
free(new_smear_brush);
return;
}
// Fill the new brush with backcolor, originally.
memset(new_brush,Back_color,((long)width)*height);
// Call distort routine
Pixel_for_distort=Pixel_in_distort_buffer;
Distort_buffer=new_brush;
Distort_buffer_width=width;
Draw_brush_linear_distort(0, 0, (Brush_width<<16), (Brush_height<<16), (x1<<16), (y1<<16), (x2<<16), (y2<<16), (x3<<16), (y3<<16), (x4<<16), (y4<<16));
// Free old brushes
free(Smear_brush);
free(Brush);
// Point to the new ones
Brush=new_brush;
Brush_width=width;
Brush_height=height;
Smear_brush=new_smear_brush;
Smear_brush_width=new_smear_brush_width;
Smear_brush_height=new_smear_brush_height;
}
//------------------------- Rotation de la brosse --------------------------- //------------------------- Rotation de la brosse ---------------------------

12
brush.h
View File

@ -68,6 +68,18 @@ void Rotate_brush_preview(float angle);
Remap the brush palette to the nearest color in the picture one. Remap the brush palette to the nearest color in the picture one.
Used when switching to the spare page. Used when switching to the spare page.
*/ */
/*!
Distort the brush on the screen.
*/
void Distort_brush_preview(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4);
/*!
Replace the brush by a distorted version of itself.
*/
void Distort_brush(short x1, short y1, short x2, short y2, short x3, short y3, short x4, short y4);
void Remap_brush(void); void Remap_brush(void);
/*! /*!

View File

@ -1367,11 +1367,15 @@ void Button_Resolution(void)
char str[5]; char str[5];
T_Special_button * input_width_button, * input_button_height; T_Special_button * input_width_button, * input_button_height;
T_Dropdown_button * pixel_button; T_Dropdown_button * pixel_button;
static const char *pixel_ratio_labels[] ={ static const char *pixel_ratio_labels[PIXEL_MAX] ={
"Normal (1x1)", "Normal (1x1)",
"Wide (2x1)", "Wide (2x1)",
"Tall (1x2)", "Tall (1x2)",
"Double (2x2)"}; "Double (2x2)",
"Triple (3x3)",
"Wide2 (4x2)",
"Tall2 (2x4)",
"Quadruple (4x4)"};
Open_window(299,190,"Picture & screen sizes"); Open_window(299,190,"Picture & screen sizes");
@ -1423,11 +1427,9 @@ void Button_Resolution(void)
chosen_pixel=Pixel_ratio; chosen_pixel=Pixel_ratio;
Print_in_window( 12, 57,"Pixel size:" ,MC_Dark,MC_Light); Print_in_window( 12, 57,"Pixel size:" ,MC_Dark,MC_Light);
pixel_button=Window_set_dropdown_button(108,55,14*8,11,14*8,pixel_ratio_labels[Pixel_ratio],1,0,1,LEFT_SIDE|RIGHT_SIDE); // 7 pixel_button=Window_set_dropdown_button(108,55,17*8,11,17*8,pixel_ratio_labels[Pixel_ratio],1,0,1,LEFT_SIDE|RIGHT_SIDE); // 7
Window_dropdown_add_item(pixel_button,PIXEL_SIMPLE,pixel_ratio_labels[PIXEL_SIMPLE]); for (temp=0;temp<PIXEL_MAX;temp++)
Window_dropdown_add_item(pixel_button,PIXEL_WIDE,pixel_ratio_labels[PIXEL_WIDE]); Window_dropdown_add_item(pixel_button,temp,pixel_ratio_labels[temp]);
Window_dropdown_add_item(pixel_button,PIXEL_TALL,pixel_ratio_labels[PIXEL_TALL]);
Window_dropdown_add_item(pixel_button,PIXEL_DOUBLE,pixel_ratio_labels[PIXEL_DOUBLE]);
// 10 little buttons for the state of each visible mode // 10 little buttons for the state of each visible mode
for (temp=0; temp<MODELIST_LINES && temp < Nb_video_modes; temp++) for (temp=0; temp<MODELIST_LINES && temp < Nb_video_modes; temp++)
@ -3368,22 +3370,17 @@ void Button_Brush_FX(void)
switch (clicked_button) switch (clicked_button)
{ {
case 2 : // Flip X case 2 : // Flip X
Flip_X_lowlevel(); Flip_X_lowlevel(Brush, Brush_width, Brush_height);
break; break;
case 3 : // Flip Y case 3 : // Flip Y
Flip_Y_lowlevel(); Flip_Y_lowlevel(Brush, Brush_width, Brush_height);
break; break;
case 4 : // 90° Rotation case 4 : // 90° Rotation
Rotate_90_deg(); Rotate_90_deg();
break; break;
case 5 : // 180° Rotation case 5 : // 180° Rotation
if (Brush_height&1) if (Brush_height&1)
{ // Brush de hauteur impaire Rotate_180_deg_lowlevel(Brush, Brush_width, Brush_height);
Flip_X_lowlevel();
Flip_Y_lowlevel();
}
else
Rotate_180_deg_lowlevel();
Brush_offset_X=(Brush_width>>1); Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1); Brush_offset_Y=(Brush_height>>1);
break; break;
@ -3394,9 +3391,7 @@ void Button_Brush_FX(void)
Start_operation_stack(OPERATION_STRETCH_BRUSH); Start_operation_stack(OPERATION_STRETCH_BRUSH);
break; break;
case 8 : // Distort case 8 : // Distort
Display_cursor(); Start_operation_stack(OPERATION_DISTORT_BRUSH);
Message_not_implemented(); // !!! TEMPORAIRE !!!
Hide_cursor();
break; break;
case 9 : // Recolorize case 9 : // Recolorize
Remap_brush(); Remap_brush();

View File

@ -153,6 +153,10 @@ enum PIXEL_RATIO
PIXEL_WIDE, PIXEL_WIDE,
PIXEL_TALL, PIXEL_TALL,
PIXEL_DOUBLE, PIXEL_DOUBLE,
PIXEL_TRIPLE,
PIXEL_WIDE2,
PIXEL_TALL2,
PIXEL_QUAD,
PIXEL_MAX ///< Number of elements in enum PIXEL_MAX ///< Number of elements in enum
}; };

View File

@ -106,7 +106,7 @@ void Restore_effects(void)
char * Menu_tooltip[NB_BUTTONS]= char * Menu_tooltip[NB_BUTTONS]=
{ {
"Paintbrush choice ", "Paintbrush choice ",
"Adjust picture / Effects", "Adjust / Transform menu ",
"Freehand draw. / Toggle ", "Freehand draw. / Toggle ",
"Splines / Toggle ", "Splines / Toggle ",
"Lines / Toggle ", "Lines / Toggle ",
@ -407,6 +407,10 @@ void Unselect_button(int btn_number,byte click)
&& (!(Main_magnifier_mode && (b==BUTTON_MAGNIFIER))) ) && (!(Main_magnifier_mode && (b==BUTTON_MAGNIFIER))) )
// Alors on désenclenche le bouton // Alors on désenclenche le bouton
Unselect_bouton(b); Unselect_bouton(b);
// Right-clicking on Adjust opens a menu, so in this case we skip
// the unselection of all "Tool" buttons.
if (btn_number==BUTTON_ADJUST && click==RIGHT_SIDE)
break;
// Pour chaque bouton: // Pour chaque bouton:
for (b=0; b<NB_BUTTONS; b++) for (b=0; b<NB_BUTTONS; b++)
// S'il est de la męme famille // S'il est de la męme famille
@ -698,13 +702,13 @@ void Main_handler(void)
break; break;
case SPECIAL_FLIP_X : // Flip X case SPECIAL_FLIP_X : // Flip X
Hide_cursor(); Hide_cursor();
Flip_X_lowlevel(); Flip_X_lowlevel(Brush, Brush_width, Brush_height);
Display_cursor(); Display_cursor();
Key=0; Key=0;
break; break;
case SPECIAL_FLIP_Y : // Flip Y case SPECIAL_FLIP_Y : // Flip Y
Hide_cursor(); Hide_cursor();
Flip_Y_lowlevel(); Flip_Y_lowlevel(Brush, Brush_width, Brush_height);
Display_cursor(); Display_cursor();
Key=0; Key=0;
break; break;
@ -716,14 +720,7 @@ void Main_handler(void)
break; break;
case SPECIAL_ROTATE_180 : // 180° brush rotation case SPECIAL_ROTATE_180 : // 180° brush rotation
Hide_cursor(); Hide_cursor();
if (Brush_height&1) Rotate_180_deg_lowlevel(Brush, Brush_width, Brush_height);
{
// Brush de hauteur impaire
Flip_X_lowlevel();
Flip_Y_lowlevel();
}
else
Rotate_180_deg_lowlevel();
Brush_offset_X=(Brush_width>>1); Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1); Brush_offset_Y=(Brush_height>>1);
Display_cursor(); Display_cursor();
@ -736,7 +733,9 @@ void Main_handler(void)
Key=0; Key=0;
break; break;
case SPECIAL_DISTORT : // Distort brush case SPECIAL_DISTORT : // Distort brush
Message_not_implemented(); // !!! TEMPORAIRE !!! Hide_cursor();
Start_operation_stack(OPERATION_DISTORT_BRUSH);
Display_cursor();
Key=0; Key=0;
break; break;
case SPECIAL_ROTATE_ANY_ANGLE : // Rotate brush by any angle case SPECIAL_ROTATE_ANY_ANGLE : // Rotate brush by any angle

View File

@ -1040,7 +1040,7 @@ byte Button_Load_or_Save(byte load, byte image)
{ {
bookmark_dropdown[temp]= bookmark_dropdown[temp]=
Window_set_dropdown_button(127+(88+1)*(temp%2),18+(temp/2)*12,88,11,56,"",0,0,1,RIGHT_SIDE); // 10-13 Window_set_dropdown_button(127+(88+1)*(temp%2),18+(temp/2)*12,88,11,56,"",0,0,1,RIGHT_SIDE); // 10-13
Window_display_icon_sprite(bookmark_dropdown[temp]->Pos_X+3,bookmark_dropdown[temp]->Pos_Y+2,5); Window_display_icon_sprite(bookmark_dropdown[temp]->Pos_X+3,bookmark_dropdown[temp]->Pos_Y+2,ICON_STAR);
Display_bookmark(bookmark_dropdown[temp],temp); Display_bookmark(bookmark_dropdown[temp],temp);
} }
// On prend bien soin de passer dans le répertoire courant (le bon qui faut! Oui madame!) // On prend bien soin de passer dans le répertoire courant (le bon qui faut! Oui madame!)

BIN
gfx2.cfg

Binary file not shown.

117
graph.c
View File

@ -42,8 +42,15 @@
#include "pxtall.h" #include "pxtall.h"
#include "pxwide.h" #include "pxwide.h"
#include "pxdouble.h" #include "pxdouble.h"
#include "pxtriple.h"
#include "pxwide2.h"
#include "pxtall2.h"
#include "pxquad.h"
#include "windows.h" #include "windows.h"
// Generic pixel-drawing function.
Func_pixel Pixel_figure;
// Fonction qui met à jour la zone de l'image donnée en paramètre sur l'écran. // Fonction qui met à jour la zone de l'image donnée en paramètre sur l'écran.
// Tient compte du décalage X et Y et du zoom, et fait tous les controles nécessaires // Tient compte du décalage X et Y et du zoom, et fait tous les controles nécessaires
void Update_part_of_screen(short x, short y, short width, short height) void Update_part_of_screen(short x, short y, short width, short height)
@ -177,7 +184,6 @@ void Transform_point(short x, short y, float cos_a, float sin_a,
} }
//--------------------- Initialisation d'un mode vidéo ----------------------- //--------------------- Initialisation d'un mode vidéo -----------------------
int Init_mode_video(int width, int height, int fullscreen, int pix_ratio) int Init_mode_video(int width, int height, int fullscreen, int pix_ratio)
@ -213,6 +219,22 @@ int Init_mode_video(int width, int height, int fullscreen, int pix_ratio)
pix_width=2; pix_width=2;
pix_height=2; pix_height=2;
break; break;
case PIXEL_TRIPLE:
pix_width=3;
pix_height=3;
break;
case PIXEL_WIDE2:
pix_width=4;
pix_height=2;
break;
case PIXEL_TALL2:
pix_width=2;
pix_height=4;
break;
case PIXEL_QUAD:
pix_width=4;
pix_height=4;
break;
} }
screen_changed = (Screen_width*Pixel_width!=width || screen_changed = (Screen_width*Pixel_width!=width ||
@ -246,7 +268,7 @@ int Init_mode_video(int width, int height, int fullscreen, int pix_ratio)
// On AmigaOS the systems adds some more constraints on that ... // On AmigaOS the systems adds some more constraints on that ...
width = (width + 15) & 0xFFFFFFF0; width = (width + 15) & 0xFFFFFFF0;
#else #else
width = (width + 3 ) & 0xFFFFFFFC; //width = (width + 3 ) & 0xFFFFFFFC;
#endif #endif
pixels_changed = (Pixel_ratio!=pix_ratio); pixels_changed = (Pixel_ratio!=pix_ratio);
@ -257,6 +279,7 @@ int Init_mode_video(int width, int height, int fullscreen, int pix_ratio)
{ {
Set_mode_SDL(&width, &height,fullscreen); Set_mode_SDL(&width, &height,fullscreen);
} }
Clear_border(MC_Black);
if (screen_changed || pixels_changed) if (screen_changed || pixels_changed)
{ {
Pixel_ratio=pix_ratio; Pixel_ratio=pix_ratio;
@ -353,6 +376,94 @@ int Init_mode_video(int width, int height, int fullscreen, int pix_ratio)
Clear_brush_scaled = Clear_brush_scaled_double ; Clear_brush_scaled = Clear_brush_scaled_double ;
Display_brush = Display_brush_double ; Display_brush = Display_brush_double ;
break; break;
case PIXEL_TRIPLE:
Pixel = Pixel_triple ;
Read_pixel= Read_pixel_triple ;
Display_screen = Display_part_of_screen_triple ;
Block = Block_triple ;
Pixel_preview_normal = Pixel_preview_normal_triple ;
Pixel_preview_magnifier = Pixel_preview_magnifier_triple ;
Horizontal_XOR_line = Horizontal_XOR_line_triple ;
Vertical_XOR_line = Vertical_XOR_line_triple ;
Display_brush_color = Display_brush_color_triple ;
Display_brush_mono = Display_brush_mono_triple ;
Clear_brush = Clear_brush_triple ;
Remap_screen = Remap_screen_triple ;
Display_line = Display_line_on_screen_triple ;
Display_line_fast = Display_line_on_screen_fast_triple ;
Read_line = Read_line_screen_triple ;
Display_zoomed_screen = Display_part_of_screen_scaled_triple ;
Display_brush_color_zoom = Display_brush_color_zoom_triple ;
Display_brush_mono_zoom = Display_brush_mono_zoom_triple ;
Clear_brush_scaled = Clear_brush_scaled_triple ;
Display_brush = Display_brush_triple ;
break;
case PIXEL_WIDE2:
Pixel = Pixel_wide2 ;
Read_pixel= Read_pixel_wide2 ;
Display_screen = Display_part_of_screen_wide2 ;
Block = Block_wide2 ;
Pixel_preview_normal = Pixel_preview_normal_wide2 ;
Pixel_preview_magnifier = Pixel_preview_magnifier_wide2 ;
Horizontal_XOR_line = Horizontal_XOR_line_wide2 ;
Vertical_XOR_line = Vertical_XOR_line_wide2 ;
Display_brush_color = Display_brush_color_wide2 ;
Display_brush_mono = Display_brush_mono_wide2 ;
Clear_brush = Clear_brush_wide2 ;
Remap_screen = Remap_screen_wide2 ;
Display_line = Display_line_on_screen_wide2 ;
Display_line_fast = Display_line_on_screen_fast_wide2 ;
Read_line = Read_line_screen_wide2 ;
Display_zoomed_screen = Display_part_of_screen_scaled_wide2 ;
Display_brush_color_zoom = Display_brush_color_zoom_wide2 ;
Display_brush_mono_zoom = Display_brush_mono_zoom_wide2 ;
Clear_brush_scaled = Clear_brush_scaled_wide2 ;
Display_brush = Display_brush_wide2 ;
break;
case PIXEL_TALL2:
Pixel = Pixel_tall2 ;
Read_pixel= Read_pixel_tall2 ;
Display_screen = Display_part_of_screen_tall2 ;
Block = Block_tall2 ;
Pixel_preview_normal = Pixel_preview_normal_tall2 ;
Pixel_preview_magnifier = Pixel_preview_magnifier_tall2 ;
Horizontal_XOR_line = Horizontal_XOR_line_tall2 ;
Vertical_XOR_line = Vertical_XOR_line_tall2 ;
Display_brush_color = Display_brush_color_tall2 ;
Display_brush_mono = Display_brush_mono_tall2 ;
Clear_brush = Clear_brush_tall2 ;
Remap_screen = Remap_screen_tall2 ;
Display_line = Display_line_on_screen_tall2 ;
Display_line_fast = Display_line_on_screen_fast_tall2 ;
Read_line = Read_line_screen_tall2 ;
Display_zoomed_screen = Display_part_of_screen_scaled_tall2 ;
Display_brush_color_zoom = Display_brush_color_zoom_tall2 ;
Display_brush_mono_zoom = Display_brush_mono_zoom_tall2 ;
Clear_brush_scaled = Clear_brush_scaled_tall2 ;
Display_brush = Display_brush_tall2 ;
break;
case PIXEL_QUAD:
Pixel = Pixel_quad ;
Read_pixel= Read_pixel_quad ;
Display_screen = Display_part_of_screen_quad ;
Block = Block_quad ;
Pixel_preview_normal = Pixel_preview_normal_quad ;
Pixel_preview_magnifier = Pixel_preview_magnifier_quad ;
Horizontal_XOR_line = Horizontal_XOR_line_quad ;
Vertical_XOR_line = Vertical_XOR_line_quad ;
Display_brush_color = Display_brush_color_quad ;
Display_brush_mono = Display_brush_mono_quad ;
Clear_brush = Clear_brush_quad ;
Remap_screen = Remap_screen_quad ;
Display_line = Display_line_on_screen_quad ;
Display_line_fast = Display_line_on_screen_fast_quad ;
Read_line = Read_line_screen_quad ;
Display_zoomed_screen = Display_part_of_screen_scaled_quad ;
Display_brush_color_zoom = Display_brush_color_zoom_quad ;
Display_brush_mono_zoom = Display_brush_mono_zoom_quad ;
Clear_brush_scaled = Clear_brush_scaled_quad ;
Display_brush = Display_brush_quad ;
break;
} }
} }
Screen_width = width/Pixel_width; Screen_width = width/Pixel_width;
@ -480,6 +591,8 @@ void Resize_image(word chosen_width,word chosen_height)
// La nouvelle page a pu être allouée, elle est pour l'instant pleine de // La nouvelle page a pu être allouée, elle est pour l'instant pleine de
// 0s. Elle fait Main_image_width de large. // 0s. Elle fait Main_image_width de large.
Main_image_is_modified=1;
// On copie donc maintenant la partie C dans la nouvelle image. // On copie donc maintenant la partie C dans la nouvelle image.
Copy_part_of_image_to_another( Copy_part_of_image_to_another(
Screen_backup,0,0,Min(old_width,Main_image_width), Screen_backup,0,0,Min(old_width,Main_image_width),

26
graph.h
View File

@ -97,22 +97,16 @@ void Draw_grad_rectangle(short rax,short ray,short rbx,short rby,short vax,short
void Polyfill_general(int vertices, short * points, int color); void Polyfill_general(int vertices, short * points, int color);
void Polyfill(int vertices, short * points, int color); void Polyfill(int vertices, short * points, int color);
// Gestion des backups:
void Download_infos_page_main(T_Page * page);
void Download_infos_page_spare(T_Page * page);
void Download_infos_backup(T_List_of_pages * list);
void Free_all_backup_lists(void);
int Backup_with_new_dimensions(int upload,int width,int height);
int Backup_and_resize_the_spare(int width,int height);
void Undo(void);
void Redo(void);
void Free_current_page(void);
void Exchange_main_and_spare(void);
void Change_magnifier_factor(byte factor_index);
void Remap_picture(void); void Remap_picture(void);
// Définition d'une fonction générique de traçage de figures: ///
Func_pixel Pixel_figure; /// All the figure-drawing functions work by calling this function for each
/// pixel to draw. Before calling these functions, you should assign
/// ::Pixel_figure depending on what you where you want to draw:
/// - ::Pixel_figure_preview : On screen.
/// - ::Pixel_figure_preview_xor : On screen, XORing the color.
/// - ::Pixel_figure_permanent : On screen and in the image.
/// - ::Pixel_figure_clear_preview : On screen, reverting to the image's pixels.
extern Func_pixel Pixel_figure;
void Update_part_of_screen(short x, short y, short width, short height); void Update_part_of_screen(short x, short y, short width, short height);

View File

@ -54,7 +54,7 @@ static const T_Help_table helptable_about[] =
HELP_TITLE("======================") HELP_TITLE("======================")
*/ */
{ {
HELP_TEXT ("") // Laisse de la place pour le logo HELP_TEXT ("") // Leave enough room for a hard-coded logo, eventually.
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT ("") HELP_TEXT ("")
@ -539,7 +539,8 @@ static const T_Help_table helptable_paintbrush[] =
}; };
static const T_Help_table helptable_adjust[] = static const T_Help_table helptable_adjust[] =
{ {
HELP_TITLE("ADJUST PICTURE") HELP_TITLE("ADJUST OR TRANSFORM")
HELP_TITLE(" PICTURE")
HELP_TEXT ("") HELP_TEXT ("")
HELP_BOLD (" LEFT CLICK") HELP_BOLD (" LEFT CLICK")
HELP_LINK ("(Key:%s)",0x100+BUTTON_ADJUST) HELP_LINK ("(Key:%s)",0x100+BUTTON_ADJUST)
@ -558,8 +559,24 @@ static const T_Help_table helptable_adjust[] =
HELP_BOLD (" RIGHT CLICK") HELP_BOLD (" RIGHT CLICK")
HELP_LINK ("(Key:%s)",0x200+BUTTON_ADJUST) HELP_LINK ("(Key:%s)",0x200+BUTTON_ADJUST)
HELP_TEXT ("") HELP_TEXT ("")
HELP_TEXT (" *** Not implemented yet ***") HELP_TEXT ("Opens the Picture Transform menu.")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TITLE("PICTURE TRANSFORM")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
HELP_TEXT ("")
}; };
static const T_Help_table helptable_draw[] = static const T_Help_table helptable_draw[] =
{ {
@ -1079,7 +1096,15 @@ static const T_Help_table helptable_brush_fx[] =
HELP_TEXT ("because it's the only way for cancelling)") HELP_TEXT ("because it's the only way for cancelling)")
HELP_TEXT ("") HELP_TEXT ("")
HELP_LINK ("- Distort: (Key:%s)",SPECIAL_DISTORT) HELP_LINK ("- Distort: (Key:%s)",SPECIAL_DISTORT)
HELP_TEXT ("*** Not implemented yet ***") HELP_TEXT ("Triggers an interactive operation")
HELP_TEXT ("that allows you to distort your brush.")
HELP_TEXT ("Start by placing the brush somewhere on the")
HELP_TEXT ("screen and left-click. The brush will")
HELP_TEXT ("appear, with a little peg at each corner.")
HELP_TEXT ("Use the left mouse button to displace the")
HELP_TEXT ("corners, which will deform the brush.")
HELP_TEXT ("When you're done, click the right mouse")
HELP_TEXT ("button.")
HELP_TEXT ("") HELP_TEXT ("")
HELP_LINK ("- Outline: (Key:%s)",SPECIAL_OUTLINE) HELP_LINK ("- Outline: (Key:%s)",SPECIAL_OUTLINE)
HELP_TEXT ("This option permits to draw the") HELP_TEXT ("This option permits to draw the")

21
init.c
View File

@ -66,6 +66,8 @@
#include "mountlist.h" // read_file_system_list #include "mountlist.h" // read_file_system_list
#include "loadsave.h" // Image_emergency_backup #include "loadsave.h" // Image_emergency_backup
#include "init.h" #include "init.h"
#include "transform.h"
// Rechercher la liste et le type des lecteurs de la machine // Rechercher la liste et le type des lecteurs de la machine
@ -822,12 +824,11 @@ void Init_buttons(void)
Do_nothing, Do_nothing,
FAMILY_INSTANT); FAMILY_INSTANT);
// !!! TEMPORAIRE !!!
Init_button(BUTTON_ADJUST, Init_button(BUTTON_ADJUST,
0,18, 0,18,
16,16, 16,16,
BUTTON_SHAPE_RECTANGLE, BUTTON_SHAPE_RECTANGLE,
Button_Adjust,Message_not_implemented, Button_Adjust,Button_Transform_menu,
Do_nothing, Do_nothing,
FAMILY_TOOL); FAMILY_TOOL);
@ -1322,6 +1323,22 @@ void Init_operations(void)
Init_operation(OPERATION_ROTATE_BRUSH,2,5, Init_operation(OPERATION_ROTATE_BRUSH,2,5,
Rotate_brush_2_5,1); Rotate_brush_2_5,1);
Init_operation(OPERATION_DISTORT_BRUSH,0,0,
Distort_brush_0_0,0);
Init_operation(OPERATION_DISTORT_BRUSH,1,0,
Distort_brush_1_0,0);
Init_operation(OPERATION_DISTORT_BRUSH,1,8,
Distort_brush_1_8,0);
Init_operation(OPERATION_DISTORT_BRUSH,2,8,
Distort_brush_2_8,1);
Init_operation(OPERATION_DISTORT_BRUSH,2,0,
Distort_brush_2_0,1);
Init_operation(OPERATION_DISTORT_BRUSH,1,9,
Distort_brush_1_9,0);
Init_operation(OPERATION_DISTORT_BRUSH,0,9,
Distort_brush_0_9,0);
Init_operation(OPERATION_POLYBRUSH,1,0, Init_operation(OPERATION_POLYBRUSH,1,0,
Filled_polyform_12_0,1); Filled_polyform_12_0,1);
Init_operation(OPERATION_POLYBRUSH,2,0, Init_operation(OPERATION_POLYBRUSH,2,0,

30
input.c
View File

@ -88,12 +88,25 @@ int Is_shortcut(word Key, word function)
int Move_cursor_with_constraints() int Move_cursor_with_constraints()
{ {
int feedback=0; int feedback=0;
byte bl=0;//BL va indiquer si on doit corriger la position du curseur
// Clip mouse to the editing area. There can be a border when using big
// pixels, if the SDL screen dimensions are not factors of the pixel size.
if (Input_new_mouse_Y>=Screen_height)
{
Input_new_mouse_Y=Screen_height-1;
bl=1;
}
if (Input_new_mouse_X>=Screen_width)
{
Input_new_mouse_X=Screen_width-1;
bl=1;
}
//Gestion "avancée" du curseur: interdire la descente du curseur dans le //Gestion "avancée" du curseur: interdire la descente du curseur dans le
//menu lorsqu'on est en train de travailler dans l'image //menu lorsqu'on est en train de travailler dans l'image
if (Operation_stack_size != 0) if (Operation_stack_size != 0)
{ {
byte bl=0;//BL va indiquer si on doit corriger la position du curseur
//Si le curseur ne se trouve plus dans l'image //Si le curseur ne se trouve plus dans l'image
if(Menu_Y<=Input_new_mouse_Y) if(Menu_Y<=Input_new_mouse_Y)
@ -122,14 +135,13 @@ int Move_cursor_with_constraints()
} }
} }
} }
}
if (bl) if (bl)
{ {
SDL_WarpMouse( SDL_WarpMouse(
Input_new_mouse_X*Pixel_width, Input_new_mouse_X*Pixel_width,
Input_new_mouse_Y*Pixel_height Input_new_mouse_Y*Pixel_height
); );
}
} }
if ((Input_new_mouse_X != Mouse_X) || if ((Input_new_mouse_X != Mouse_X) ||
(Input_new_mouse_Y != Mouse_Y) || (Input_new_mouse_Y != Mouse_Y) ||

34
main.c
View File

@ -79,14 +79,18 @@ static char Gui_skin_file[MAX_PATH_CHARACTERS]= "skins" PATH_SEPARATOR "base.gif
void Display_syntax(void) void Display_syntax(void)
{ {
int mode_index; int mode_index;
printf("Syntax: GFX2 [<arguments>] [<picture>]\n\n"); printf("Syntax: grafx2 [<arguments>] [<picture>]\n\n");
printf("<arguments> can be:]\n"); printf("<arguments> can be:]\n");
printf("\t/? /h /help for this help screen\n"); printf("\t/? /h /help for this help screen\n");
printf("\t/wide to emulate a video mode with wide pixels (2x1)\n"); printf("\t/wide to emulate a video mode with wide pixels (2x1)\n");
printf("\t/tall to emulate a video mode with tall pixels (1x2)\n"); printf("\t/tall to emulate a video mode with tall pixels (1x2)\n");
printf("\t/double to emulate a video mode with double pixels (2x2)\n"); printf("\t/double to emulate a video mode with double pixels (2x2)\n");
printf("\t/skin <filename> use an alternate file with the menu graphics\n"); printf("\t/wide2 to emulate a video mode with double wide pixels (4x2)\n");
printf("\t/mode <videomode> to set a video mode\n\n"); printf("\t/tall2 to emulate a video mode with double tall pixels (2x4)\n");
printf("\t/triple to emulate a video mode with triple pixels (3x3)\n");
printf("\t/quadruple to emulate a video mode with quadruple pixels (4x4)\n");
printf("\t/skin <filename> use an alternate file with the menu graphics\n");
printf("\t/mode <videomode> to set a video mode\n\n");
printf("Available video modes:\n\n"); printf("Available video modes:\n\n");
for (mode_index=0; mode_index<Nb_video_modes; mode_index++) for (mode_index=0; mode_index<Nb_video_modes; mode_index++)
printf("\t%s\n",Mode_label(mode_index)); printf("\t%s\n",Mode_label(mode_index));
@ -217,6 +221,22 @@ void Analyze_command_line(int argc,char * argv[])
{ {
Pixel_ratio = PIXEL_DOUBLE; Pixel_ratio = PIXEL_DOUBLE;
} }
else if ( !strcmp(argv[index],"/triple") )
{
Pixel_ratio = PIXEL_DOUBLE;
}
else if ( !strcmp(argv[index],"/quadruple") )
{
Pixel_ratio = PIXEL_QUAD;
}
else if ( !strcmp(argv[index],"/tall2") )
{
Pixel_ratio = PIXEL_TALL2;
}
else if ( !strcmp(argv[index],"/wide2") )
{
Pixel_ratio = PIXEL_WIDE2;
}
else if ( !strcmp(argv[index],"/rgb") ) else if ( !strcmp(argv[index],"/rgb") )
{ {
// echelle des composants RGB // echelle des composants RGB

143
misc.c
View File

@ -282,32 +282,31 @@ byte Read_pixel_from_spare_screen(word x,word y)
return *(Spare_screen+y*Spare_image_width+x); return *(Spare_screen+y*Spare_image_width+x);
} }
void Rotate_90_deg_lowlevel(byte * source,byte * dest) void Rotate_90_deg_lowlevel(byte * source, byte * dest, short width, short height)
{ {
byte* esi; word x,y;
byte* edi;
word dx,bx,cx;
//ESI = Point haut droit de la source for(y=0;y<height;y++)
byte* Debut_de_colonne = source + Brush_width - 1;
edi = dest;
// Largeur de la source = hauteur de la destination
dx = bx = Brush_width;
// Pour chaque ligne
for(dx = Brush_width;dx>0;dx--)
{ {
esi = Debut_de_colonne; for(x=0;x<width;x++)
// Pout chaque colonne
for(cx=Brush_height;cx>0;cx--)
{ {
*edi = *esi; *(dest+height*(width-1-x)+y)=*source;
esi+=Brush_width; source++;
edi++;
} }
}
}
Debut_de_colonne--; void Rotate_270_deg_lowlevel(byte * source, byte * dest, short width, short height)
{
word x,y;
for(y=0;y<height;y++)
{
for(x=0;x<width;x++)
{
*(dest+(height-1-y)+x*height)=*source;
source++;
}
} }
} }
@ -486,13 +485,12 @@ void Check_timer(void)
if((SDL_GetTicks()/55)-Timer_delay>Timer_start) Timer_state=1; if((SDL_GetTicks()/55)-Timer_delay>Timer_start) Timer_state=1;
} }
// Effectue une inversion de la brosse selon une droite horizontale void Flip_Y_lowlevel(byte *src, short width, short height)
void Flip_Y_lowlevel(void)
{ {
// ESI pointe sur la partie haute de la brosse // ESI pointe sur la partie haute de la brosse
// EDI sur la partie basse // EDI sur la partie basse
byte* ESI = Brush ; byte* ESI = src ;
byte* EDI = Brush + (Brush_height - 1) *Brush_width; byte* EDI = src + (height - 1) *width;
byte tmp; byte tmp;
word cx; word cx;
@ -501,7 +499,7 @@ void Flip_Y_lowlevel(void)
// Il faut inverser les lignes pointées par ESI et // Il faut inverser les lignes pointées par ESI et
// EDI ("Brush_width" octets en tout) // EDI ("Brush_width" octets en tout)
for(cx = Brush_width;cx>0;cx--) for(cx = width;cx>0;cx--)
{ {
tmp = *ESI; tmp = *ESI;
*ESI = *EDI; *ESI = *EDI;
@ -514,57 +512,65 @@ void Flip_Y_lowlevel(void)
// ESI pointe déjà sur le début de la ligne suivante // ESI pointe déjà sur le début de la ligne suivante
// EDI pointe sur la fin de la ligne en cours, il // EDI pointe sur la fin de la ligne en cours, il
// doit pointer sur le début de la précédente... // doit pointer sur le début de la précédente...
EDI -= 2 * Brush_width; // On recule de 2 lignes EDI -= 2 * width; // On recule de 2 lignes
} }
} }
// Effectue une inversion de la brosse selon une droite verticale void Flip_X_lowlevel(byte *src, short width, short height)
void Flip_X_lowlevel(void)
{ {
// ESI pointe sur la partie gauche et EDI sur la partie // ESI pointe sur la partie gauche et EDI sur la partie
// droite // droite
byte* ESI = Brush; byte* ESI = src;
byte* EDI = Brush + Brush_width - 1; byte* EDI = src + width - 1;
byte* Debut_Ligne; byte* line_start;
byte* Fin_Ligne; byte* line_end;
byte tmp; byte tmp;
word cx; word cx;
while(ESI<EDI) while(ESI<EDI)
{ {
Debut_Ligne = ESI; line_start = ESI;
Fin_Ligne = EDI; line_end = EDI;
// On échange par colonnes // On échange par colonnes
for(cx=Brush_height;cx>0;cx--) for(cx=height;cx>0;cx--)
{ {
tmp=*ESI; tmp=*ESI;
*ESI=*EDI; *ESI=*EDI;
*EDI=tmp; *EDI=tmp;
EDI+=Brush_width; EDI+=width;
ESI+=Brush_width; ESI+=width;
} }
// On change de colonne // On change de colonne
// ESI > colonne suivante // ESI > colonne suivante
// EDI > colonne précédente // EDI > colonne précédente
ESI = Debut_Ligne + 1; ESI = line_start + 1;
EDI = Fin_Ligne - 1; EDI = line_end - 1;
} }
} }
// Faire une rotation de 180º de la brosse // Rotate a pixel buffer 180º on itself.
void Rotate_180_deg_lowlevel(void) void Rotate_180_deg_lowlevel(byte *src, short width, short height)
{ {
// ESI pointe sur la partie supérieure de la brosse // ESI pointe sur la partie supérieure de la brosse
// EDI pointe sur la partie basse // EDI pointe sur la partie basse
byte* ESI = Brush; byte* ESI = src;
byte* EDI = Brush + Brush_height*Brush_width - 1; byte* EDI = src + height*width - 1;
// EDI pointe sur le dernier pixel de la derniere ligne // EDI pointe sur le dernier pixel de la derniere ligne
byte tmp; byte tmp;
word cx; word cx;
// In case of odd height, the algorithm in this function would
// miss the middle line, so we do it this way:
if (height & 1)
{
Flip_X_lowlevel(src, width, height);
Flip_Y_lowlevel(src, width, height);
return;
}
while(ESI < EDI) while(ESI < EDI)
{ {
// On échange les deux lignes pointées par EDI et // On échange les deux lignes pointées par EDI et
@ -572,7 +578,7 @@ void Rotate_180_deg_lowlevel(void)
// En même temps, on échange les pixels, donc EDI // En même temps, on échange les pixels, donc EDI
// pointe sur la FIN de sa ligne // pointe sur la FIN de sa ligne
for(cx=Brush_width;cx>0;cx--) for(cx=width;cx>0;cx--)
{ {
tmp = *ESI; tmp = *ESI;
*ESI = *EDI; *ESI = *EDI;
@ -584,6 +590,55 @@ void Rotate_180_deg_lowlevel(void)
} }
} }
void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buffer, short dst_width, short dst_height, short x_flipped, short y_flipped)
{
int offset,line,column;
int x_pos_in_brush; // Position courante dans l'ancienne brosse
int y_pos_in_brush;
int delta_x_in_brush; // "Vecteur incrémental" du point précédent
int delta_y_in_brush;
int initial_x_pos; // Position X de début de parcours de ligne
// Calcul du "vecteur incrémental":
delta_x_in_brush=(src_width<<16) * (x_flipped?-1:1) / (dst_width);
delta_y_in_brush=(src_height<<16) * (y_flipped?-1:1) / (dst_height);
offset=0;
// Calcul de la valeur initiale de y_pos:
if (y_flipped)
y_pos_in_brush=(src_height<<16)-1; // Inversion en Y de la brosse
else
y_pos_in_brush=0; // Pas d'inversion en Y de la brosse
// Calcul de la valeur initiale de x_pos pour chaque ligne:
if (x_flipped)
initial_x_pos = (src_width<<16)-1; // Inversion en X de la brosse
else
initial_x_pos = 0; // Pas d'inversion en X de la brosse
// Pour chaque ligne
for (line=0;line<dst_height;line++)
{
// On repart du début de la ligne:
x_pos_in_brush=initial_x_pos;
// Pour chaque colonne:
for (column=0;column<dst_width;column++)
{
// On copie le pixel:
dst_buffer[offset]=*(src_buffer + (x_pos_in_brush>>16) + (y_pos_in_brush>>16)*src_width);
// On passe à la colonne de brosse suivante:
x_pos_in_brush+=delta_x_in_brush;
// On passe au pixel suivant de la nouvelle brosse:
offset++;
}
// On passe à la ligne de brosse suivante:
y_pos_in_brush+=delta_y_in_brush;
}
}
void Slider_timer(byte speed) void Slider_timer(byte speed)
//Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte //Boucle d'attente pour faire bouger les scrollbars à une vitesse correcte
{ {

50
misc.h
View File

@ -84,10 +84,52 @@ byte Effect_additive_colorize (word x,word y,byte color);
byte Effect_substractive_colorize(word x,word y,byte color); byte Effect_substractive_colorize(word x,word y,byte color);
byte Effect_sieve(word x,word y); byte Effect_sieve(word x,word y);
void Flip_Y_lowlevel(void); ///
void Flip_X_lowlevel(void); /// Inverts a pixel buffer, according to a horizontal axis.
void Rotate_90_deg_lowlevel(byte * source,byte * dest); /// @param src Pointer to the pixel buffer to process.
void Rotate_180_deg_lowlevel(void); /// @param width Width of the buffer.
/// @param height Height of the buffer.
void Flip_Y_lowlevel(byte *src, short width, short height);
///
/// Inverts a pixel buffer, according to a vertical axis.
/// @param src Pointer to the pixel buffer to process.
/// @param width Width of the buffer.
/// @param height Height of the buffer.
void Flip_X_lowlevel(byte *src, short width, short height);
///
/// Rotate a pixel buffer by 90 degrees, clockwise.
/// @param source Source pixel buffer.
/// @param dest Destination pixel buffer.
/// @param width Width of the original buffer (height of the destination one).
/// @param height Height of the original buffer (width of the destination one).
void Rotate_90_deg_lowlevel(byte * source, byte * dest, short width, short height);
///
/// Rotate a pixel buffer by 90 degrees, counter-clockwise.
/// @param source Source pixel buffer.
/// @param dest Destination pixel buffer.
/// @param width Width of the original buffer (height of the destination one).
/// @param height Height of the original buffer (width of the destination one).
void Rotate_270_deg_lowlevel(byte * source, byte * dest, short width, short height);
///
/// Rotate a pixel buffer by 180 degrees.
/// @param src The pixel buffer (source and destination).
/// @param width Width of the buffer.
/// @param height Height of the buffer.
void Rotate_180_deg_lowlevel(byte *src, short width, short height);
///
/// Copies an image to another, rescaling it and optionally flipping it.
/// @param src_buffer Original image (address of first byte)
/// @param src_width Original image's width in pixels
/// @param src_height Original image's height in pixels
/// @param dst_buffer Destination image (address of first byte)
/// @param dst_width Destination image's width in pixels
/// @param dst_height Destination image's height in pixels
/// @param x_flipped Boolean, true to flip the image horizontally
/// @param y_flipped Boolean, true to flip the image vertically
void Rescale(byte *src_buffer, short src_width, short src_height, byte *dst_buffer, short dst_width, short dst_height, short x_flipped, short y_flipped);
void Zoom_a_line(byte * original_line,byte * zoomed_line,word factor,word width); void Zoom_a_line(byte * original_line,byte * zoomed_line,word factor,word width);
void Copy_part_of_image_to_another(byte * source,word source_x,word source_y,word width,word height,word source_width,byte * dest,word dest_x,word dest_y,word destination_width); void Copy_part_of_image_to_another(byte * source,word source_x,word source_y,word width,word height,word source_width,byte * dest,word dest_x,word dest_y,word destination_width);

View File

@ -157,6 +157,35 @@ void Display_coords_rel_or_abs(short start_x, short start_y)
Print_coordinates(); Print_coordinates();
} }
/// Simulates clicking the "Draw" button.
void Return_to_draw_mode(void)
{
// Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au
// préalable:
Display_cursor();
if (Mouse_K)
Wait_end_of_click();
// !!! Efface la croix puis affiche le viseur !!!
Unselect_button(BUTTON_DRAW,LEFT_SIDE); // Désenclenche au passage le bouton brosse
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu à la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Unselect_button(BUTTON_DRAW,RIGHT_SIDE);
}
// Maintenant, il faut réeffacer le curseur parce qu'il sera raffiché en fin
// d'appel à cette action:
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("X: Y:",0);
Print_coordinates();
}
//////////////////////////////////////////////////// OPERATION_CONTINUOUS_DRAW //////////////////////////////////////////////////// OPERATION_CONTINUOUS_DRAW
void Freehand_mode1_1_0(void) void Freehand_mode1_1_0(void)
@ -2955,29 +2984,7 @@ void Brush_0_5(void)
Brush_offset_Y=(Brush_offset_Y/Snap_height)*Snap_height; Brush_offset_Y=(Brush_offset_Y/Snap_height)*Snap_height;
} }
// Simuler l'appui du bouton "Dessin" Return_to_draw_mode();
// Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au
// préalable:
Display_cursor();
// !!! Efface la croix puis affiche le viseur !!!
Unselect_button(BUTTON_DRAW,LEFT_SIDE); // Désenclenche au passage le bouton brosse
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu à la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Unselect_button(BUTTON_DRAW,RIGHT_SIDE);
}
// Maintenant, il faut réeffacer le curseur parce qu'il sera raffiché en fin
// d'appel à cette action:
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("X: Y:",0);
Print_coordinates();
} }
@ -3099,28 +3106,8 @@ void Polybrush_12_8(void)
Brush_offset_X=(Brush_offset_X/Snap_width)*Snap_width; Brush_offset_X=(Brush_offset_X/Snap_width)*Snap_width;
Brush_offset_Y=(Brush_offset_Y/Snap_height)*Snap_height; Brush_offset_Y=(Brush_offset_Y/Snap_height)*Snap_height;
} }
// Simuler l'appui du bouton "Dessin" Return_to_draw_mode();
// Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au
// préalable:
Display_cursor();
Wait_end_of_click();
// !!! Efface la croix puis affiche le viseur !!!
Unselect_button(BUTTON_DRAW,LEFT_SIDE); // Désenclenche au passage le bouton brosse
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu à la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Unselect_button(BUTTON_DRAW,RIGHT_SIDE);
}
// Maintenant, il faut réeffacer le curseur parce qu'il sera raffiché en fin
// d'appel à cette action:
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
Display_cursor(); Display_cursor();
} }
} }
@ -3398,31 +3385,7 @@ void Stretch_brush_2_7(void)
// Et enfin on stocke pour de bon la nouvelle brosse étirée // Et enfin on stocke pour de bon la nouvelle brosse étirée
Stretch_brush(start_x,start_y,computed_x,computed_y); Stretch_brush(start_x,start_y,computed_x,computed_y);
// Simuler l'appui du bouton "Dessin" Return_to_draw_mode();
// Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au
// préalable:
Display_cursor();
// !!! Efface la croix puis affiche le viseur !!!
Unselect_button(BUTTON_DRAW,LEFT_SIDE); // Désenclenche au passage le bouton brosse
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu à la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Unselect_button(BUTTON_DRAW,RIGHT_SIDE);
}
// Maintenant, il faut réeffacer le curseur parce qu'il sera raffiché en fin
// d'appel à cette action:
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("X: Y:",0);
Print_coordinates();
// Inutile de de faire un Wait_end_of_click car c'est fait dans Unselect_button
} }
@ -3650,33 +3613,261 @@ void Rotate_brush_2_5(void)
// Et enfin on stocke pour de bon la nouvelle brosse étirée // Et enfin on stocke pour de bon la nouvelle brosse étirée
Rotate_brush(angle); Rotate_brush(angle);
// Simuler l'appui du bouton "Dessin" Return_to_draw_mode();
// Comme l'enclenchement du bouton efface le curseur, il faut l'afficher au
// préalable:
Display_cursor();
// !!! Efface le curseur de l'opération puis affiche le viseur !!!
Unselect_button(BUTTON_DRAW,LEFT_SIDE); // Désenclenche au passage le bouton brosse
if (Config.Auto_discontinuous)
{
// On se place en mode Dessin discontinu à la main
while (Current_operation!=OPERATION_DISCONTINUOUS_DRAW)
Unselect_button(BUTTON_DRAW,RIGHT_SIDE);
}
// Maintenant, il faut réeffacer le curseur parce qu'il sera raffiché en fin
// d'appel à cette action:
Hide_cursor();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
if ((Config.Coords_rel) && (Menu_is_visible))
Print_in_menu("X: Y:",0);
Print_coordinates();
// Inutile de de faire un Wait_end_of_click car c'est fait dans Unselect_button
} }
///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH
/// Draws a 2x2 XOR square at the specified picture coordinates, on the screen.
void Draw_stretch_spot(short x_pos, short y_pos)
{
short x,y;
for (y=y_pos-1;y<y_pos+1;y++)
if (y>=Limit_top && y<=Limit_visible_bottom)
for (x=x_pos-1;x<x_pos+1;x++)
if (x>=Limit_left && x<=Limit_visible_right)
Pixel_preview(x,y,~Read_pixel(x-Main_offset_X,y-Main_offset_Y));
Update_part_of_screen(x_pos-1, y_pos-1, 2, 2);
}
void Distort_brush_0_0(void)
//
// Opération : OPERATION_DISTORT_BRUSH
// Click Souris: 0
// Taille_Pile : 0
//
// Souris effacée: Non
//
{
if ( Menu_is_visible )
{
Print_in_menu("POSITION BRUSH TO START ",0);
}
}
void Distort_brush_1_0(void)
//
// Opération : OPERATION_DISTORT_BRUSH
// Click Souris: 1
// Taille_Pile : 0
//
// Souris effacée: Non
//
{
short x_pos, y_pos;
Init_start_operation();
Paintbrush_hidden=1;
Hide_cursor();
// Top left angle
x_pos=Paintbrush_X-Brush_offset_X;
y_pos=Paintbrush_Y-Brush_offset_Y;
Draw_stretch_spot(x_pos,y_pos);
Operation_push(x_pos);
Operation_push(y_pos);
// Top right angle
x_pos+=Brush_width;
Draw_stretch_spot(x_pos,y_pos);
Operation_push(x_pos);
Operation_push(y_pos);
// Bottom right angle
y_pos+=Brush_height;
Draw_stretch_spot(x_pos,y_pos);
Operation_push(x_pos);
Operation_push(y_pos);
// Bottom left angle
x_pos-=Brush_width;
Draw_stretch_spot(x_pos,y_pos);
Operation_push(x_pos);
Operation_push(y_pos);
Distort_brush_preview(
Operation_stack[1],
Operation_stack[2],
Operation_stack[3],
Operation_stack[4],
Operation_stack[5],
Operation_stack[6],
Operation_stack[7],
Operation_stack[8]);
Display_cursor();
Update_part_of_screen(Paintbrush_X-Brush_offset_X, Paintbrush_Y-Brush_offset_Y, Brush_width, Brush_height);
Wait_end_of_click();
// Erase the message in status bar
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
Print_in_menu("X: Y: ",0);
}
}
void Distort_brush_1_8(void)
//
// Opération : OPERATION_DISTORT_BRUSH
// Click Souris: 1
// Taille_Pile : 8
//
// Souris effacée: No
//
{
// How far (in pixels) you can catch a handle
#define REACH_DISTANCE 100
short i;
short x[4];
short y[4];
long best_distance=REACH_DISTANCE;
short best_spot=-1;
for (i=3;i>=0;i--)
{
long distance;
Operation_pop(&y[i]);
Operation_pop(&x[i]);
distance=Distance(Paintbrush_X,Paintbrush_Y,x[i],y[i]);
if (distance<best_distance)
{
best_spot=i;
best_distance=distance;
}
}
for (i=0;i<4;i++)
{
Operation_push(x[i]);
Operation_push(y[i]);
}
if (best_spot>-1)
{
Operation_push(best_spot);
}
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
Print_in_menu("X: Y: ",0);
Print_coordinates();
}
}
void Distort_brush_1_9(void)
//
// Opération : OPERATION_DISTORT_BRUSH
// Click Souris: 1
// Taille_Pile : 9
//
// Souris effacée: No
//
{
short i;
short x[4];
short y[4];
short selected_corner;
// Pop all arguments
Operation_pop(&selected_corner);
for (i=3;i>=0;i--)
{
Operation_pop(&y[i]);
Operation_pop(&x[i]);
}
if (Paintbrush_X!=x[selected_corner] || Paintbrush_Y!=y[selected_corner])
{
Hide_cursor();
// Easiest refresh mode: make no assumptions on how the brush was
// displayed before.
Display_all_screen();
x[selected_corner]=Paintbrush_X;
y[selected_corner]=Paintbrush_Y;
for (i=0;i<4;i++)
Draw_stretch_spot(x[i],y[i]);
Distort_brush_preview(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]);
Display_cursor();
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
Print_in_menu("X: Y: ",0);
Print_coordinates();
}
Update_rect(0,0,Screen_width,Menu_Y);
}
// Push back all arguments
for (i=0;i<4;i++)
{
Operation_push(x[i]);
Operation_push(y[i]);
}
Operation_push(selected_corner);
}
void Distort_brush_0_9(void)
//
// Opération : OPERATION_DISTORT_BRUSH
// Click Souris: 0
// Taille_Pile : 9
//
// Souris effacée: No
//
{
short selected_corner;
Operation_pop(&selected_corner);
}
void Distort_brush_2_0(void)
//
// Opération : OPERATION_DISTORT_BRUSH
// Click Souris: 2
// Taille_Pile : 0
//
// Souris effacée: Oui
//
{
Paintbrush_hidden=0;
Display_all_screen();
// Erase the message in status bar
if ( (Config.Coords_rel) && (Menu_is_visible) )
{
Print_in_menu("X: Y: ",0);
}
Return_to_draw_mode();
}
void Distort_brush_2_8(void)
//
// Opération : OPERATION_DISTORT_BRUSH
// Click Souris: 2
// Taille_Pile : 8
//
// Souris effacée: Oui
//
{
short i;
short x[4];
short y[4];
// Pop all arguments
for (i=3;i>=0;i--)
{
Operation_pop(&y[i]);
Operation_pop(&x[i]);
}
Distort_brush(x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]);
Paintbrush_hidden=0;
Display_all_screen();
Return_to_draw_mode();
}
//////////////////////////////////////////////////////////// OPERATION_SCROLL //////////////////////////////////////////////////////////// OPERATION_SCROLL

View File

@ -100,6 +100,16 @@ void Rotate_brush_1_5(void);
void Rotate_brush_0_5(void); void Rotate_brush_0_5(void);
void Rotate_brush_2_5(void); void Rotate_brush_2_5(void);
///////////////////////////////////////////////////// OPERATION_DISTORT_BRUSH
void Distort_brush_0_0(void);
void Distort_brush_1_0(void);
void Distort_brush_2_0(void);
void Distort_brush_1_8(void);
void Distort_brush_2_8(void);
void Distort_brush_1_9(void);
void Distort_brush_0_9(void);
//////////////////////////////////////////////////////// OPERATION_POLYBRUSH //////////////////////////////////////////////////////// OPERATION_POLYBRUSH
void Polybrush_12_8(void); void Polybrush_12_8(void);

View File

@ -36,26 +36,26 @@
void Pixel_double (word x,word y,byte color) void Pixel_double (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */ /* Affiche un pixel de la color aux coords x;y à l'écran */
{ {
*(Screen_pixels + x * 2 + y * 4 * Screen_width)=color; *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * 2 + y * 4 * Screen_width + 1)=color; *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * 2 + (y * 4 + 2 )* Screen_width)=color; *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1)* VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * 2 + (y * 4 + 2 )* Screen_width + 1)=color; *(Screen_pixels + x * ZOOMX + (y*ZOOMY+1)* VIDEO_LINE_WIDTH + 1)=color;
} }
byte Read_pixel_double (word x,word y) byte Read_pixel_double (word x,word y)
/* On retourne la couleur du pixel aux coords données */ /* On retourne la couleur du pixel aux coords données */
{ {
return *( Screen_pixels + y * 4 * Screen_width + x * 2); return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
} }
void Block_double (word start_x,word start_y,word width,word height,byte color) void Block_double (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */ /* On affiche un rectangle de la couleur donnée */
{ {
SDL_Rect rectangle; SDL_Rect rectangle;
rectangle.x=start_x*2; rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*2; rectangle.y=start_y*ZOOMY;
rectangle.w=width*2; rectangle.w=width*ZOOMX;
rectangle.h=height*2; rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color); SDL_FillRect(Screen_SDL,&rectangle,color);
} }
@ -75,14 +75,14 @@ void Display_part_of_screen_double (word width,word height,word image_width)
{ {
*(dest+1)=*dest=*src; *(dest+1)=*dest=*src;
src++; src++;
dest+=2; dest+=ZOOMX;
} }
// On double la ligne qu'on vient de copier // On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+Screen_width*ZOOMX,dest-width*ZOOMX,width*ZOOMX); memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante // On passe à la ligne suivante
src+=image_width-width; src+=image_width-width;
dest+=Screen_width*4 - width*2; dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
} }
//Update_rect(0,0,width,height); //Update_rect(0,0,width,height);
} }
@ -127,29 +127,29 @@ void Pixel_preview_magnifier_double (word x,word y,byte color)
void Horizontal_XOR_line_double(word x_pos,word y_pos,word width) void Horizontal_XOR_line_double(word x_pos,word y_pos,word width)
{ {
//On calcule la valeur initiale de dest: //On calcule la valeur initiale de dest:
byte* dest=y_pos*4*Screen_width+x_pos*2+Screen_pixels; byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x; int x;
for (x=0;x<width*2;x+=2) for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+2*Screen_width+1)=*(dest+x+2*Screen_width)=*(dest+x+1)=*(dest+x)=~*(dest+x); *(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+1)=*(dest+x)=~*(dest+x);
} }
void Vertical_XOR_line_double(word x_pos,word y_pos,word height) void Vertical_XOR_line_double(word x_pos,word y_pos,word height)
{ {
int i; int i;
byte *dest=Screen_pixels+x_pos*2+y_pos*Screen_width*4; byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--) for (i=height;i>0;i--)
{ {
*dest=*(dest+1)=*(dest+Screen_width*2)=*(dest+Screen_width*2+1)=~*dest; *dest=*(dest+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=~*dest;
dest+=Screen_width*4; dest+=VIDEO_LINE_WIDTH*ZOOMY;
} }
} }
void Display_brush_color_double(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) void Display_brush_color_double(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{ {
// dest = Position à l'écran // dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * 4 * Screen_width + x_pos * 2; byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse // src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset; byte* src = Brush + y_offset * brush_width + x_offset;
@ -164,16 +164,16 @@ void Display_brush_color_double(word x_pos,word y_pos,word x_offset,word y_offse
// On vérifie que ce n'est pas la transparence // On vérifie que ce n'est pas la transparence
if(*src != transp_color) if(*src != transp_color)
{ {
*(dest+Screen_width*2+1) = *(dest+Screen_width*2) = *(dest+1) = *dest = *src; *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+1) = *dest = *src;
} }
// Pixel suivant // Pixel suivant
src++; src++;
dest+=2; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
dest = dest + Screen_width*4 - width*2; dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width; src = src + brush_width - width;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
@ -184,7 +184,7 @@ void Display_brush_mono_double(word x_pos, word y_pos,
byte transp_color, byte color, word brush_width) byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */ /* On affiche la brosse en monochrome */
{ {
byte* dest=y_pos*4*Screen_width+x_pos*2+Screen_pixels; // dest = adr destination à byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran // l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse // la brosse
@ -197,23 +197,23 @@ void Display_brush_mono_double(word x_pos, word y_pos,
//Pour chaque pixel //Pour chaque pixel
{ {
if (*src!=transp_color) if (*src!=transp_color)
*(dest+Screen_width*2+1)=*(dest+Screen_width*2)=*(dest+1)=*dest=color; *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=color;
// On passe au pixel suivant // On passe au pixel suivant
src++; src++;
dest+=2; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
src+=brush_width-width; src+=brush_width-width;
dest+=Screen_width*4-width*2; dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
} }
void Clear_brush_double(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) void Clear_brush_double(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{ {
byte* dest=Screen_pixels+x_pos*2+y_pos*4*Screen_width; //On va se mettre en 0,0 dans l'écran (dest) byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y; int y;
int x; int x;
@ -224,16 +224,16 @@ void Clear_brush_double(word x_pos,word y_pos,__attribute__((unused)) word x_off
for(x=width;x!=0;x--) for(x=width;x!=0;x--)
//Pour chaque pixel //Pour chaque pixel
{ {
*(dest+Screen_width*2+1)=*(dest+Screen_width*2)=*(dest+1)=*dest=*src; *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*src;
// On passe au pixel suivant // On passe au pixel suivant
src++; src++;
dest+=2; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
src+=image_width-width; src+=image_width-width;
dest+=Screen_width*4-width*2; dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
} }
@ -242,7 +242,7 @@ void Clear_brush_double(word x_pos,word y_pos,__attribute__((unused)) word x_off
void Display_brush_double(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) void Display_brush_double(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{ {
// dest = Position à l'écran // dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * 4 * Screen_width + x_pos * 2; byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse // src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset; byte* src = brush + y_offset * brush_width + x_offset;
@ -257,15 +257,15 @@ void Display_brush_double(byte * brush, word x_pos,word y_pos,word x_offset,word
// On vérifie que ce n'est pas la transparence // On vérifie que ce n'est pas la transparence
if(*src != transp_color) if(*src != transp_color)
{ {
*(dest+Screen_width*2+1)=*(dest+Screen_width*2)=*(dest+1)=*dest=*src; *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*src;
} }
// Pixel suivant // Pixel suivant
src++; dest+=2; src++; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
dest = dest + Screen_width*4 - width*2; dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width; src = src + brush_width - width;
} }
} }
@ -273,7 +273,7 @@ void Display_brush_double(byte * brush, word x_pos,word y_pos,word x_offset,word
void Remap_screen_double(word x_pos,word y_pos,word width,word height,byte * conversion_table) void Remap_screen_double(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{ {
// dest = coords a l'écran // dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * 4 * Screen_width + x_pos * 2; byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y; int x,y;
// Pour chaque ligne // Pour chaque ligne
@ -282,12 +282,12 @@ void Remap_screen_double(word x_pos,word y_pos,word width,word height,byte * con
// Pour chaque pixel // Pour chaque pixel
for(x=width;x>0;x--) for(x=width;x>0;x--)
{ {
*(dest+Screen_width*2+1)=*(dest+Screen_width*2)=*(dest+1)=*dest= *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=
conversion_table[*dest]; conversion_table[*dest];
dest +=2; dest +=ZOOMX;
} }
dest = dest + Screen_width*4 - width*2; dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
@ -297,8 +297,8 @@ void Display_line_on_screen_fast_double(word x_pos,word y_pos,word width,byte *
/* On affiche toute une ligne de pixels telle quelle. */ /* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */ /* Utilisée si le buffer contient déja des pixel doublés. */
{ {
memcpy(Screen_pixels+x_pos*2+y_pos*4*Screen_width,line,width*2); memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*2+(y_pos*4+2)*Screen_width,line,width*2); memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
} }
void Display_line_on_screen_double(word x_pos,word y_pos,word width,byte * line) void Display_line_on_screen_double(word x_pos,word y_pos,word width,byte * line)
@ -306,11 +306,11 @@ void Display_line_on_screen_double(word x_pos,word y_pos,word width,byte * line)
{ {
int x; int x;
byte *dest; byte *dest;
dest=Screen_pixels+x_pos*2+y_pos*4*Screen_width; dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--) for(x=width;x>0;x--)
{ {
*(dest+Screen_width*2+1)=*(dest+Screen_width*2)=*(dest+1)=*dest=*line; *(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*line;
dest+=2; dest+=ZOOMX;
line++; line++;
} }
} }
@ -320,7 +320,7 @@ void Display_transparent_mono_line_on_screen_double(
// Affiche une ligne à l'écran avec une couleur + transparence. // Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom // Utilisé par les brosses en mode zoom
{ {
byte* dest = Screen_pixels+ y_pos*ZOOMX*Screen_width + x_pos*ZOOMX; byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x; int x;
// Pour chaque pixel // Pour chaque pixel
for(x=0;x<width;x++) for(x=0;x<width;x++)
@ -330,13 +330,13 @@ void Display_transparent_mono_line_on_screen_double(
*(dest+1)=*dest=color; *(dest+1)=*dest=color;
} }
line ++; // Pixel suivant line ++; // Pixel suivant
dest+=2; dest+=ZOOMX;
} }
} }
void Read_line_screen_double(word x_pos,word y_pos,word width,byte * line) void Read_line_screen_double(word x_pos,word y_pos,word width,byte * line)
{ {
memcpy(line,Screen_width * 4 * y_pos + x_pos * 2 + Screen_pixels,width*2); memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
} }
void Display_part_of_screen_scaled_double( void Display_part_of_screen_scaled_double(
@ -356,7 +356,7 @@ void Display_part_of_screen_scaled_double(
// On éclate la ligne // On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width); Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives // On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/; x = Main_magnifier_factor;
// Pour chaque ligne // Pour chaque ligne
do{ do{
// On affiche la ligne zoomée // On affiche la ligne zoomée
@ -366,7 +366,7 @@ void Display_part_of_screen_scaled_double(
); );
// On passe à la suivante // On passe à la suivante
y++; y++;
if(y==height/**ZOOMY*/) if(y==height)
{ {
Update_rect(Main_X_zoom,0, Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height); width*Main_magnifier_factor,height);
@ -398,9 +398,8 @@ void Display_brush_color_zoom_double(word x_pos,word y_pos,
// On affiche facteur fois la ligne zoomée // On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--) for(bx=Main_magnifier_factor;bx>0;bx--)
{ {
Display_transparent_line_on_screen_wide(x_pos,y*ZOOMX,width*Main_magnifier_factor,buffer,transp_color); Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color);
// TODO: pas clair ici memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
memcpy(Screen_pixels + (y*ZOOMY+1)*ZOOMX*Screen_width + x_pos*ZOOMX, Screen_pixels + y*ZOOMX*ZOOMY*Screen_width + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++; y++;
if(y==end_y_pos) if(y==end_y_pos)
{ {
@ -435,7 +434,7 @@ void Display_brush_mono_zoom_double(word x_pos, word y_pos,
// On affiche la ligne Facteur fois à l'écran (sur des // On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives) // lignes consécutives)
bx = Main_magnifier_factor*ZOOMX; bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran // Pour chaque ligne écran
do do
@ -448,7 +447,7 @@ void Display_brush_mono_zoom_double(word x_pos, word y_pos,
// On passe à la ligne suivante // On passe à la ligne suivante
y++; y++;
// On vérifie qu'on est pas à la ligne finale // On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMX) if(y == end_y_pos*ZOOMY)
{ {
Update_rect( x_pos, y_pos, Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos ); width * Main_magnifier_factor, end_y_pos - y_pos );
@ -473,13 +472,12 @@ void Clear_brush_scaled_double(word x_pos,word y_pos,word x_offset,word y_offset
// Pour chaque ligne à zoomer // Pour chaque ligne à zoomer
while(1){ while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*2,width); Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor; bx=Main_magnifier_factor;
// Pour chaque ligne // Pour chaque ligne
do{ do{
// TODO a verifier
Display_line_on_screen_fast_double(x_pos,y, Display_line_on_screen_fast_double(x_pos,y,
width * Main_magnifier_factor,buffer); width * Main_magnifier_factor,buffer);

534
pxquad.c Normal file
View File

@ -0,0 +1,534 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "pxquad.h"
#define ZOOMX 4
#define ZOOMY 4
void Pixel_quad (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 3)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 3)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 3)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 3)=color;
}
byte Read_pixel_quad (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_quad (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_quad (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la triple
memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la quadruple
memcpy(dest-width*ZOOMX+3*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_quad (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_quad(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_quad (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_quad(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Zoom_factor_table[y-Main_magnifier_offset_Y];
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_quad(
Zoom_factor_table[x-Main_magnifier_offset_X]+Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_quad(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+3*VIDEO_LINE_WIDTH+3)=*(dest+x+3*VIDEO_LINE_WIDTH+2)=*(dest+x+3*VIDEO_LINE_WIDTH+1)=*(dest+x+3*VIDEO_LINE_WIDTH)=*(dest+x+2*VIDEO_LINE_WIDTH+3)=*(dest+x+2*VIDEO_LINE_WIDTH+2)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+3)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+3)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_quad(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest);
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_quad(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+3*VIDEO_LINE_WIDTH+3) = *(dest+3*VIDEO_LINE_WIDTH+2) = *(dest+3*VIDEO_LINE_WIDTH+1) = *(dest+3*VIDEO_LINE_WIDTH) = *(dest+2*VIDEO_LINE_WIDTH+3) = *(dest+2*VIDEO_LINE_WIDTH+2) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+3) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+3) = *(dest+2) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_quad(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_quad(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_quad(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_quad(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_quad(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+3)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_quad(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_quad(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_quad(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_quad(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_quad(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
{
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_quad(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
byte* line_src = buffer;
byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width*Main_magnifier_factor;x > 0;x--)
{
if(*line_src!=transp_color)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest = *line_src;
}
line_src++;
dest+=ZOOMX;
}
// Double the line
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Triple the line
memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Quadruple it
memcpy(Screen_pixels + (y*ZOOMY+3)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_quad(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_quad(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_quad(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_quad(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

50
pxquad.h Normal file
View File

@ -0,0 +1,50 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//////////////////////////////////////////////////////////////////////////////
///@file pxquad.h
/// Renderer for quadruple pixels (4x4).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_quad (word x,word y,byte color);
byte Read_pixel_quad (word x,word y);
void Block_quad (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_quad (word x,word y,byte color);
void Pixel_preview_magnifier_quad (word x,word y,byte color);
void Horizontal_XOR_line_quad (word x_pos,word y_pos,word width);
void Vertical_XOR_line_quad (word x_pos,word y_pos,word height);
void Display_brush_color_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_quad (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_quad (word width,word height,word image_width);
void Display_line_on_screen_quad (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_quad (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_quad(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_quad (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_quad (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_quad (word x_pos,word y_pos,word width,byte * line);

View File

@ -32,13 +32,13 @@
void Pixel_simple (word x,word y,byte color) void Pixel_simple (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */ /* Affiche un pixel de la color aux coords x;y à l'écran */
{ {
*(Screen_pixels + x + y * Screen_width)=color; *(Screen_pixels + x + y * VIDEO_LINE_WIDTH)=color;
} }
byte Read_pixel_simple (word x,word y) byte Read_pixel_simple (word x,word y)
/* On retourne la couleur du pixel aux coords données */ /* On retourne la couleur du pixel aux coords données */
{ {
return *( Screen_pixels + y * Screen_width + x ); return *( Screen_pixels + y * VIDEO_LINE_WIDTH + x );
} }
void Block_simple (word start_x,word start_y,word width,word height,byte color) void Block_simple (word start_x,word start_y,word width,word height,byte color)
@ -67,7 +67,7 @@ void Display_part_of_screen_simple (word width,word height,word image_width)
// On passe à la ligne suivante // On passe à la ligne suivante
src+=image_width; src+=image_width;
dest+=Screen_width; dest+=VIDEO_LINE_WIDTH;
} }
//Update_rect(0,0,width,height); //Update_rect(0,0,width,height);
} }
@ -112,7 +112,7 @@ void Pixel_preview_magnifier_simple (word x,word y,byte color)
void Horizontal_XOR_line_simple(word x_pos,word y_pos,word width) void Horizontal_XOR_line_simple(word x_pos,word y_pos,word width)
{ {
//On calcule la valeur initiale de dest: //On calcule la valeur initiale de dest:
byte* dest=y_pos*Screen_width+x_pos+Screen_pixels; byte* dest=y_pos*VIDEO_LINE_WIDTH+x_pos+Screen_pixels;
int x; int x;
@ -126,15 +126,15 @@ void Vertical_XOR_line_simple(word x_pos,word y_pos,word height)
byte color; byte color;
for (i=y_pos;i<y_pos+height;i++) for (i=y_pos;i<y_pos+height;i++)
{ {
color=*(Screen_pixels+x_pos+i*Screen_width); color=*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH);
*(Screen_pixels+x_pos+i*Screen_width)=~color; *(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH)=~color;
} }
} }
void Display_brush_color_simple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) void Display_brush_color_simple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{ {
// dest = Position à l'écran // dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * Screen_width + x_pos; byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos;
// src = Position dans la brosse // src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset; byte* src = Brush + y_offset * brush_width + x_offset;
@ -157,7 +157,7 @@ void Display_brush_color_simple(word x_pos,word y_pos,word x_offset,word y_offse
} }
// On passe à la ligne suivante // On passe à la ligne suivante
dest = dest + Screen_width - width; dest = dest + VIDEO_LINE_WIDTH - width;
src = src + brush_width - width; src = src + brush_width - width;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
@ -168,7 +168,7 @@ void Display_brush_mono_simple(word x_pos, word y_pos,
byte transp_color, byte color, word brush_width) byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */ /* On affiche la brosse en monochrome */
{ {
byte* dest=y_pos*Screen_width+x_pos+Screen_pixels; // dest = adr Destination à byte* dest=y_pos*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; // dest = adr Destination à
// l'écran // l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse // la brosse
@ -190,14 +190,14 @@ void Display_brush_mono_simple(word x_pos, word y_pos,
// On passe à la ligne suivante // On passe à la ligne suivante
src+=brush_width-width; src+=brush_width-width;
dest+=Screen_width-width; dest+=VIDEO_LINE_WIDTH-width;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
} }
void Clear_brush_simple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) void Clear_brush_simple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{ {
byte* dest=Screen_pixels+x_pos+y_pos*Screen_width; //On va se mettre en 0,0 dans l'écran (dest) byte* dest=Screen_pixels+x_pos+y_pos*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y; int y;
@ -209,7 +209,7 @@ void Clear_brush_simple(word x_pos,word y_pos,__attribute__((unused)) word x_off
// On passe à la ligne suivante // On passe à la ligne suivante
src+=image_width; src+=image_width;
dest+=Screen_width; dest+=VIDEO_LINE_WIDTH;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
} }
@ -218,7 +218,7 @@ void Clear_brush_simple(word x_pos,word y_pos,__attribute__((unused)) word x_off
void Display_brush_simple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) void Display_brush_simple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{ {
// dest = Position à l'écran // dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * Screen_width + x_pos; byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos;
// src = Position dans la brosse // src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset; byte* src = brush + y_offset * brush_width + x_offset;
@ -241,7 +241,7 @@ void Display_brush_simple(byte * brush, word x_pos,word y_pos,word x_offset,word
} }
// On passe à la ligne suivante // On passe à la ligne suivante
dest = dest + Screen_width - width; dest = dest + VIDEO_LINE_WIDTH - width;
src = src + brush_width - width; src = src + brush_width - width;
} }
} }
@ -249,7 +249,7 @@ void Display_brush_simple(byte * brush, word x_pos,word y_pos,word x_offset,word
void Remap_screen_simple(word x_pos,word y_pos,word width,word height,byte * conversion_table) void Remap_screen_simple(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{ {
// dest = coords a l'écran // dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * Screen_width + x_pos; byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos;
int x,y; int x,y;
// Pour chaque ligne // Pour chaque ligne
@ -262,7 +262,7 @@ void Remap_screen_simple(word x_pos,word y_pos,word width,word height,byte * con
dest ++; dest ++;
} }
dest = dest + Screen_width - width; dest = dest + VIDEO_LINE_WIDTH - width;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
@ -271,7 +271,7 @@ void Remap_screen_simple(word x_pos,word y_pos,word width,word height,byte * con
void Display_line_on_screen_simple(word x_pos,word y_pos,word width,byte * line) void Display_line_on_screen_simple(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels. Utilisé pour les textes. */ /* On affiche toute une ligne de pixels. Utilisé pour les textes. */
{ {
memcpy(Screen_pixels+x_pos+y_pos*Screen_width,line,width); memcpy(Screen_pixels+x_pos+y_pos*VIDEO_LINE_WIDTH,line,width);
} }
void Display_transparent_mono_line_on_screen_simple( void Display_transparent_mono_line_on_screen_simple(
@ -280,7 +280,7 @@ void Display_transparent_mono_line_on_screen_simple(
// Affiche une ligne à l'écran avec une couleur + transparence. // Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom // Utilisé par les brosses en mode zoom
{ {
byte* dest = Screen_pixels+ y_pos * Screen_width + x_pos; byte* dest = Screen_pixels+ y_pos * VIDEO_LINE_WIDTH + x_pos;
int x; int x;
// Pour chaque pixel // Pour chaque pixel
for(x=0;x<width;x++) for(x=0;x<width;x++)
@ -294,7 +294,7 @@ void Display_transparent_mono_line_on_screen_simple(
void Read_line_screen_simple(word x_pos,word y_pos,word width,byte * line) void Read_line_screen_simple(word x_pos,word y_pos,word width,byte * line)
{ {
memcpy(line,Screen_width * y_pos + x_pos + Screen_pixels,width); memcpy(line,VIDEO_LINE_WIDTH * y_pos + x_pos + Screen_pixels,width);
} }
void Display_part_of_screen_scaled_simple( void Display_part_of_screen_scaled_simple(
@ -340,7 +340,7 @@ void Display_part_of_screen_scaled_simple(
void Display_transparent_line_on_screen_simple(word x_pos,word y_pos,word width,byte* line,byte transp_color) void Display_transparent_line_on_screen_simple(word x_pos,word y_pos,word width,byte* line,byte transp_color)
{ {
byte* src = line; byte* src = line;
byte* dest = Screen_pixels + y_pos * Screen_width + x_pos; byte* dest = Screen_pixels + y_pos * VIDEO_LINE_WIDTH + x_pos;
word x; word x;

View File

@ -30,17 +30,20 @@
#include "pxtall.h" #include "pxtall.h"
#include "pxsimple.h" #include "pxsimple.h"
#define ZOOMX 1
#define ZOOMY 2
void Pixel_tall (word x,word y,byte color) void Pixel_tall (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */ /* Affiche un pixel de la color aux coords x;y à l'écran */
{ {
*(Screen_pixels + x + y * 2 * Screen_width)=color; *(Screen_pixels + x + y*ZOOMY*VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x + (y * 2 + 1) * Screen_width)=color; *(Screen_pixels + x + (y*ZOOMY+1)*VIDEO_LINE_WIDTH)=color;
} }
byte Read_pixel_tall (word x,word y) byte Read_pixel_tall (word x,word y)
/* On retourne la couleur du pixel aux coords données */ /* On retourne la couleur du pixel aux coords données */
{ {
return *( Screen_pixels + y * 2 * Screen_width + x ); return *( Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x );
} }
void Block_tall (word start_x,word start_y,word width,word height,byte color) void Block_tall (word start_x,word start_y,word width,word height,byte color)
@ -48,9 +51,9 @@ void Block_tall (word start_x,word start_y,word width,word height,byte color)
{ {
SDL_Rect rectangle; SDL_Rect rectangle;
rectangle.x=start_x; rectangle.x=start_x;
rectangle.y=start_y*2; rectangle.y=start_y*ZOOMY;
rectangle.w=width; rectangle.w=width;
rectangle.h=height*2; rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color); SDL_FillRect(Screen_SDL,&rectangle,color);
} }
@ -66,12 +69,12 @@ void Display_part_of_screen_tall (word width,word height,word image_width)
{ {
// On fait une copie de la ligne // On fait une copie de la ligne
memcpy(dest,src,width); memcpy(dest,src,width);
dest+=Screen_width; dest+=VIDEO_LINE_WIDTH;
memcpy(dest,src,width); memcpy(dest,src,width);
// On passe à la ligne suivante // On passe à la ligne suivante
src+=image_width; src+=image_width;
dest+=Screen_width; dest+=VIDEO_LINE_WIDTH;
} }
//Update_rect(0,0,width,height); //Update_rect(0,0,width,height);
} }
@ -116,14 +119,14 @@ void Pixel_preview_magnifier_tall (word x,word y,byte color)
void Horizontal_XOR_line_tall(word x_pos,word y_pos,word width) void Horizontal_XOR_line_tall(word x_pos,word y_pos,word width)
{ {
//On calcule la valeur initiale de dest: //On calcule la valeur initiale de dest:
byte* dest=y_pos*2*Screen_width+x_pos+Screen_pixels; byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos+Screen_pixels;
int x; int x;
for (x=0;x<width;x++) for (x=0;x<width;x++)
*(dest+x)=~*(dest+x); *(dest+x)=~*(dest+x);
dest=(y_pos*2+1)*Screen_width+x_pos+Screen_pixels; dest=(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH+x_pos+Screen_pixels;
for (x=0;x<width;x++) for (x=0;x<width;x++)
*(dest+x)=~*(dest+x); *(dest+x)=~*(dest+x);
} }
@ -132,17 +135,17 @@ void Vertical_XOR_line_tall(word x_pos,word y_pos,word height)
{ {
int i; int i;
byte color; byte color;
for (i=y_pos*2;i<(y_pos+height)*2;i++) for (i=y_pos*ZOOMY;i<(y_pos+height)*ZOOMY;i++)
{ {
color=*(Screen_pixels+x_pos+i*Screen_width); color=*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH);
*(Screen_pixels+x_pos+i*Screen_width)=~color; *(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH)=~color;
} }
} }
void Display_brush_color_tall(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) void Display_brush_color_tall(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{ {
// dest = Position à l'écran // dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * 2 * Screen_width + x_pos; byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos;
// src = Position dans la brosse // src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset; byte* src = Brush + y_offset * brush_width + x_offset;
@ -158,7 +161,7 @@ void Display_brush_color_tall(word x_pos,word y_pos,word x_offset,word y_offset,
if(*src != transp_color) if(*src != transp_color)
{ {
*dest = *src; *dest = *src;
*(dest+Screen_width) = *src; *(dest+VIDEO_LINE_WIDTH) = *src;
} }
// Pixel suivant // Pixel suivant
@ -166,7 +169,7 @@ void Display_brush_color_tall(word x_pos,word y_pos,word x_offset,word y_offset,
} }
// On passe à la ligne suivante // On passe à la ligne suivante
dest = dest + 2 * Screen_width - width; dest = dest + ZOOMY*VIDEO_LINE_WIDTH - width;
src = src + brush_width - width; src = src + brush_width - width;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
@ -177,7 +180,7 @@ void Display_brush_mono_tall(word x_pos, word y_pos,
byte transp_color, byte color, word brush_width) byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */ /* On affiche la brosse en monochrome */
{ {
byte* dest=y_pos*2*Screen_width+x_pos+Screen_pixels; // dest = adr Destination à byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos+Screen_pixels; // dest = adr Destination à
// l'écran // l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse // la brosse
@ -192,7 +195,7 @@ void Display_brush_mono_tall(word x_pos, word y_pos,
if (*src!=transp_color) if (*src!=transp_color)
{ {
*dest=color; *dest=color;
*(dest+Screen_width)=color; *(dest+VIDEO_LINE_WIDTH)=color;
} }
// On passe au pixel suivant // On passe au pixel suivant
@ -202,14 +205,14 @@ void Display_brush_mono_tall(word x_pos, word y_pos,
// On passe à la ligne suivante // On passe à la ligne suivante
src+=brush_width-width; src+=brush_width-width;
dest+=2*Screen_width-width; dest+=ZOOMY*VIDEO_LINE_WIDTH-width;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
} }
void Clear_brush_tall(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) void Clear_brush_tall(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{ {
byte* dest=Screen_pixels+x_pos+y_pos*2*Screen_width; //On va se mettre en 0,0 dans l'écran (dest) byte* dest=Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y; int y;
@ -218,12 +221,12 @@ void Clear_brush_tall(word x_pos,word y_pos,__attribute__((unused)) word x_offse
{ {
// On fait une copie de la ligne // On fait une copie de la ligne
memcpy(dest,src,width); memcpy(dest,src,width);
dest+=Screen_width; dest+=VIDEO_LINE_WIDTH;
memcpy(dest,src,width); memcpy(dest,src,width);
// On passe à la ligne suivante // On passe à la ligne suivante
src+=image_width; src+=image_width;
dest+=Screen_width; dest+=VIDEO_LINE_WIDTH;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
} }
@ -232,7 +235,7 @@ void Clear_brush_tall(word x_pos,word y_pos,__attribute__((unused)) word x_offse
void Display_brush_tall(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) void Display_brush_tall(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{ {
// dest = Position à l'écran // dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * 2 * Screen_width + x_pos; byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos;
// src = Position dans la brosse // src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset; byte* src = brush + y_offset * brush_width + x_offset;
@ -248,7 +251,7 @@ void Display_brush_tall(byte * brush, word x_pos,word y_pos,word x_offset,word y
if(*src != transp_color) if(*src != transp_color)
{ {
*dest = *src; *dest = *src;
*(dest+Screen_width) = *src; *(dest+VIDEO_LINE_WIDTH) = *src;
} }
// Pixel suivant // Pixel suivant
@ -256,7 +259,7 @@ void Display_brush_tall(byte * brush, word x_pos,word y_pos,word x_offset,word y
} }
// On passe à la ligne suivante // On passe à la ligne suivante
dest = dest + Screen_width * 2 - width; dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width;
src = src + brush_width - width; src = src + brush_width - width;
} }
} }
@ -264,11 +267,11 @@ void Display_brush_tall(byte * brush, word x_pos,word y_pos,word x_offset,word y
void Remap_screen_tall(word x_pos,word y_pos,word width,word height,byte * conversion_table) void Remap_screen_tall(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{ {
// dest = coords a l'écran // dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * 2 * Screen_width + x_pos; byte* dest = Screen_pixels + y_pos*ZOOMY*VIDEO_LINE_WIDTH + x_pos;
int x,y; int x,y;
// Pour chaque ligne // Pour chaque ligne
for(y=height*2;y>0;y--) for(y=height*ZOOMY;y>0;y--)
{ {
// Pour chaque pixel // Pour chaque pixel
for(x=width;x>0;x--) for(x=width;x>0;x--)
@ -277,7 +280,7 @@ void Remap_screen_tall(word x_pos,word y_pos,word width,word height,byte * conve
dest ++; dest ++;
} }
dest = dest + Screen_width - width; dest = dest + VIDEO_LINE_WIDTH - width;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
@ -286,13 +289,13 @@ void Remap_screen_tall(word x_pos,word y_pos,word width,word height,byte * conve
void Display_line_on_screen_tall(word x_pos,word y_pos,word width,byte * line) void Display_line_on_screen_tall(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels. Utilisé pour les textes. */ /* On affiche toute une ligne de pixels. Utilisé pour les textes. */
{ {
memcpy(Screen_pixels+x_pos+y_pos*2*Screen_width,line,width); memcpy(Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width);
memcpy(Screen_pixels+x_pos+(y_pos*2+1)*Screen_width,line,width); memcpy(Screen_pixels+x_pos+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width);
} }
void Read_line_screen_tall(word x_pos,word y_pos,word width,byte * line) void Read_line_screen_tall(word x_pos,word y_pos,word width,byte * line)
{ {
memcpy(line,Screen_width * 2 * y_pos + x_pos + Screen_pixels,width); memcpy(line,VIDEO_LINE_WIDTH*ZOOMY*y_pos + x_pos + Screen_pixels,width);
} }
void Display_part_of_screen_scaled_tall( void Display_part_of_screen_scaled_tall(
@ -312,7 +315,7 @@ void Display_part_of_screen_scaled_tall(
// On éclate la ligne // On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width); Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On l'affiche Facteur fois, sur des lignes consécutives // On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor*2; x = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne // Pour chaque ligne
do{ do{
// On affiche la ligne zoomée // On affiche la ligne zoomée
@ -322,7 +325,7 @@ void Display_part_of_screen_scaled_tall(
); );
// On passe à la suivante // On passe à la suivante
y++; y++;
if(y==height*2) if(y==height*ZOOMY)
{ {
Update_rect(Main_X_zoom,0, Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height); width*Main_magnifier_factor,height);
@ -354,8 +357,8 @@ void Display_brush_color_zoom_tall(word x_pos,word y_pos,
// On affiche facteur fois la ligne zoomée // On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--) for(bx=Main_magnifier_factor;bx>0;bx--)
{ {
Display_transparent_line_on_screen_simple(x_pos,y*2,width*Main_magnifier_factor,buffer,transp_color); Display_transparent_line_on_screen_simple(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color);
memcpy(Screen_pixels + (y*2 +1) * Screen_width + x_pos, Screen_pixels + y*2* Screen_width + x_pos, width*Main_magnifier_factor); memcpy(Screen_pixels + (y*ZOOMY +1) * VIDEO_LINE_WIDTH + x_pos, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos, width*Main_magnifier_factor);
y++; y++;
if(y==end_y_pos) if(y==end_y_pos)
{ {
@ -378,7 +381,7 @@ void Display_brush_mono_zoom_tall(word x_pos, word y_pos,
{ {
byte* src = Brush + y_offset * brush_width + x_offset; byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*2; int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer : //Pour chaque ligne à zoomer :
while(1) while(1)
@ -390,7 +393,7 @@ void Display_brush_mono_zoom_tall(word x_pos, word y_pos,
// On affiche la ligne Facteur fois à l'écran (sur des // On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives) // lignes consécutives)
bx = Main_magnifier_factor*2; bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran // Pour chaque ligne écran
do do
@ -403,7 +406,7 @@ void Display_brush_mono_zoom_tall(word x_pos, word y_pos,
// On passe à la ligne suivante // On passe à la ligne suivante
y++; y++;
// On vérifie qu'on est pas à la ligne finale // On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*2) if(y == end_y_pos*ZOOMY)
{ {
Update_rect( x_pos, y_pos, Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos ); width * Main_magnifier_factor, end_y_pos - y_pos );

526
pxtall2.c Normal file
View File

@ -0,0 +1,526 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "pxtall2.h"
#define ZOOMX 2
#define ZOOMY 4
void Pixel_tall2 (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+3) * VIDEO_LINE_WIDTH + 1)=color;
}
byte Read_pixel_tall2 (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_tall2 (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_tall2 (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la triple
memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la quadruple
memcpy(dest-width*ZOOMX+3*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_tall2 (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_tall2(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_tall2 (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_tall2(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Zoom_factor_table[y-Main_magnifier_offset_Y];
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_tall2(
Zoom_factor_table[x-Main_magnifier_offset_X]+Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_tall2(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+3*VIDEO_LINE_WIDTH+1)=*(dest+x+3*VIDEO_LINE_WIDTH)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_tall2(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=~*(dest);
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_tall2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+3*VIDEO_LINE_WIDTH+1) = *(dest+3*VIDEO_LINE_WIDTH) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_tall2(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_tall2(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_tall2(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_tall2(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_tall2(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+3)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_tall2(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_tall2(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_tall2(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_tall2(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_tall2(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
{
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_tall2(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
byte* line_src = buffer;
byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width*Main_magnifier_factor;x > 0;x--)
{
if(*line_src!=transp_color)
{
*(dest+1)=*dest = *line_src;
}
line_src++;
dest+=ZOOMX;
}
// Double the line
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Triple the line
memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Quadruple it
memcpy(Screen_pixels + (y*ZOOMY+3)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_tall2(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_tall2(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_tall2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_tall2(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

50
pxtall2.h Normal file
View File

@ -0,0 +1,50 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//////////////////////////////////////////////////////////////////////////////
///@file pxtall2.h
/// Renderer for double-tall pixels (2x4).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_tall2 (word x,word y,byte color);
byte Read_pixel_tall2 (word x,word y);
void Block_tall2 (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_tall2 (word x,word y,byte color);
void Pixel_preview_magnifier_tall2 (word x,word y,byte color);
void Horizontal_XOR_line_tall2 (word x_pos,word y_pos,word width);
void Vertical_XOR_line_tall2 (word x_pos,word y_pos,word height);
void Display_brush_color_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_tall2 (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_tall2 (word width,word height,word image_width);
void Display_line_on_screen_tall2 (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_tall2 (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_tall2(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_tall2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_tall2 (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_tall2 (word x_pos,word y_pos,word width,byte * line);

522
pxtriple.c Normal file
View File

@ -0,0 +1,522 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "pxtriple.h"
#define ZOOMX 3
#define ZOOMY 3
void Pixel_triple (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+2) * VIDEO_LINE_WIDTH + 2)=color;
}
byte Read_pixel_triple (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_triple (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_triple (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+2)=*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On la triple
memcpy(dest-width*ZOOMX+2*VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_triple (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_triple(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_triple (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_triple(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Zoom_factor_table[y-Main_magnifier_offset_Y];
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_triple(
Zoom_factor_table[x-Main_magnifier_offset_X]+Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_triple(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+2*VIDEO_LINE_WIDTH+2)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_triple(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=~*dest;
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_triple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+2*VIDEO_LINE_WIDTH+2) = *(dest+2*VIDEO_LINE_WIDTH+1) = *(dest+2*VIDEO_LINE_WIDTH) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+2) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_triple(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_triple(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_triple(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_triple(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_triple(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+2)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_triple(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_triple(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+2)=*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_triple(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_triple(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_triple(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
{
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_triple(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
byte* line_src = buffer;
byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width*Main_magnifier_factor;x > 0;x--)
{
if(*line_src!=transp_color)
{
*(dest+2)=*(dest+1)=*dest = *line_src;
}
line_src++;
dest+=ZOOMX;
}
// Double the line
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
// Triple the line
memcpy(Screen_pixels + (y*ZOOMY+2)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_triple(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_triple(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_triple(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_triple(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

50
pxtriple.h Normal file
View File

@ -0,0 +1,50 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//////////////////////////////////////////////////////////////////////////////
///@file pxtriple.h
/// Renderer for triple pixels (3x3).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_triple (word x,word y,byte color);
byte Read_pixel_triple (word x,word y);
void Block_triple (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_triple (word x,word y,byte color);
void Pixel_preview_magnifier_triple (word x,word y,byte color);
void Horizontal_XOR_line_triple (word x_pos,word y_pos,word width);
void Vertical_XOR_line_triple (word x_pos,word y_pos,word height);
void Display_brush_color_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_triple (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_triple (word width,word height,word image_width);
void Display_line_on_screen_triple (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_triple (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_triple(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_triple (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_triple (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_triple (word x_pos,word y_pos,word width,byte * line);

103
pxwide.c
View File

@ -29,27 +29,30 @@
#include "misc.h" #include "misc.h"
#include "pxwide.h" #include "pxwide.h"
#define ZOOMX 2
#define ZOOMY 1
void Pixel_wide (word x,word y,byte color) void Pixel_wide (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */ /* Affiche un pixel de la color aux coords x;y à l'écran */
{ {
*(Screen_pixels + x * 2 + y * 2 * Screen_width)=color; *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * 2 + y * 2 * Screen_width + 1)=color; *(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
} }
byte Read_pixel_wide (word x,word y) byte Read_pixel_wide (word x,word y)
/* On retourne la couleur du pixel aux coords données */ /* On retourne la couleur du pixel aux coords données */
{ {
return *( Screen_pixels + y * 2 * Screen_width + x * 2); return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
} }
void Block_wide (word start_x,word start_y,word width,word height,byte color) void Block_wide (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */ /* On affiche un rectangle de la couleur donnée */
{ {
SDL_Rect rectangle; SDL_Rect rectangle;
rectangle.x=start_x*2; rectangle.x=start_x*ZOOMX;
rectangle.y=start_y; rectangle.y=start_y*ZOOMY;
rectangle.w=width*2; rectangle.w=width*ZOOMX;
rectangle.h=height; rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color); SDL_FillRect(Screen_SDL,&rectangle,color);
} }
@ -69,12 +72,12 @@ void Display_part_of_screen_wide (word width,word height,word image_width)
{ {
*(dest+1)=*dest=*src; *(dest+1)=*dest=*src;
src++; src++;
dest+=2; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
src+=image_width-width; src+=image_width-width;
dest+=(Screen_width - width)*2; dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
} }
//Update_rect(0,0,width,height); //Update_rect(0,0,width,height);
} }
@ -119,32 +122,29 @@ void Pixel_preview_magnifier_wide (word x,word y,byte color)
void Horizontal_XOR_line_wide(word x_pos,word y_pos,word width) void Horizontal_XOR_line_wide(word x_pos,word y_pos,word width)
{ {
//On calcule la valeur initiale de dest: //On calcule la valeur initiale de dest:
byte* dest=y_pos*2*Screen_width+x_pos*2+Screen_pixels; byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x; int x;
for (x=0;x<width*2;x+=2) for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+1)=*(dest+x)=~*(dest+x); *(dest+x+1)=*(dest+x)=~*(dest+x);
} }
void Vertical_XOR_line_wide(word x_pos,word y_pos,word height) void Vertical_XOR_line_wide(word x_pos,word y_pos,word height)
{ {
int i; int i;
byte color; byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
byte *dest=Screen_pixels+x_pos*2+y_pos*Screen_width*2;
for (i=height;i>0;i--) for (i=height;i>0;i--)
{ {
color=~*dest; *dest=*(dest+1)=~*dest;
*dest=color; dest+=VIDEO_LINE_WIDTH*ZOOMY;
*(dest+1)=color;
dest+=Screen_width*2;
} }
} }
void Display_brush_color_wide(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) void Display_brush_color_wide(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{ {
// dest = Position à l'écran // dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * 2 * Screen_width + x_pos * 2; byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse // src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset; byte* src = Brush + y_offset * brush_width + x_offset;
@ -164,11 +164,11 @@ void Display_brush_color_wide(word x_pos,word y_pos,word x_offset,word y_offset,
// Pixel suivant // Pixel suivant
src++; src++;
dest+=2; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
dest = dest + (Screen_width - width)*2; dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width; src = src + brush_width - width;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
@ -179,7 +179,7 @@ void Display_brush_mono_wide(word x_pos, word y_pos,
byte transp_color, byte color, word brush_width) byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */ /* On affiche la brosse en monochrome */
{ {
byte* dest=y_pos*2*Screen_width+x_pos*2+Screen_pixels; // dest = adr Destination à byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran // l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse // la brosse
@ -196,19 +196,19 @@ void Display_brush_mono_wide(word x_pos, word y_pos,
// On passe au pixel suivant // On passe au pixel suivant
src++; src++;
dest+=2; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
src+=brush_width-width; src+=brush_width-width;
dest+=(Screen_width-width)*2; dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
} }
void Clear_brush_wide(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width) void Clear_brush_wide(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{ {
byte* dest=Screen_pixels+x_pos*2+y_pos*2*Screen_width; //On va se mettre en 0,0 dans l'écran (dest) byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src) byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y; int y;
int x; int x;
@ -223,12 +223,12 @@ void Clear_brush_wide(word x_pos,word y_pos,__attribute__((unused)) word x_offse
// On passe au pixel suivant // On passe au pixel suivant
src++; src++;
dest+=2; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
src+=image_width-width; src+=image_width-width;
dest+=(Screen_width-width)*2; dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
} }
@ -237,7 +237,7 @@ void Clear_brush_wide(word x_pos,word y_pos,__attribute__((unused)) word x_offse
void Display_brush_wide(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width) void Display_brush_wide(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{ {
// dest = Position à l'écran // dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * 2 * Screen_width + x_pos * 2; byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse // src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset; byte* src = brush + y_offset * brush_width + x_offset;
@ -256,11 +256,11 @@ void Display_brush_wide(byte * brush, word x_pos,word y_pos,word x_offset,word y
} }
// Pixel suivant // Pixel suivant
src++; dest+=2; src++; dest+=ZOOMX;
} }
// On passe à la ligne suivante // On passe à la ligne suivante
dest = dest + (Screen_width - width)*2; dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width; src = src + brush_width - width;
} }
} }
@ -268,7 +268,7 @@ void Display_brush_wide(byte * brush, word x_pos,word y_pos,word x_offset,word y
void Remap_screen_wide(word x_pos,word y_pos,word width,word height,byte * conversion_table) void Remap_screen_wide(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{ {
// dest = coords a l'écran // dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * 2 * Screen_width + x_pos * 2; byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y; int x,y;
// Pour chaque ligne // Pour chaque ligne
@ -278,10 +278,10 @@ void Remap_screen_wide(word x_pos,word y_pos,word width,word height,byte * conve
for(x=width;x>0;x--) for(x=width;x>0;x--)
{ {
*(dest+1) = *dest = conversion_table[*dest]; *(dest+1) = *dest = conversion_table[*dest];
dest +=2; dest +=ZOOMX;
} }
dest = dest + (Screen_width - width)*2; dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
} }
Update_rect(x_pos,y_pos,width,height); Update_rect(x_pos,y_pos,width,height);
@ -291,7 +291,7 @@ void Display_line_on_screen_fast_wide(word x_pos,word y_pos,word width,byte * li
/* On affiche toute une ligne de pixels telle quelle. */ /* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */ /* Utilisée si le buffer contient déja des pixel doublés. */
{ {
memcpy(Screen_pixels+x_pos*2+y_pos*2*Screen_width,line,width*2); memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
} }
void Display_line_on_screen_wide(word x_pos,word y_pos,word width,byte * line) void Display_line_on_screen_wide(word x_pos,word y_pos,word width,byte * line)
@ -299,13 +299,11 @@ void Display_line_on_screen_wide(word x_pos,word y_pos,word width,byte * line)
{ {
int x; int x;
byte *dest; byte *dest;
dest=Screen_pixels+x_pos*2+y_pos*2*Screen_width; dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--) for(x=width;x>0;x--)
{ {
*dest=*line; *(dest+1)=*dest=*line;
dest++; dest+=ZOOMX;
*dest=*line;
dest++;
line++; line++;
} }
} }
@ -315,24 +313,23 @@ void Display_transparent_mono_line_on_screen_wide(
// Affiche une ligne à l'écran avec une couleur + transparence. // Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom // Utilisé par les brosses en mode zoom
{ {
byte* dest = Screen_pixels+ y_pos*2 * Screen_width + x_pos*2; byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x; int x;
// Pour chaque pixel // Pour chaque pixel
for(x=0;x<width;x++) for(x=0;x<width;x++)
{ {
if (transp_color!=*line) if (transp_color!=*line)
{ {
*dest = color; *(dest+1)=*dest=color;
*(dest+1) = color;
} }
line ++; // Pixel suivant line ++; // Pixel suivant
dest+=2; dest+=ZOOMX;
} }
} }
void Read_line_screen_wide(word x_pos,word y_pos,word width,byte * line) void Read_line_screen_wide(word x_pos,word y_pos,word width,byte * line)
{ {
memcpy(line,Screen_width * 2 * y_pos + x_pos * 2 + Screen_pixels,width*2); memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
} }
void Display_part_of_screen_scaled_wide( void Display_part_of_screen_scaled_wide(
@ -350,7 +347,7 @@ void Display_part_of_screen_scaled_wide(
int x; int x;
// On éclate la ligne // On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*2,width); Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives // On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor; x = Main_magnifier_factor;
// Pour chaque ligne // Pour chaque ligne
@ -378,8 +375,7 @@ void Display_part_of_screen_scaled_wide(
void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,byte* line,byte transp_color) void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,byte* line,byte transp_color)
{ {
byte* src = line; byte* src = line;
byte* dest = Screen_pixels + y_pos * 2 * Screen_width + x_pos * 2; byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
word x; word x;
// Pour chaque pixel de la ligne // Pour chaque pixel de la ligne
@ -387,11 +383,10 @@ void Display_transparent_line_on_screen_wide(word x_pos,word y_pos,word width,by
{ {
if(*src!=transp_color) if(*src!=transp_color)
{ {
*dest = *src; *(dest+1) = *dest = *src;
*(dest+1) = *src;
} }
src++; src++;
dest+=2; dest+=ZOOMX;
} }
} }
@ -414,7 +409,7 @@ void Display_brush_color_zoom_wide(word x_pos,word y_pos,
// On affiche facteur fois la ligne zoomée // On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--) for(bx=Main_magnifier_factor;bx>0;bx--)
{ {
Display_transparent_line_on_screen_wide(x_pos,y,width*Main_magnifier_factor,buffer,transp_color); Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color);
y++; y++;
if(y==end_y_pos) if(y==end_y_pos)
{ {
@ -437,7 +432,7 @@ void Display_brush_mono_zoom_wide(word x_pos, word y_pos,
{ {
byte* src = Brush + y_offset * brush_width + x_offset; byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos; int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer : //Pour chaque ligne à zoomer :
while(1) while(1)
@ -449,7 +444,7 @@ void Display_brush_mono_zoom_wide(word x_pos, word y_pos,
// On affiche la ligne Facteur fois à l'écran (sur des // On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives) // lignes consécutives)
bx = Main_magnifier_factor; bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran // Pour chaque ligne écran
do do
@ -462,7 +457,7 @@ void Display_brush_mono_zoom_wide(word x_pos, word y_pos,
// On passe à la ligne suivante // On passe à la ligne suivante
y++; y++;
// On vérifie qu'on est pas à la ligne finale // On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos) if(y == end_y_pos*ZOOMY)
{ {
Update_rect( x_pos, y_pos, Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos ); width * Main_magnifier_factor, end_y_pos - y_pos );
@ -486,7 +481,7 @@ void Clear_brush_scaled_wide(word x_pos,word y_pos,word x_offset,word y_offset,w
// Pour chaque ligne à zoomer // Pour chaque ligne à zoomer
while(1){ while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*2,width); Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor; bx=Main_magnifier_factor;

516
pxwide2.c Normal file
View File

@ -0,0 +1,516 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <stdlib.h>
#include <SDL.h>
#include "global.h"
#include "sdlscreen.h"
#include "misc.h"
#include "pxwide2.h"
#define ZOOMX 4
#define ZOOMY 2
void Pixel_wide2 (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 3)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 1)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 2)=color;
*(Screen_pixels + x * ZOOMX + (y*ZOOMY+1) * VIDEO_LINE_WIDTH + 3)=color;
}
byte Read_pixel_wide2 (word x,word y)
/* On retourne la couleur du pixel aux coords données */
{
return *( Screen_pixels + y * ZOOMY * VIDEO_LINE_WIDTH + x * ZOOMX);
}
void Block_wide2 (word start_x,word start_y,word width,word height,byte color)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
SDL_FillRect(Screen_SDL,&rectangle,color);
}
void Display_part_of_screen_wide2 (word width,word height,word image_width)
/* Afficher une partie de l'image telle quelle sur l'écran */
{
byte* dest=Screen_pixels; //On va se mettre en 0,0 dans l'écran (dest)
byte* src=Main_offset_Y*image_width+Main_offset_X+Main_screen; //Coords de départ ds la source (src)
int y;
int dy;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
// On fait une copie de la ligne
for (dy=width;dy>0;dy--)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
src++;
dest+=ZOOMX;
}
// On double la ligne qu'on vient de copier
memcpy(dest-width*ZOOMX+VIDEO_LINE_WIDTH,dest-width*ZOOMX,width*ZOOMX);
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//Update_rect(0,0,width,height);
}
void Pixel_preview_normal_wide2 (word x,word y,byte color)
/* Affichage d'un pixel dans l'écran, par rapport au décalage de l'image
* dans l'écran, en mode normal (pas en mode loupe)
* Note: si on modifie cette procédure, il faudra penser à faire également
* la modif dans la procédure Pixel_Preview_Loupe_SDL. */
{
// if(x-Main_offset_X >= 0 && y - Main_offset_Y >= 0)
Pixel_wide2(x-Main_offset_X,y-Main_offset_Y,color);
}
void Pixel_preview_magnifier_wide2 (word x,word y,byte color)
{
// Affiche le pixel dans la partie non zoomée
Pixel_wide2(x-Main_offset_X,y-Main_offset_Y,color);
// Regarde si on doit aussi l'afficher dans la partie zoomée
if (y >= Limit_top_zoom && y <= Limit_visible_bottom_zoom
&& x >= Limit_left_zoom && x <= Limit_visible_right_zoom)
{
// On est dedans
int height;
int y_zoom = Zoom_factor_table[y-Main_magnifier_offset_Y];
if (Menu_Y - y_zoom < Main_magnifier_factor)
// On ne doit dessiner qu'un morceau du pixel
// sinon on dépasse sur le menu
height = Menu_Y - y_zoom;
else
height = Main_magnifier_factor;
Block_wide2(
Zoom_factor_table[x-Main_magnifier_offset_X]+Main_X_zoom,
y_zoom, Main_magnifier_factor, height, color
);
}
}
void Horizontal_XOR_line_wide2(word x_pos,word y_pos,word width)
{
//On calcule la valeur initiale de dest:
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels;
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+VIDEO_LINE_WIDTH+3)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+3)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_wide2(word x_pos,word y_pos,word height)
{
int i;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest);
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
void Display_brush_color_wide2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = Brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+VIDEO_LINE_WIDTH+3) = *(dest+VIDEO_LINE_WIDTH+2) = *(dest+VIDEO_LINE_WIDTH+1) = *(dest+VIDEO_LINE_WIDTH) = *(dest+3) = *(dest+2) = *(dest+1) = *dest = *src;
}
// Pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_brush_mono_wide2(word x_pos, word y_pos,
word x_offset, word y_offset, word width, word height,
byte transp_color, byte color, word brush_width)
/* On affiche la brosse en monochrome */
{
byte* dest=y_pos*ZOOMY*VIDEO_LINE_WIDTH+x_pos*ZOOMX+Screen_pixels; // dest = adr destination à
// l'écran
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
int x,y;
for(y=height;y!=0;y--)
//Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
if (*src!=transp_color)
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=color;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Clear_brush_wide2(word x_pos,word y_pos,__attribute__((unused)) word x_offset,__attribute__((unused)) word y_offset,word width,word height,__attribute__((unused))byte transp_color,word image_width)
{
byte* dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH; //On va se mettre en 0,0 dans l'écran (dest)
byte* src = ( y_pos + Main_offset_Y ) * image_width + x_pos + Main_offset_X + Main_screen; //Coords de départ ds la source (src)
int y;
int x;
for(y=height;y!=0;y--)
// Pour chaque ligne
{
for(x=width;x!=0;x--)
//Pour chaque pixel
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
// On passe au pixel suivant
src++;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
// Affiche une brosse (arbitraire) à l'écran
void Display_brush_wide2(byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width)
{
// dest = Position à l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
// src = Position dans la brosse
byte* src = brush + y_offset * brush_width + x_offset;
word x,y;
// Pour chaque ligne
for(y = height;y > 0; y--)
{
// Pour chaque pixel
for(x = width;x > 0; x--)
{
// On vérifie que ce n'est pas la transparence
if(*src != transp_color)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*src;
}
// Pixel suivant
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
}
void Remap_screen_wide2(word x_pos,word y_pos,word width,word height,byte * conversion_table)
{
// dest = coords a l'écran
byte* dest = Screen_pixels + y_pos * ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
int x,y;
// Pour chaque ligne
for(y=height;y>0;y--)
{
// Pour chaque pixel
for(x=width;x>0;x--)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=
conversion_table[*dest];
dest +=ZOOMX;
}
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
Update_rect(x_pos,y_pos,width,height);
}
void Display_line_on_screen_fast_wide2(word x_pos,word y_pos,word width,byte * line)
/* On affiche toute une ligne de pixels telle quelle. */
/* Utilisée si le buffer contient déja des pixel doublés. */
{
memcpy(Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH,line,width*ZOOMX);
memcpy(Screen_pixels+x_pos*ZOOMX+(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH,line,width*ZOOMX);
}
void Display_line_on_screen_wide2(word x_pos,word y_pos,word width,byte * line)
/* On affiche une ligne de pixels en les doublant. */
{
int x;
byte *dest;
dest=Screen_pixels+x_pos*ZOOMX+y_pos*ZOOMY*VIDEO_LINE_WIDTH;
for(x=width;x>0;x--)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
void Display_transparent_mono_line_on_screen_wide2(
word x_pos, word y_pos, word width, byte* line,
byte transp_color, byte color)
// Affiche une ligne à l'écran avec une couleur + transparence.
// Utilisé par les brosses en mode zoom
{
byte* dest = Screen_pixels+ y_pos*VIDEO_LINE_WIDTH + x_pos*ZOOMX;
int x;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=ZOOMX;
}
}
void Read_line_screen_wide2(word x_pos,word y_pos,word width,byte * line)
{
memcpy(line,VIDEO_LINE_WIDTH*ZOOMY * y_pos + x_pos * ZOOMX + Screen_pixels,width*ZOOMX);
}
void Display_part_of_screen_scaled_wide2(
word width, // width non zoomée
word height, // height zoomée
word image_width,byte * buffer)
{
byte* src = Main_screen + Main_magnifier_offset_Y * image_width
+ Main_magnifier_offset_X;
int y = 0; // Ligne en cours de traitement
// Pour chaque ligne à zoomer
while(1)
{
int x;
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor/**ZOOMY*/;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
Display_line_on_screen_fast_wide2(
Main_X_zoom, y, width*Main_magnifier_factor,
buffer
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
{
Update_rect(Main_X_zoom,0,
width*Main_magnifier_factor,height);
return;
}
x--;
}while (x > 0);
src += image_width;
}
// ATTENTION on n'arrive jamais ici !
}
// Affiche une partie de la brosse couleur zoomée
void Display_brush_color_zoom_wide2(word x_pos,word y_pos,
word x_offset,word y_offset,
word width, // width non zoomée
word end_y_pos,byte transp_color,
word brush_width, // width réelle de la brosse
byte * buffer)
{
byte* src = Brush+y_offset*brush_width + x_offset;
word y = y_pos;
byte bx;
// Pour chaque ligne
while(1)
{
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche facteur fois la ligne zoomée
for(bx=Main_magnifier_factor;bx>0;bx--)
{
byte* line_src = buffer;
byte* dest = Screen_pixels + y*ZOOMY * VIDEO_LINE_WIDTH + x_pos * ZOOMX;
word x;
// Pour chaque pixel de la ligne
for(x = width*Main_magnifier_factor;x > 0;x--)
{
if(*line_src!=transp_color)
{
*(dest+3)=*(dest+2)=*(dest+1)=*dest = *line_src;
}
line_src++;
dest+=ZOOMX;
}
// Double the line
memcpy(Screen_pixels + (y*ZOOMY+1)*VIDEO_LINE_WIDTH + x_pos*ZOOMX, Screen_pixels + y*ZOOMY*VIDEO_LINE_WIDTH + x_pos*ZOOMX, width*ZOOMX*Main_magnifier_factor);
y++;
if(y==end_y_pos)
{
return;
}
}
src += brush_width;
}
// ATTENTION zone jamais atteinte
}
void Display_brush_mono_zoom_wide2(word x_pos, word y_pos,
word x_offset, word y_offset,
word width, // width non zoomée
word end_y_pos,
byte transp_color, byte color,
word brush_width, // width réelle de la brosse
byte * buffer
)
{
byte* src = Brush + y_offset * brush_width + x_offset;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
while(1)
{
int bx;
// src = Ligne originale
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On affiche la ligne Facteur fois à l'écran (sur des
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
{
// On affiche la ligne zoomée
Display_transparent_mono_line_on_screen_wide2(
x_pos, y, width * Main_magnifier_factor,
buffer, transp_color, color
);
// On passe à la ligne suivante
y++;
// On vérifie qu'on est pas à la ligne finale
if(y == end_y_pos*ZOOMY)
{
Update_rect( x_pos, y_pos,
width * Main_magnifier_factor, end_y_pos - y_pos );
return;
}
bx --;
}
while (bx > 0);
// Passage à la ligne suivante dans la brosse aussi
src+=brush_width;
}
}
void Clear_brush_scaled_wide2(word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,__attribute__((unused)) byte transp_color,word image_width,byte * buffer)
{
// En fait on va recopier l'image non zoomée dans la partie zoomée !
byte* src = Main_screen + y_offset * image_width + x_offset;
int y = y_pos;
int bx;
// Pour chaque ligne à zoomer
while(1){
Zoom_a_line(src,buffer,Main_magnifier_factor*ZOOMX,width);
bx=Main_magnifier_factor;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_wide2(x_pos,y,
width * Main_magnifier_factor,buffer);
// Ligne suivante
y++;
if(y==end_y_pos)
{
Update_rect(x_pos,y_pos,
width*Main_magnifier_factor,end_y_pos-y_pos);
return;
}
bx--;
}while(bx!=0);
src+= image_width;
}
}

50
pxwide2.h Normal file
View File

@ -0,0 +1,50 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//////////////////////////////////////////////////////////////////////////////
///@file pxwide2.h
/// Renderer for double-wide pixels (4x2).
//////////////////////////////////////////////////////////////////////////////
#include "struct.h"
void Pixel_wide2 (word x,word y,byte color);
byte Read_pixel_wide2 (word x,word y);
void Block_wide2 (word start_x,word start_y,word width,word height,byte color);
void Pixel_preview_normal_wide2 (word x,word y,byte color);
void Pixel_preview_magnifier_wide2 (word x,word y,byte color);
void Horizontal_XOR_line_wide2 (word x_pos,word y_pos,word width);
void Vertical_XOR_line_wide2 (word x_pos,word y_pos,word height);
void Display_brush_color_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_brush_mono_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,byte color,word brush_width);
void Clear_brush_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word image_width);
void Remap_screen_wide2 (word x_pos,word y_pos,word width,word height,byte * conversion_table);
void Display_part_of_screen_wide2 (word width,word height,word image_width);
void Display_line_on_screen_wide2 (word x_pos,word y_pos,word width,byte * line);
void Read_line_screen_wide2 (word x_pos,word y_pos,word width,byte * line);
void Display_part_of_screen_scaled_wide2(word width,word height,word image_width,byte * buffer);
void Display_brush_color_zoom_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word brush_width,byte * buffer);
void Display_brush_mono_zoom_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,byte color,word brush_width,byte * buffer);
void Clear_brush_scaled_wide2 (word x_pos,word y_pos,word x_offset,word y_offset,word width,word end_y_pos,byte transp_color,word image_width,byte * buffer);
void Display_brush_wide2 (byte * brush, word x_pos,word y_pos,word x_offset,word y_offset,word width,word height,byte transp_color,word brush_width);
void Display_line_on_screen_fast_wide2 (word x_pos,word y_pos,word width,byte * line);

View File

@ -28,14 +28,17 @@
#include "errors.h" #include "errors.h"
#include "misc.h" #include "misc.h"
// Mise à jour minimaliste en nombre de pixels // Update method that does a large number of small rectangles, aiming
// for a minimum number of total pixels updated.
#define UPDATE_METHOD_MULTI_RECTANGLE 1 #define UPDATE_METHOD_MULTI_RECTANGLE 1
// Mise à jour intermédiaire, par rectangle inclusif. // Intermediate update method, does only one update with the smallest
// rectangle that includes all modified pixels.
#define UPDATE_METHOD_CUMULATED 2 #define UPDATE_METHOD_CUMULATED 2
// Mise à jour totale, pour les plate-formes qui imposent un Vsync à chaque mise à jour écran. // Total screen update, for platforms that impose a Vsync on each SDL update.
#define UPDATE_METHOD_FULL_PAGE 3 #define UPDATE_METHOD_FULL_PAGE 3
// UPDATE_METHOD peut être fixé depuis le makefile, sinon c'est ici: // UPDATE_METHOD can be set from makefile, otherwise it's selected here
// depending on the platform :
#ifndef UPDATE_METHOD #ifndef UPDATE_METHOD
#if defined(__macosx__) || defined(__FreeBSD__) #if defined(__macosx__) || defined(__FreeBSD__)
#define UPDATE_METHOD UPDATE_METHOD_FULL_PAGE #define UPDATE_METHOD UPDATE_METHOD_FULL_PAGE
@ -44,13 +47,13 @@
#endif #endif
#endif #endif
/// Sets the new screen/window dimensions.
void Set_mode_SDL(int *width, int *height, int fullscreen) void Set_mode_SDL(int *width, int *height, int fullscreen)
/* On règle la résolution de l'écran */
{ {
Screen_SDL=SDL_SetVideoMode(*width,*height,8,(fullscreen?SDL_FULLSCREEN:0)|SDL_RESIZABLE); Screen_SDL=SDL_SetVideoMode(*width,*height,8,(fullscreen?SDL_FULLSCREEN:0)|SDL_RESIZABLE);
if(Screen_SDL != NULL) if(Screen_SDL != NULL)
{ {
// Vérification du mode obtenu (ce n'est pas toujours celui demandé) // Check the mode we got, in case it was different from the one we requested.
if (Screen_SDL->w != *width || Screen_SDL->h != *height) if (Screen_SDL->w != *width || Screen_SDL->h != *height)
{ {
DEBUG("Error: Got a different video mode than the requested one!",0); DEBUG("Error: Got a different video mode than the requested one!",0);
@ -62,7 +65,7 @@ void Set_mode_SDL(int *width, int *height, int fullscreen)
else else
DEBUG("Error: Unable to change video mode!",0); DEBUG("Error: Unable to change video mode!",0);
SDL_ShowCursor(0); // Cache le curseur SDL, on le gère en soft SDL_ShowCursor(0); // Hide the SDL mouse cursor, we use our own
} }
#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED) #if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
@ -79,7 +82,7 @@ short Max_Y=10000;
void Flush_update(void) void Flush_update(void)
{ {
#if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE) #if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
// Mise à jour de la totalité de l'écran // Do a full screen update
if (update_is_required) if (update_is_required)
{ {
SDL_UpdateRect(Screen_SDL, 0, 0, 0, 0); SDL_UpdateRect(Screen_SDL, 0, 0, 0, 0);
@ -89,7 +92,7 @@ void Flush_update(void)
#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED) #if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
if (Min_X>=Max_X || Min_Y>=Max_Y) if (Min_X>=Max_X || Min_Y>=Max_Y)
{ {
; // Rien a faire ; // Nothing to do
} }
else else
{ {
@ -137,9 +140,10 @@ void Update_rect(short x, short y, unsigned short width, unsigned short height)
} }
// Convertit une SDL_Surface (couleurs indexées ou RGB) en tableau de bytes (couleurs indexées) // Converts a SDL_Surface (indexed colors or RGB) into an array of bytes
// Si on passe NULL comme destination, elle est allouée par malloc(). Sinon, // (indexed colors).
// attention aux dimensions! // If dest is NULL, it's allocated by malloc(). Otherwise, be sure to
// pass a buffer of the right dimensions.
byte * Surface_to_bytefield(SDL_Surface *source, byte * dest) byte * Surface_to_bytefield(SDL_Surface *source, byte * dest)
{ {
byte *src; byte *src;
@ -171,7 +175,7 @@ byte * Surface_to_bytefield(SDL_Surface *source, byte * dest)
} }
// Convertit un index de palette en couleur RGB 24 bits /// Gets the RGB 24-bit color currently associated with a palette index.
SDL_Color Color_to_SDL_color(byte index) SDL_Color Color_to_SDL_color(byte index)
{ {
SDL_Color color; SDL_Color color;
@ -182,9 +186,50 @@ SDL_Color Color_to_SDL_color(byte index)
return color; return color;
} }
// Lecture d'un pixel pour une surface SDL. // Reads a pixel in a SDL surface.
// Attention, ne fonctionne que pour les surfaces 8-bit // Warning, this is only suitable for 8-bit surfaces.
byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y) byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y)
{ {
return ((byte *)(bmp->pixels))[(y*bmp->pitch+x)]; return ((byte *)(bmp->pixels))[(y*bmp->pitch+x)];
} }
void Clear_screen(byte color)
{
memset(Screen_SDL->pixels,color,Screen_SDL->pitch*Screen_SDL->h);
Update_rect(0,0,0,0);
}
void Clear_border(byte color)
{
int width;
int height;
// This function can be called before the graphics mode is set.
// Nothing to do then.
if (!Screen_SDL)
return;
width = Screen_SDL->w - Screen_width*Pixel_width;
height = Screen_SDL->h - Screen_height*Pixel_height;
if (width)
{
SDL_Rect r;
r.x=Screen_SDL->w - width;
r.y=0;
r.h=Screen_SDL->h;
r.w=width;
SDL_FillRect(Screen_SDL,&r,color);
SDL_UpdateRect(Screen_SDL, r.x, r.y, r.w, r.h);
}
if (height)
{
SDL_Rect r;
r.x=0;
r.y=Screen_SDL->h - height;
r.h=height;
r.w=Screen_SDL->w - height;
SDL_FillRect(Screen_SDL,&r,color);
SDL_UpdateRect(Screen_SDL, r.x, r.y, r.w, r.h);
}
}

View File

@ -31,15 +31,30 @@
#include <SDL.h> #include <SDL.h>
#include "struct.h" #include "struct.h"
void Set_mode_SDL(int *,int *,int); ///
/// This is the number of bytes in a video line for the current mode.
/// On many platforms it will be the video mode's width (in pixels), rounded up
/// to be a multiple of 4.
#define VIDEO_LINE_WIDTH (Screen_SDL->pitch)
SDL_Rect ** List_SDL_video_modes; void Set_mode_SDL(int *,int *,int);
byte* Screen_pixels;
void Update_rect(short x, short y, unsigned short width, unsigned short height); SDL_Rect ** List_SDL_video_modes;
void Flush_update(void); byte* Screen_pixels;
byte * Surface_to_bytefield(SDL_Surface *source, byte * dest);
SDL_Color Color_to_SDL_color(byte); void Update_rect(short x, short y, unsigned short width, unsigned short height);
byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y); void Flush_update(void);
byte * Surface_to_bytefield(SDL_Surface *source, byte * dest);
SDL_Color Color_to_SDL_color(byte);
byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y);
/// Fills the SDL screen with a given color
void Clear_screen(byte color);
///
/// Clears the parts of screen that are outside of the editing area.
/// There is such area only if the screen mode is not a multiple of the pixel
/// size, eg: 3x3 pixels in 1024x768 leaves 1 column on the right, 0 rows on bottom.
void Clear_border(byte color);
#endif // SDLSCREEN_H_INCLUDED #endif // SDLSCREEN_H_INCLUDED

411
transform.c Normal file
View File

@ -0,0 +1,411 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Yves Rizoud
Copyright 2009 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <stdlib.h>
#include "global.h"
#include "struct.h"
#include "transform.h"
#include "engine.h"
#include "sdlscreen.h"
#include "windows.h"
#include "input.h"
#include "help.h"
#include "misc.h" // Num2str
#include "readline.h"
#include "buttons.h" // Message_out_of_memory()
#include "pages.h" // Backup_with_new_dimensions()
/// Reduces a fraction A/B to its smallest representation. ie (40,60) becomes (2/3)
void Factorize(short *a, short *b)
{
// Method: brute-force.
short factor;
factor=2;
while (factor<=*a && factor<=*b)
{
if (((*a % factor) == 0) && ((*b % factor) == 0))
{
// common factor is found
*a/=factor;
*b/=factor;
// restart
factor=2;
}
else
factor++;
}
}
/// Multiplies original_size by new_ratio/old_ratio, but keeps result in 1-9999 range.
short Compute_dimension(short original_size, short new_ratio, short old_ratio)
{
long amount;
amount = (long)original_size*new_ratio/old_ratio;
if (amount>9999)
return 9999;
else if (amount<1)
return 1;
else
return amount;
}
void Button_Transform_menu(void)
{
enum RESIZE_UNIT {
UNIT_PIXELS = 1,
UNIT_PERCENT = 2,
UNIT_RATIO = 3
};
char buffer[5];
short clicked_button;
const char * unit_label[] = {
"",
"Pixels ",
"Percent",
"Ratio "};
short last_unit_index = -1;
short old_ratio_width;
short old_ratio_height;
short new_ratio_width;
short new_ratio_height;
short new_width=Main_image_width;
short new_height=Main_image_height;
byte need_display_size = 0;
// Persistent data
static short unit_index = 1; // 1= Pixels, 2= Percent, 3=Ratio
static short ratio_is_locked = 1; // True if X and Y resize should go together
T_Dropdown_button * unit_button;
T_Special_button * input_button[4];
short *input_value[4];
// Set initial ratio
if (unit_index == UNIT_PERCENT)
new_ratio_width=old_ratio_width=new_ratio_height=old_ratio_height=100;
else
new_ratio_width=old_ratio_width=new_ratio_height=old_ratio_height=1;
Open_window(215,165,"Picture transform");
Window_display_frame( 5, 15,205,91);
Window_display_frame( 5,110, 55,49);
Window_display_frame(64,110, 85,49);
Window_set_normal_button(154,140, 54,14,"Cancel",0,1,KEY_ESC); // 1
Print_in_window( 9,114,"Mirror",MC_Dark,MC_Light);
Window_set_normal_button( 17,125, 27,14,"X\035" ,1,1,SDLK_x); // 2
Window_set_normal_button( 17,140, 27,14,"Y\022" ,1,1,SDLK_y); // 3
Print_in_window( 84,114,"Rotate",MC_Dark,MC_Light);
Window_set_normal_button( 69,125, 37,14,"-90°" ,0,1,SDLK_LAST); // 4
Window_set_normal_button(107,125, 37,14,"+90°" ,0,1,SDLK_LAST); // 5
Window_set_normal_button( 69,140, 75,14,"180°" ,0,1,SDLK_LAST); // 6
Print_in_window( 87, 19,"Resize",MC_Dark,MC_Light);
Window_set_normal_button( 80, 86, 60,14,"RESIZE",1,1,SDLK_r); // 7
Print_in_window( 51, 34,"New",MC_Dark,MC_Light);
Print_in_window( 96, 34,"Old",MC_Dark,MC_Light);
Print_in_window( 30, 44,"X:",MC_Dark,MC_Light);
Print_in_window( 30, 59,"Y:",MC_Dark,MC_Light);
Print_in_window( 80, 44,":",MC_Dark,MC_Light);
Print_in_window( 80, 59,":",MC_Dark,MC_Light);
Print_in_window( 44, 75,"Lock proportions",MC_Dark,MC_Light);
Window_set_normal_button( 28, 72, 13,13,ratio_is_locked?"X":" ",0,1,SDLK_l);// 8
unit_button = Window_set_dropdown_button(128,50,69,11,69,unit_label[unit_index],1,0,1,LEFT_SIDE|RIGHT_SIDE);// 9
Window_dropdown_add_item(unit_button,UNIT_PIXELS,unit_label[UNIT_PIXELS]);
Window_dropdown_add_item(unit_button,UNIT_PERCENT,unit_label[UNIT_PERCENT]);
Window_dropdown_add_item(unit_button,UNIT_RATIO,unit_label[UNIT_RATIO]);
input_button[0] = Window_set_input_button(45,43,4); // 10
input_button[1] = Window_set_input_button(89,43,4); // 11
input_button[2] = Window_set_input_button(45,58,4); // 12
input_button[3] = Window_set_input_button(89,58,4); // 13
Update_window_area(0,0,Window_width, Window_height);
Display_cursor();
do
{
// Display the coordinates with the right unit
if (last_unit_index != unit_index)
{
switch(unit_index)
{
case UNIT_PIXELS:
default:
input_value[0]=&new_width;
input_value[1]=&Main_image_width; // Don't worry, it's read-only
input_value[2]=&new_height;
input_value[3]=&Main_image_height; // Don't worry, it's read-only
break;
case UNIT_PERCENT:
case UNIT_RATIO:
input_value[0]=&new_ratio_width;
input_value[1]=&old_ratio_width;
input_value[2]=&new_ratio_height;
input_value[3]=&old_ratio_height;
break;
}
need_display_size=1;
last_unit_index=unit_index;
}
if (need_display_size)
{
short i;
Hide_cursor();
for (i=0;i<4;i++)
{
// "Old" values are not editable, unless the unit is "ratio"
byte color = ((unit_index!=UNIT_RATIO) && (i==1 || i==3)) ? MC_Dark : MC_Black;
Num2str(*(input_value[i]),buffer,4);
Print_in_window_limited(input_button[i]->Pos_X+2,input_button[i]->Pos_Y+2,buffer,input_button[i]->Width/8,color,MC_Light);
}
Display_cursor();
need_display_size=0;
}
clicked_button=Window_clicked_button();
// Contextual help
if (Is_shortcut(Key,0x100+BUTTON_HELP))
{
Key=0;
Window_help(BUTTON_ADJUST, "PICTURE TRANSFORM");
}
else switch(clicked_button)
{
case 9: // Unit
switch(Window_attribute2)
{
case UNIT_PIXELS:
// Do nothing, pixel size was already computed.
break;
case UNIT_PERCENT:
if (unit_index == UNIT_RATIO)
{
// Approximate from current ratio
new_ratio_width = Compute_dimension(new_ratio_width,100,old_ratio_width);
new_ratio_height = Compute_dimension(new_ratio_height,100,old_ratio_height);
old_ratio_width = 100;
old_ratio_height = 100;
// Update pixel dimensions, to match percentage exactly
new_width=Compute_dimension(Main_image_width, new_ratio_width, old_ratio_width);
new_height=Compute_dimension(Main_image_height, new_ratio_height, old_ratio_height);
}
else // unit_index == UNIT_PIXELS
{
// Approximate from current pixel size
new_ratio_width = new_width*100/Main_image_width;
new_ratio_height = new_height*100/Main_image_height;
old_ratio_width = 100;
old_ratio_height = 100;
}
break;
case UNIT_RATIO:
if (unit_index == UNIT_PERCENT)
{
// Compute simplest ratio from current %
Factorize(&new_ratio_width, &old_ratio_width);
Factorize(&new_ratio_height, &old_ratio_height);
}
else // unit_index == UNIT_PIXELS
{
// Compute simplest ratio from current pixel size
new_ratio_width = new_width;
new_ratio_height = new_height;
old_ratio_width = Main_image_width;
old_ratio_height = Main_image_height;
Factorize(&new_ratio_width, &old_ratio_width);
Factorize(&new_ratio_height, &old_ratio_height);
}
break;
}
unit_index = Window_attribute2;
break;
case 8: // Lock proportions
ratio_is_locked = ! ratio_is_locked;
Hide_cursor();
Print_in_window(31,75,(ratio_is_locked)?"X":" ",MC_Black,MC_Light);
Display_cursor();
break;
case 11: // input old width
case 13: // input old height
// "Old" values are not editable, unless the unit is "ratio"
if (unit_index!=UNIT_RATIO)
break;
case 10: // input new width
case 12: // input new height
Num2str(*( input_value[clicked_button-10]),buffer,4);
Hide_cursor();
if (Readline(input_button[clicked_button-10]->Pos_X+2,
input_button[clicked_button-10]->Pos_Y+2,
buffer,
4,
1))
{
// Accept entered value
*(input_value[clicked_button-10])=atoi(buffer);
// 0 is not acceptable size
if (*(input_value[clicked_button-10])==0)
{
*(input_value[clicked_button-10])=1;
}
// Adapt the other coordinate if X and Y are locked
if (ratio_is_locked)
{
if (clicked_button == 10 || clicked_button == 11 )
{
// Get Y value because X changed
if (unit_index == UNIT_PIXELS)
{
new_height=Compute_dimension(Main_image_height, new_width, Main_image_width);
}
else
{
// Copy the whole ratio
new_ratio_height=new_ratio_width;
old_ratio_height=old_ratio_width;
}
}
else // (clicked_button == 12 || clicked_button == 13)
{
// Get X value because Y changed
if (unit_index == UNIT_PIXELS)
{
new_width=Compute_dimension(Main_image_width, new_height, Main_image_height);
}
else
{
// Copy the whole ratio
new_ratio_width=new_ratio_height;
old_ratio_width=old_ratio_height;
}
}
}
// Re-compute ratio from size in pixels
if (unit_index == UNIT_PIXELS)
{
//new_width=(long)Main_image_width*new_ratio_width/old_ratio_width;
//new_height=(long)Main_image_height*new_ratio_height/old_ratio_height;
}
else // Re-compute size in pixels from ratio
{
new_width=Compute_dimension(Main_image_width,new_ratio_width,old_ratio_width);
new_height=Compute_dimension(Main_image_height,new_ratio_height,old_ratio_height);
}
need_display_size=1;
}
Display_cursor();
break;
}
}
while (clicked_button<=0 || clicked_button>=8);
Close_window();
// The Scroll operation uses the same button as transformation menu.
if (Current_operation != OPERATION_SCROLL)
Unselect_bouton(BUTTON_ADJUST);
if (clicked_button != 1) // 1 is Cancel
{
short old_width;
short old_height;
// Determine new image dimensions
switch (clicked_button)
{
case 7 : // Resize
// Keep new_width and new_height as entered.
break;
case 2 : // Flip X
case 3 : // Flip Y
case 6 : // 180° Rotation
new_width=Main_image_width;
new_height=Main_image_height;
break;
case 4 : // -90° Rotation
case 5 : // +90° Rotation
new_width=Main_image_height;
new_height=Main_image_width;
break;
}
// Memorize the current dimensions
old_width=Main_image_width;
old_height=Main_image_height;
// Allocate a new page
if (Backup_with_new_dimensions(1,new_width,new_height))
{
// The new image is allocated, the new dimensions are already updated.
Main_image_is_modified=1;
// Process the transformation:
switch(clicked_button)
{
case 2 : // Flip X
memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height);
Flip_X_lowlevel(Main_screen, Main_image_width, Main_image_height);
break;
case 3 : // Flip Y
memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height);
Flip_Y_lowlevel(Main_screen, Main_image_width, Main_image_height);
break;
case 4 : // -90° Rotation
Rotate_270_deg_lowlevel(Screen_backup, Main_screen, old_width, old_height);
break;
case 5 : // +90° Rotation
Rotate_90_deg_lowlevel(Screen_backup, Main_screen, old_width, old_height);
break;
case 6 : // 180° Rotation
memcpy(Main_screen,Screen_backup,Main_image_width*Main_image_height);
Rotate_180_deg_lowlevel(Main_screen, Main_image_width, Main_image_height);
break;
case 7 : // Resize
Rescale(Screen_backup, old_width, old_height, Main_screen, Main_image_width, Main_image_height, 0, 0);
break;
}
Display_all_screen();
}
else
{
Display_cursor();
Message_out_of_memory();
Hide_cursor();
}
}
Display_cursor();
}

29
transform.h Normal file
View File

@ -0,0 +1,29 @@
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Yves Rizoud
Copyright 2009 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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 Grafx2; if not, see <http://www.gnu.org/licenses/> or
write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//////////////////////////////////////////////////////////////////////////////
///@file transform.h
/// Screen and functions for picture transform.
//////////////////////////////////////////////////////////////////////////////
/// Opens and handles the Picture transform screen.
void Button_Transform_menu(void);

View File

@ -2394,6 +2394,7 @@ void Remap_screen_after_menu_colors_change(void)
// On passe la table juste pour ne rafficher que les couleurs modifiées // On passe la table juste pour ne rafficher que les couleurs modifiées
Display_menu_palette_avoiding_window(conversion_table); Display_menu_palette_avoiding_window(conversion_table);
} }
Clear_border(MC_Black);
} }
} }
@ -2529,4 +2530,5 @@ void Compute_optimal_menu_colors(T_Components * palette)
for (i=0; i<ICON_SPRITE_WIDTH; i++) for (i=0; i<ICON_SPRITE_WIDTH; i++)
Remap_pixel(&GFX_icon_sprite[k][j][i]); Remap_pixel(&GFX_icon_sprite[k][j][i]);
} }
Clear_border(MC_Black);
} }

View File

@ -96,4 +96,6 @@ byte Best_color_nonexcluded(byte red,byte green,byte blue);
void Horizontal_XOR_line_zoom(short x_pos, short y_pos, short width); void Horizontal_XOR_line_zoom(short x_pos, short y_pos, short width);
void Vertical_XOR_line_zoom(short x_pos, short y_pos, short height); void Vertical_XOR_line_zoom(short x_pos, short y_pos, short height);
void Change_magnifier_factor(byte factor_index);
#endif #endif