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
# 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)

View File

@ -1,6 +1,6 @@
$(OBJDIR)/SFont.o: SFont.c SFont.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 \
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 \
@ -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
$(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 \
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 \
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 \
help.h sdlscreen.h text.h keyboard.h windows.h input.h hotkeys.h \
errors.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 \
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 \
windows.h errors.h misc.h input.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 \
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 \
@ -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 \
windows.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 \
pxwide.h
$(OBJDIR)/pxsimple.o: pxsimple.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 \
pxdouble.h pxwide.h
$(OBJDIR)/pxquad.o: pxquad.c global.h struct.h const.h sdlscreen.h misc.h pxquad.h
$(OBJDIR)/pxsimple.o: pxsimple.c global.h struct.h const.h sdlscreen.h misc.h \
pxsimple.h
$(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h sdlscreen.h misc.h
$(OBJDIR)/readini.o: readini.c const.h global.h struct.h misc.h
$(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h sdlscreen.h misc.h pxtall.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 \
sdlscreen.h readline.h windows.h input.h
$(OBJDIR)/realpath.o: realpath.c
$(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 \
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 \
readline.h help.h sdlscreen.h windows.h input.h
$(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h windows.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 \
special.h
$(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.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)/windows.o: windows.c windows.h struct.h const.h global.h graph.h engine.h \
misc.h sdlscreen.h errors.h

283
brush.c
View File

@ -718,7 +718,7 @@ void Rotate_90_deg()
new_brush=(byte *)malloc(((long)Brush_height)*Brush_width);
if (new_brush)
{
Rotate_90_deg_lowlevel(Brush,new_brush);
Rotate_90_deg_lowlevel(Brush,new_brush,Brush_width,Brush_height);
free(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)
{
int offset,line,column;
byte * new_brush;
int new_brush_width; // Width 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;
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:
// Compute new brush dimensions
if ((new_brush_width=x1-x2)<0)
{
x_flipped=1;
new_brush_width=-new_brush_width;
}
new_brush_width++;
if ((new_brush_height=y1-y2)<0)
{
y_flipped=1;
new_brush_height=-new_brush_height;
}
new_brush_height++;
// Calcul des anciennes dimensions de la brosse:
// 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
// Free some memory
free(Smear_brush);
if ((new_brush=((byte *)malloc(new_brush_width*new_brush_height))))
{
offset=0;
// 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;
}
Rescale(Brush, Brush_width, Brush_height, new_brush, new_brush_width, new_brush_height, x2<x1, y2<y1);
free(Brush);
Brush=new_brush;
@ -1248,7 +1205,7 @@ void Stretch_brush(short x1, short y1, short x2, short y2)
}
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
// normalement la place pour elle puisque rien d'autre n'a pu être alloué
// 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);
}
/// 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 ---------------------------

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.
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);
/*!

View File

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

View File

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

View File

@ -106,7 +106,7 @@ void Restore_effects(void)
char * Menu_tooltip[NB_BUTTONS]=
{
"Paintbrush choice ",
"Adjust picture / Effects",
"Adjust / Transform menu ",
"Freehand draw. / Toggle ",
"Splines / Toggle ",
"Lines / Toggle ",
@ -407,6 +407,10 @@ void Unselect_button(int btn_number,byte click)
&& (!(Main_magnifier_mode && (b==BUTTON_MAGNIFIER))) )
// Alors on désenclenche le bouton
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:
for (b=0; b<NB_BUTTONS; b++)
// S'il est de la męme famille
@ -698,13 +702,13 @@ void Main_handler(void)
break;
case SPECIAL_FLIP_X : // Flip X
Hide_cursor();
Flip_X_lowlevel();
Flip_X_lowlevel(Brush, Brush_width, Brush_height);
Display_cursor();
Key=0;
break;
case SPECIAL_FLIP_Y : // Flip Y
Hide_cursor();
Flip_Y_lowlevel();
Flip_Y_lowlevel(Brush, Brush_width, Brush_height);
Display_cursor();
Key=0;
break;
@ -716,14 +720,7 @@ void Main_handler(void)
break;
case SPECIAL_ROTATE_180 : // 180° brush rotation
Hide_cursor();
if (Brush_height&1)
{
// Brush de hauteur impaire
Flip_X_lowlevel();
Flip_Y_lowlevel();
}
else
Rotate_180_deg_lowlevel();
Rotate_180_deg_lowlevel(Brush, Brush_width, Brush_height);
Brush_offset_X=(Brush_width>>1);
Brush_offset_Y=(Brush_height>>1);
Display_cursor();
@ -736,7 +733,9 @@ void Main_handler(void)
Key=0;
break;
case SPECIAL_DISTORT : // Distort brush
Message_not_implemented(); // !!! TEMPORAIRE !!!
Hide_cursor();
Start_operation_stack(OPERATION_DISTORT_BRUSH);
Display_cursor();
Key=0;
break;
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]=
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);
}
// 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 "pxwide.h"
#include "pxdouble.h"
#include "pxtriple.h"
#include "pxwide2.h"
#include "pxtall2.h"
#include "pxquad.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.
// 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)
@ -177,7 +184,6 @@ void Transform_point(short x, short y, float cos_a, float sin_a,
}
//--------------------- Initialisation d'un mode vidéo -----------------------
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_height=2;
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 ||
@ -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 ...
width = (width + 15) & 0xFFFFFFF0;
#else
width = (width + 3 ) & 0xFFFFFFFC;
//width = (width + 3 ) & 0xFFFFFFFC;
#endif
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);
}
Clear_border(MC_Black);
if (screen_changed || pixels_changed)
{
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 ;
Display_brush = Display_brush_double ;
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;
@ -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
// 0s. Elle fait Main_image_width de large.
Main_image_is_modified=1;
// On copie donc maintenant la partie C dans la nouvelle image.
Copy_part_of_image_to_another(
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(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);
// 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);

View File

@ -54,7 +54,7 @@ static const T_Help_table helptable_about[] =
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 ("")
@ -539,7 +539,8 @@ static const T_Help_table helptable_paintbrush[] =
};
static const T_Help_table helptable_adjust[] =
{
HELP_TITLE("ADJUST PICTURE")
HELP_TITLE("ADJUST OR TRANSFORM")
HELP_TITLE(" PICTURE")
HELP_TEXT ("")
HELP_BOLD (" LEFT CLICK")
HELP_LINK ("(Key:%s)",0x100+BUTTON_ADJUST)
@ -558,8 +559,24 @@ static const T_Help_table helptable_adjust[] =
HELP_BOLD (" RIGHT CLICK")
HELP_LINK ("(Key:%s)",0x200+BUTTON_ADJUST)
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[] =
{
@ -1079,7 +1096,15 @@ static const T_Help_table helptable_brush_fx[] =
HELP_TEXT ("because it's the only way for cancelling)")
HELP_TEXT ("")
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_LINK ("- Outline: (Key:%s)",SPECIAL_OUTLINE)
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 "loadsave.h" // Image_emergency_backup
#include "init.h"
#include "transform.h"
// Rechercher la liste et le type des lecteurs de la machine
@ -822,12 +824,11 @@ void Init_buttons(void)
Do_nothing,
FAMILY_INSTANT);
// !!! TEMPORAIRE !!!
Init_button(BUTTON_ADJUST,
0,18,
16,16,
BUTTON_SHAPE_RECTANGLE,
Button_Adjust,Message_not_implemented,
Button_Adjust,Button_Transform_menu,
Do_nothing,
FAMILY_TOOL);
@ -1322,6 +1323,22 @@ void Init_operations(void)
Init_operation(OPERATION_ROTATE_BRUSH,2,5,
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,
Filled_polyform_12_0,1);
Init_operation(OPERATION_POLYBRUSH,2,0,

18
input.c
View File

@ -88,12 +88,25 @@ int Is_shortcut(word Key, word function)
int Move_cursor_with_constraints()
{
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
//menu lorsqu'on est en train de travailler dans l'image
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
if(Menu_Y<=Input_new_mouse_Y)
@ -122,7 +135,7 @@ int Move_cursor_with_constraints()
}
}
}
}
if (bl)
{
SDL_WarpMouse(
@ -130,7 +143,6 @@ int Move_cursor_with_constraints()
Input_new_mouse_Y*Pixel_height
);
}
}
if ((Input_new_mouse_X != Mouse_X) ||
(Input_new_mouse_Y != Mouse_Y) ||
(Input_new_mouse_K != Mouse_K))

22
main.c
View File

@ -79,12 +79,16 @@ static char Gui_skin_file[MAX_PATH_CHARACTERS]= "skins" PATH_SEPARATOR "base.gif
void Display_syntax(void)
{
int mode_index;
printf("Syntax: GFX2 [<arguments>] [<picture>]\n\n");
printf("Syntax: grafx2 [<arguments>] [<picture>]\n\n");
printf("<arguments> can be:]\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/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/wide2 to emulate a video mode with double wide pixels (4x2)\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");
@ -217,6 +221,22 @@ void Analyze_command_line(int argc,char * argv[])
{
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") )
{
// 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);
}
void Rotate_90_deg_lowlevel(byte * source,byte * dest)
void Rotate_90_deg_lowlevel(byte * source, byte * dest, short width, short height)
{
byte* esi;
byte* edi;
word dx,bx,cx;
word x,y;
//ESI = Point haut droit de la source
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--)
for(y=0;y<height;y++)
{
esi = Debut_de_colonne;
// Pout chaque colonne
for(cx=Brush_height;cx>0;cx--)
for(x=0;x<width;x++)
{
*edi = *esi;
esi+=Brush_width;
edi++;
*(dest+height*(width-1-x)+y)=*source;
source++;
}
}
}
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;
}
// Effectue une inversion de la brosse selon une droite horizontale
void Flip_Y_lowlevel(void)
void Flip_Y_lowlevel(byte *src, short width, short height)
{
// ESI pointe sur la partie haute de la brosse
// EDI sur la partie basse
byte* ESI = Brush ;
byte* EDI = Brush + (Brush_height - 1) *Brush_width;
byte* ESI = src ;
byte* EDI = src + (height - 1) *width;
byte tmp;
word cx;
@ -501,7 +499,7 @@ void Flip_Y_lowlevel(void)
// Il faut inverser les lignes pointées par ESI et
// EDI ("Brush_width" octets en tout)
for(cx = Brush_width;cx>0;cx--)
for(cx = width;cx>0;cx--)
{
tmp = *ESI;
*ESI = *EDI;
@ -514,57 +512,65 @@ void Flip_Y_lowlevel(void)
// ESI pointe déjà sur le début de la ligne suivante
// EDI pointe sur la fin de la ligne en cours, il
// 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(void)
void Flip_X_lowlevel(byte *src, short width, short height)
{
// ESI pointe sur la partie gauche et EDI sur la partie
// droite
byte* ESI = Brush;
byte* EDI = Brush + Brush_width - 1;
byte* ESI = src;
byte* EDI = src + width - 1;
byte* Debut_Ligne;
byte* Fin_Ligne;
byte* line_start;
byte* line_end;
byte tmp;
word cx;
while(ESI<EDI)
{
Debut_Ligne = ESI;
Fin_Ligne = EDI;
line_start = ESI;
line_end = EDI;
// On échange par colonnes
for(cx=Brush_height;cx>0;cx--)
for(cx=height;cx>0;cx--)
{
tmp=*ESI;
*ESI=*EDI;
*EDI=tmp;
EDI+=Brush_width;
ESI+=Brush_width;
EDI+=width;
ESI+=width;
}
// On change de colonne
// ESI > colonne suivante
// EDI > colonne précédente
ESI = Debut_Ligne + 1;
EDI = Fin_Ligne - 1;
ESI = line_start + 1;
EDI = line_end - 1;
}
}
// Faire une rotation de 180º de la brosse
void Rotate_180_deg_lowlevel(void)
// Rotate a pixel buffer 180º on itself.
void Rotate_180_deg_lowlevel(byte *src, short width, short height)
{
// ESI pointe sur la partie supérieure de la brosse
// EDI pointe sur la partie basse
byte* ESI = Brush;
byte* EDI = Brush + Brush_height*Brush_width - 1;
byte* ESI = src;
byte* EDI = src + height*width - 1;
// EDI pointe sur le dernier pixel de la derniere ligne
byte tmp;
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)
{
// 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
// pointe sur la FIN de sa ligne
for(cx=Brush_width;cx>0;cx--)
for(cx=width;cx>0;cx--)
{
tmp = *ESI;
*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)
//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_sieve(word x,word y);
void Flip_Y_lowlevel(void);
void Flip_X_lowlevel(void);
void Rotate_90_deg_lowlevel(byte * source,byte * dest);
void Rotate_180_deg_lowlevel(void);
///
/// Inverts a pixel buffer, according to a horizontal axis.
/// @param src Pointer to the pixel buffer to process.
/// @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 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();
}
/// 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
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;
}
// Simuler l'appui du bouton "Dessin"
// 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();
Return_to_draw_mode();
}
@ -3100,27 +3107,7 @@ void Polybrush_12_8(void)
Brush_offset_Y=(Brush_offset_Y/Snap_height)*Snap_height;
}
// Simuler l'appui du bouton "Dessin"
// 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);
Return_to_draw_mode();
Display_cursor();
}
}
@ -3398,31 +3385,7 @@ void Stretch_brush_2_7(void)
// Et enfin on stocke pour de bon la nouvelle brosse étirée
Stretch_brush(start_x,start_y,computed_x,computed_y);
// Simuler l'appui du bouton "Dessin"
// 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
Return_to_draw_mode();
}
@ -3650,33 +3613,261 @@ void Rotate_brush_2_5(void)
// Et enfin on stocke pour de bon la nouvelle brosse étirée
Rotate_brush(angle);
// Simuler l'appui du bouton "Dessin"
// 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);
Return_to_draw_mode();
}
// Maintenant, il faut réeffacer le curseur parce qu'il sera raffiché en fin
// d'appel à cette action:
///////////////////////////////////////////////////// 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();
// On passe en brosse couleur:
Change_paintbrush_shape(PAINTBRUSH_SHAPE_COLOR_BRUSH);
// 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);
Print_coordinates();
// Inutile de de faire un Wait_end_of_click car c'est fait dans Unselect_button
}
}
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

View File

@ -100,6 +100,16 @@ void Rotate_brush_1_5(void);
void Rotate_brush_0_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
void Polybrush_12_8(void);

View File

@ -36,26 +36,26 @@
void Pixel_double (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * 2 + y * 4 * Screen_width)=color;
*(Screen_pixels + x * 2 + y * 4 * Screen_width + 1)=color;
*(Screen_pixels + x * 2 + (y * 4 + 2 )* Screen_width)=color;
*(Screen_pixels + x * 2 + (y * 4 + 2 )* Screen_width + 1)=color;
*(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;
}
byte Read_pixel_double (word x,word y)
/* 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)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*2;
rectangle.y=start_y*2;
rectangle.w=width*2;
rectangle.h=height*2;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
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;
src++;
dest+=2;
dest+=ZOOMX;
}
// 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
src+=image_width-width;
dest+=Screen_width*4 - width*2;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//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)
{
//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;
for (x=0;x<width*2;x+=2)
*(dest+x+2*Screen_width+1)=*(dest+x+2*Screen_width)=*(dest+x+1)=*(dest+x)=~*(dest+x);
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(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)
{
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--)
{
*dest=*(dest+1)=*(dest+Screen_width*2)=*(dest+Screen_width*2+1)=~*dest;
dest+=Screen_width*4;
*dest=*(dest+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=~*dest;
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)
{
// 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
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
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
src++;
dest+=2;
dest+=ZOOMX;
}
// 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;
}
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)
/* 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
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
@ -197,23 +197,23 @@ void Display_brush_mono_double(word x_pos, word y_pos,
//Pour chaque pixel
{
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
src++;
dest+=2;
dest+=ZOOMX;
}
// On passe à la ligne suivante
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);
}
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)
int y;
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--)
//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
src++;
dest+=2;
dest+=ZOOMX;
}
// On passe à la ligne suivante
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);
}
@ -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)
{
// 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
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
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
src++; dest+=2;
src++; dest+=ZOOMX;
}
// 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;
}
}
@ -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)
{
// 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;
// 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
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];
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);
@ -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. */
/* 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*2+(y_pos*4+2)*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*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)
@ -306,11 +306,11 @@ void Display_line_on_screen_double(word x_pos,word y_pos,word width,byte * line)
{
int x;
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--)
{
*(dest+Screen_width*2+1)=*(dest+Screen_width*2)=*(dest+1)=*dest=*line;
dest+=2;
*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
@ -320,7 +320,7 @@ void Display_transparent_mono_line_on_screen_double(
// Affiche une ligne à l'écran avec une couleur + transparence.
// 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;
// Pour chaque pixel
for(x=0;x<width;x++)
@ -330,13 +330,13 @@ void Display_transparent_mono_line_on_screen_double(
*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=2;
dest+=ZOOMX;
}
}
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(
@ -356,7 +356,7 @@ void Display_part_of_screen_scaled_double(
// 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*/;
x = Main_magnifier_factor;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
@ -366,7 +366,7 @@ void Display_part_of_screen_scaled_double(
);
// On passe à la suivante
y++;
if(y==height/**ZOOMY*/)
if(y==height)
{
Update_rect(Main_X_zoom,0,
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
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);
// TODO: pas clair ici
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);
Display_transparent_line_on_screen_wide(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color);
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)
{
@ -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
// lignes consécutives)
bx = Main_magnifier_factor*ZOOMX;
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
@ -448,7 +447,7 @@ void Display_brush_mono_zoom_double(word x_pos, word y_pos,
// On passe à la ligne suivante
y++;
// 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,
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
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;
// Pour chaque ligne
do{
// TODO a verifier
Display_line_on_screen_fast_double(x_pos,y,
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)
/* 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)
/* 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)
@ -67,7 +67,7 @@ void Display_part_of_screen_simple (word width,word height,word image_width)
// On passe à la ligne suivante
src+=image_width;
dest+=Screen_width;
dest+=VIDEO_LINE_WIDTH;
}
//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)
{
//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;
@ -126,15 +126,15 @@ void Vertical_XOR_line_simple(word x_pos,word y_pos,word height)
byte color;
for (i=y_pos;i<y_pos+height;i++)
{
color=*(Screen_pixels+x_pos+i*Screen_width);
*(Screen_pixels+x_pos+i*Screen_width)=~color;
color=*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH);
*(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)
{
// 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
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
dest = dest + Screen_width - width;
dest = dest + VIDEO_LINE_WIDTH - width;
src = src + brush_width - width;
}
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)
/* 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
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
@ -190,14 +190,14 @@ void Display_brush_mono_simple(word x_pos, word y_pos,
// On passe à la ligne suivante
src+=brush_width-width;
dest+=Screen_width-width;
dest+=VIDEO_LINE_WIDTH-width;
}
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)
{
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)
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
src+=image_width;
dest+=Screen_width;
dest+=VIDEO_LINE_WIDTH;
}
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)
{
// 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
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
dest = dest + Screen_width - width;
dest = dest + VIDEO_LINE_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)
{
// 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;
// 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 + Screen_width - width;
dest = dest + VIDEO_LINE_WIDTH - width;
}
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)
/* 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(
@ -280,7 +280,7 @@ void Display_transparent_mono_line_on_screen_simple(
// Affiche une ligne à l'écran avec une couleur + transparence.
// 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;
// Pour chaque pixel
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)
{
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(
@ -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)
{
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;

View File

@ -30,17 +30,20 @@
#include "pxtall.h"
#include "pxsimple.h"
#define ZOOMX 1
#define ZOOMY 2
void Pixel_tall (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x + y * 2 * Screen_width)=color;
*(Screen_pixels + x + (y * 2 + 1) * Screen_width)=color;
*(Screen_pixels + x + y*ZOOMY*VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x + (y*ZOOMY+1)*VIDEO_LINE_WIDTH)=color;
}
byte Read_pixel_tall (word x,word y)
/* 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)
@ -48,9 +51,9 @@ void Block_tall (word start_x,word start_y,word width,word height,byte color)
{
SDL_Rect rectangle;
rectangle.x=start_x;
rectangle.y=start_y*2;
rectangle.y=start_y*ZOOMY;
rectangle.w=width;
rectangle.h=height*2;
rectangle.h=height*ZOOMY;
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
memcpy(dest,src,width);
dest+=Screen_width;
dest+=VIDEO_LINE_WIDTH;
memcpy(dest,src,width);
// On passe à la ligne suivante
src+=image_width;
dest+=Screen_width;
dest+=VIDEO_LINE_WIDTH;
}
//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)
{
//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;
for (x=0;x<width;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++)
*(dest+x)=~*(dest+x);
}
@ -132,17 +135,17 @@ void Vertical_XOR_line_tall(word x_pos,word y_pos,word height)
{
int i;
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);
*(Screen_pixels+x_pos+i*Screen_width)=~color;
color=*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH);
*(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)
{
// 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
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)
{
*dest = *src;
*(dest+Screen_width) = *src;
*(dest+VIDEO_LINE_WIDTH) = *src;
}
// 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
dest = dest + 2 * Screen_width - width;
dest = dest + ZOOMY*VIDEO_LINE_WIDTH - width;
src = src + brush_width - width;
}
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)
/* 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
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
@ -192,7 +195,7 @@ void Display_brush_mono_tall(word x_pos, word y_pos,
if (*src!=transp_color)
{
*dest=color;
*(dest+Screen_width)=color;
*(dest+VIDEO_LINE_WIDTH)=color;
}
// 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
src+=brush_width-width;
dest+=2*Screen_width-width;
dest+=ZOOMY*VIDEO_LINE_WIDTH-width;
}
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)
{
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)
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
memcpy(dest,src,width);
dest+=Screen_width;
dest+=VIDEO_LINE_WIDTH;
memcpy(dest,src,width);
// On passe à la ligne suivante
src+=image_width;
dest+=Screen_width;
dest+=VIDEO_LINE_WIDTH;
}
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)
{
// 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
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)
{
*dest = *src;
*(dest+Screen_width) = *src;
*(dest+VIDEO_LINE_WIDTH) = *src;
}
// 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
dest = dest + Screen_width * 2 - width;
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - 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)
{
// 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;
// Pour chaque ligne
for(y=height*2;y>0;y--)
for(y=height*ZOOMY;y>0;y--)
{
// Pour chaque pixel
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 + Screen_width - width;
dest = dest + VIDEO_LINE_WIDTH - width;
}
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)
/* 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*2+1)*Screen_width,line,width);
memcpy(Screen_pixels+x_pos+y_pos*ZOOMY*VIDEO_LINE_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)
{
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(
@ -312,7 +315,7 @@ void Display_part_of_screen_scaled_tall(
// On éclate la ligne
Zoom_a_line(src,buffer,Main_magnifier_factor,width);
// On l'affiche Facteur fois, sur des lignes consécutives
x = Main_magnifier_factor*2;
x = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne
do{
// On affiche la ligne zoomée
@ -322,7 +325,7 @@ void Display_part_of_screen_scaled_tall(
);
// On passe à la suivante
y++;
if(y==height*2)
if(y==height*ZOOMY)
{
Update_rect(Main_X_zoom,0,
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
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);
memcpy(Screen_pixels + (y*2 +1) * Screen_width + x_pos, Screen_pixels + y*2* Screen_width + x_pos, width*Main_magnifier_factor);
Display_transparent_line_on_screen_simple(x_pos,y*ZOOMY,width*Main_magnifier_factor,buffer,transp_color);
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++;
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;
int y=y_pos*2;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
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
// lignes consécutives)
bx = Main_magnifier_factor*2;
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
@ -403,7 +406,7 @@ void Display_brush_mono_zoom_tall(word x_pos, word y_pos,
// On passe à la ligne suivante
y++;
// 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,
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 "pxwide.h"
#define ZOOMX 2
#define ZOOMY 1
void Pixel_wide (word x,word y,byte color)
/* Affiche un pixel de la color aux coords x;y à l'écran */
{
*(Screen_pixels + x * 2 + y * 2 * Screen_width)=color;
*(Screen_pixels + x * 2 + y * 2 * Screen_width + 1)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH)=color;
*(Screen_pixels + x * ZOOMX + y*ZOOMY * VIDEO_LINE_WIDTH + 1)=color;
}
byte Read_pixel_wide (word x,word y)
/* 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)
/* On affiche un rectangle de la couleur donnée */
{
SDL_Rect rectangle;
rectangle.x=start_x*2;
rectangle.y=start_y;
rectangle.w=width*2;
rectangle.h=height;
rectangle.x=start_x*ZOOMX;
rectangle.y=start_y*ZOOMY;
rectangle.w=width*ZOOMX;
rectangle.h=height*ZOOMY;
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;
src++;
dest+=2;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=(Screen_width - width)*2;
dest+=VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
}
//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)
{
//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;
for (x=0;x<width*2;x+=2)
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+1)=*(dest+x)=~*(dest+x);
}
void Vertical_XOR_line_wide(word x_pos,word y_pos,word height)
{
int i;
byte color;
byte *dest=Screen_pixels+x_pos*2+y_pos*Screen_width*2;
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
color=~*dest;
*dest=color;
*(dest+1)=color;
dest+=Screen_width*2;
*dest=*(dest+1)=~*dest;
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}
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
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
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
src++;
dest+=2;
dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + (Screen_width - width)*2;
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
src = src + brush_width - width;
}
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)
/* 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
byte* src=brush_width*y_offset+x_offset+Brush; // src = adr ds
// la brosse
@ -196,19 +196,19 @@ void Display_brush_mono_wide(word x_pos, word y_pos,
// On passe au pixel suivant
src++;
dest+=2;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=brush_width-width;
dest+=(Screen_width-width)*2;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
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)
{
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)
int y;
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
src++;
dest+=2;
dest+=ZOOMX;
}
// On passe à la ligne suivante
src+=image_width-width;
dest+=(Screen_width-width)*2;
dest+=VIDEO_LINE_WIDTH*ZOOMY-width*ZOOMX;
}
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)
{
// 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
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
src++; dest+=2;
src++; dest+=ZOOMX;
}
// On passe à la ligne suivante
dest = dest + (Screen_width - width)*2;
dest = dest + VIDEO_LINE_WIDTH*ZOOMY - width*ZOOMX;
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)
{
// 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;
// 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--)
{
*(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);
@ -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. */
/* 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)
@ -299,13 +299,11 @@ void Display_line_on_screen_wide(word x_pos,word y_pos,word width,byte * line)
{
int x;
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--)
{
*dest=*line;
dest++;
*dest=*line;
dest++;
*(dest+1)=*dest=*line;
dest+=ZOOMX;
line++;
}
}
@ -315,24 +313,23 @@ void Display_transparent_mono_line_on_screen_wide(
// Affiche une ligne à l'écran avec une couleur + transparence.
// 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;
// Pour chaque pixel
for(x=0;x<width;x++)
{
if (transp_color!=*line)
{
*dest = color;
*(dest+1) = color;
*(dest+1)=*dest=color;
}
line ++; // Pixel suivant
dest+=2;
dest+=ZOOMX;
}
}
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(
@ -350,7 +347,7 @@ void Display_part_of_screen_scaled_wide(
int x;
// 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
x = Main_magnifier_factor;
// 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)
{
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;
// 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)
{
*dest = *src;
*(dest+1) = *src;
*(dest+1) = *dest = *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
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++;
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;
int y=y_pos;
int y=y_pos*ZOOMY;
//Pour chaque ligne à zoomer :
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
// lignes consécutives)
bx = Main_magnifier_factor;
bx = Main_magnifier_factor*ZOOMY;
// Pour chaque ligne écran
do
@ -462,7 +457,7 @@ void Display_brush_mono_zoom_wide(word x_pos, word y_pos,
// On passe à la ligne suivante
y++;
// 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,
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
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;

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 "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
// 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
// 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
// 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
#if defined(__macosx__) || defined(__FreeBSD__)
#define UPDATE_METHOD UPDATE_METHOD_FULL_PAGE
@ -44,13 +47,13 @@
#endif
#endif
/// Sets the new screen/window dimensions.
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);
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)
{
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
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)
@ -79,7 +82,7 @@ short Max_Y=10000;
void Flush_update(void)
{
#if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
// Mise à jour de la totalité de l'écran
// Do a full screen update
if (update_is_required)
{
SDL_UpdateRect(Screen_SDL, 0, 0, 0, 0);
@ -89,7 +92,7 @@ void Flush_update(void)
#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
if (Min_X>=Max_X || Min_Y>=Max_Y)
{
; // Rien a faire
; // Nothing to do
}
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)
// Si on passe NULL comme destination, elle est allouée par malloc(). Sinon,
// attention aux dimensions!
// Converts a SDL_Surface (indexed colors or RGB) into an array of bytes
// (indexed colors).
// 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 *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;
@ -182,9 +186,50 @@ SDL_Color Color_to_SDL_color(byte index)
return color;
}
// Lecture d'un pixel pour une surface SDL.
// Attention, ne fonctionne que pour les surfaces 8-bit
// Reads a pixel in a SDL surface.
// Warning, this is only suitable for 8-bit surfaces.
byte Get_SDL_pixel_8(SDL_Surface *bmp, int x, int y)
{
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,6 +31,12 @@
#include <SDL.h>
#include "struct.h"
///
/// 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)
void Set_mode_SDL(int *,int *,int);
SDL_Rect ** List_SDL_video_modes;
@ -42,4 +48,13 @@
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

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
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++)
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 Vertical_XOR_line_zoom(short x_pos, short y_pos, short height);
void Change_magnifier_factor(byte factor_index);
#endif