Per-stamp sane scaling range enforced. (generally bigger)
This commit is contained in:
parent
41402eca12
commit
34cd0b93cb
2 changed files with 142 additions and 56 deletions
|
|
@ -8,6 +8,10 @@ http://www.newbreedsoftware.com/tuxpaint/
|
||||||
|
|
||||||
|
|
||||||
2004.November.23 (0.9.15)
|
2004.November.23 (0.9.15)
|
||||||
|
* abstracted stamp scaling (prep for large sizes)
|
||||||
|
Per-stamp sane scaling range enforced. (generally bigger)
|
||||||
|
Albert Cahalan <albert@users.sf.net>
|
||||||
|
|
||||||
* simplify strip_trailing_whitespace, now O(n)
|
* simplify strip_trailing_whitespace, now O(n)
|
||||||
Albert Cahalan <albert@users.sf.net>
|
Albert Cahalan <albert@users.sf.net>
|
||||||
|
|
||||||
|
|
|
||||||
194
src/tuxpaint.c
194
src/tuxpaint.c
|
|
@ -55,9 +55,45 @@
|
||||||
#define PROMPTOFFSETX (WINDOW_WIDTH - 640) / 2
|
#define PROMPTOFFSETX (WINDOW_WIDTH - 640) / 2
|
||||||
#define PROMPTOFFSETY (HEIGHTOFFSET / 2)
|
#define PROMPTOFFSETY (HEIGHTOFFSET / 2)
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
// hide all scale-related values here
|
||||||
|
|
||||||
#define MIN_STAMP_SIZE 25 /* Stamp can only shrink to 25% (1/4) of original */
|
typedef struct scaleparams {
|
||||||
#define MAX_STAMP_SIZE 400 /* Stamp can only grow to 400% (4 times) original */
|
unsigned numer, denom;
|
||||||
|
} scaleparams;
|
||||||
|
static scaleparams scaletable[] = {
|
||||||
|
{ 1, 16}, // 0.0625
|
||||||
|
{ 3, 32}, // 0.09375
|
||||||
|
{ 1, 8}, // 0.125
|
||||||
|
{ 3, 16}, // 0.1875
|
||||||
|
{ 1, 4}, // 0.25
|
||||||
|
{ 3, 8}, // 0.375
|
||||||
|
{ 1, 2}, // 0.5
|
||||||
|
{ 3, 4}, // 0.75
|
||||||
|
{ 1, 1}, // 1
|
||||||
|
{ 3, 2}, // 1.5
|
||||||
|
{ 2, 1}, // 2
|
||||||
|
{ 3, 1}, // 3
|
||||||
|
{ 4, 1}, // 4
|
||||||
|
{ 6, 1}, // 6
|
||||||
|
{ 8, 1}, // 8
|
||||||
|
{ 12, 1}, // 12
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HARD_MIN_STAMP_SIZE 0 // bottom of scaletable
|
||||||
|
#define HARD_MAX_STAMP_SIZE (sizeof scaletable / sizeof scaletable[0] - 1)
|
||||||
|
|
||||||
|
#define MIN_STAMP_SIZE (state_stamps[cur_stamp]->min)
|
||||||
|
#define MAX_STAMP_SIZE (state_stamps[cur_stamp]->max)
|
||||||
|
|
||||||
|
#define CAN_USE_HQ4X (scaletable[state_stamps[cur_stamp]->size] == (scaleparams){4,1})
|
||||||
|
// to scale some offset, in pixels, like the current stamp is scaled
|
||||||
|
#define SCALE_LIKE_STAMP(x) ( ((x) * scaletable[state_stamps[cur_stamp]->size].numer + scaletable[state_stamps[cur_stamp]->size].denom-1) / scaletable[state_stamps[cur_stamp]->size].denom )
|
||||||
|
// pixel dimensions of the current stamp, as scaled
|
||||||
|
#define CUR_STAMP_W SCALE_LIKE_STAMP(img_stamps[cur_stamp]->w)
|
||||||
|
#define CUR_STAMP_H SCALE_LIKE_STAMP(img_stamps[cur_stamp]->h)
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
// #define MAX_FILES 2048 /* Max. # of files in a dir. to worry about... */
|
// #define MAX_FILES 2048 /* Max. # of files in a dir. to worry about... */
|
||||||
|
|
@ -65,7 +101,6 @@
|
||||||
#define REPEAT_SPEED 300 /* Initial repeat speed for scrollbars */
|
#define REPEAT_SPEED 300 /* Initial repeat speed for scrollbars */
|
||||||
#define CURSOR_BLINK_SPEED 500 /* Initial repeat speed for cursor */
|
#define CURSOR_BLINK_SPEED 500 /* Initial repeat speed for cursor */
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -467,13 +502,14 @@ typedef struct info_type {
|
||||||
int mirrorable;
|
int mirrorable;
|
||||||
int flipable;
|
int flipable;
|
||||||
int tintgray;
|
int tintgray;
|
||||||
|
// int min, def, max; // TODO: size range
|
||||||
} info_type;
|
} info_type;
|
||||||
|
|
||||||
|
|
||||||
typedef struct state_type {
|
typedef struct state_type {
|
||||||
int mirrored;
|
int mirrored;
|
||||||
int flipped;
|
int flipped;
|
||||||
int size;
|
unsigned min,size,max;
|
||||||
} state_type;
|
} state_type;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1820,11 +1856,7 @@ static void mainloop(void)
|
||||||
|
|
||||||
if (state_stamps[cur_stamp]->size > MIN_STAMP_SIZE)
|
if (state_stamps[cur_stamp]->size > MIN_STAMP_SIZE)
|
||||||
{
|
{
|
||||||
state_stamps[cur_stamp]->size =
|
state_stamps[cur_stamp]->size--;
|
||||||
state_stamps[cur_stamp]->size / 2;
|
|
||||||
|
|
||||||
if (state_stamps[cur_stamp]->size < MIN_STAMP_SIZE)
|
|
||||||
state_stamps[cur_stamp]->size = MIN_STAMP_SIZE;
|
|
||||||
|
|
||||||
playsound(0, SND_SHRINK, 0);
|
playsound(0, SND_SHRINK, 0);
|
||||||
draw_stamps();
|
draw_stamps();
|
||||||
|
|
@ -1840,11 +1872,7 @@ static void mainloop(void)
|
||||||
|
|
||||||
if (state_stamps[cur_stamp]->size < MAX_STAMP_SIZE)
|
if (state_stamps[cur_stamp]->size < MAX_STAMP_SIZE)
|
||||||
{
|
{
|
||||||
state_stamps[cur_stamp]->size =
|
state_stamps[cur_stamp]->size++;
|
||||||
state_stamps[cur_stamp]->size * 2;
|
|
||||||
|
|
||||||
if (state_stamps[cur_stamp]->size > MAX_STAMP_SIZE)
|
|
||||||
state_stamps[cur_stamp]->size = MAX_STAMP_SIZE;
|
|
||||||
|
|
||||||
playsound(0, SND_GROW, 0);
|
playsound(0, SND_GROW, 0);
|
||||||
draw_stamps();
|
draw_stamps();
|
||||||
|
|
@ -2051,13 +2079,13 @@ static void mainloop(void)
|
||||||
|
|
||||||
stamp_draw(old_x, old_y);
|
stamp_draw(old_x, old_y);
|
||||||
#ifdef LOW_QUALITY_STAMP_OUTLINE
|
#ifdef LOW_QUALITY_STAMP_OUTLINE
|
||||||
rect_xor(old_x - ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100),
|
// the +1 is for rounding, probably needed only one side though
|
||||||
old_y - ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100),
|
rect_xor(old_x - (CUR_STAMP_W+1)/2,
|
||||||
old_x + ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100),
|
old_y - (CUR_STAMP_H+1)/2,
|
||||||
old_y + ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100));
|
old_x + (CUR_STAMP_W+1)/2,
|
||||||
|
old_y + (CUR_STAMP_H+1)/2);
|
||||||
#else
|
#else
|
||||||
stamp_xor(old_x - (img_stamps[cur_stamp]->w / 2),
|
stamp_xor(old_x, old_y);
|
||||||
old_y - (img_stamps[cur_stamp]->h / 2));
|
|
||||||
#endif
|
#endif
|
||||||
playsound(1, SND_STAMP, 1);
|
playsound(1, SND_STAMP, 1);
|
||||||
|
|
||||||
|
|
@ -2765,18 +2793,18 @@ static void mainloop(void)
|
||||||
if (cur_tool == TOOL_STAMP)
|
if (cur_tool == TOOL_STAMP)
|
||||||
{
|
{
|
||||||
#ifndef LOW_QUALITY_STAMP_OUTLINE
|
#ifndef LOW_QUALITY_STAMP_OUTLINE
|
||||||
stamp_xor(old_x - w / 2, old_y - h / 2);
|
stamp_xor(old_x, old_y);
|
||||||
#else
|
#else
|
||||||
rect_xor(old_x - ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100),
|
rect_xor(old_x - (CUR_STAMP_W+1)/2,
|
||||||
old_y - ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100),
|
old_y - (CUR_STAMP_H+1)/2,
|
||||||
old_x + ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100),
|
old_x + (CUR_STAMP_W+1)/2,
|
||||||
old_y + ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100));
|
old_y + (CUR_STAMP_H+1)/2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
update_screen(old_x - ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100) + 96,
|
update_screen(old_x - (CUR_STAMP_W+1)/2 + 96,
|
||||||
old_y - ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100),
|
old_y - (CUR_STAMP_H+1)/2,
|
||||||
old_x + ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100) + 96,
|
old_x + (CUR_STAMP_W+1)/2 + 96,
|
||||||
old_y + ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100));
|
old_y + (CUR_STAMP_H+1)/2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2794,18 +2822,18 @@ static void mainloop(void)
|
||||||
if (cur_tool == TOOL_STAMP)
|
if (cur_tool == TOOL_STAMP)
|
||||||
{
|
{
|
||||||
#ifndef LOW_QUALITY_STAMP_OUTLINE
|
#ifndef LOW_QUALITY_STAMP_OUTLINE
|
||||||
stamp_xor(new_x - w / 2, new_y - h / 2);
|
stamp_xor(new_x, new_y);
|
||||||
#else
|
#else
|
||||||
rect_xor(new_x - ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100),
|
rect_xor(old_x - (CUR_STAMP_W+1)/2,
|
||||||
new_y - ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100),
|
old_y - (CUR_STAMP_H+1)/2,
|
||||||
new_x + ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100),
|
old_x + (CUR_STAMP_W+1)/2,
|
||||||
new_y + ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100));
|
old_y + (CUR_STAMP_H+1)/2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
update_screen(new_x - ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100) + 96,
|
update_screen(old_x - (CUR_STAMP_W+1)/2 + 96,
|
||||||
new_y - ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100),
|
old_y - (CUR_STAMP_H+1)/2,
|
||||||
new_x + ((img_stamps[cur_stamp]->w / 2) * (state_stamps[cur_stamp]->size) / 100) + 96,
|
old_x + (CUR_STAMP_W+1)/2 + 96,
|
||||||
new_y + ((img_stamps[cur_stamp]->h / 2) * (state_stamps[cur_stamp]->size) / 100));
|
old_y + (CUR_STAMP_H+1)/2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3145,7 +3173,7 @@ static void stamp_draw(int x, int y)
|
||||||
/* Shrink or grow it! */
|
/* Shrink or grow it! */
|
||||||
|
|
||||||
#ifdef USE_HQ4X
|
#ifdef USE_HQ4X
|
||||||
if (state_stamps[cur_stamp]->size == 400)
|
if (CAN_USE_HQ4X)
|
||||||
{
|
{
|
||||||
/* Use high quality 4x filter! */
|
/* Use high quality 4x filter! */
|
||||||
|
|
||||||
|
|
@ -3181,19 +3209,14 @@ static void stamp_draw(int x, int y)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
final_surf = thumbnail(tmp_surf,
|
final_surf = thumbnail(tmp_surf, CUR_STAMP_W, CUR_STAMP_H, 0);
|
||||||
(tmp_surf->w *
|
|
||||||
state_stamps[cur_stamp]->size) / 100,
|
|
||||||
(tmp_surf->h *
|
|
||||||
state_stamps[cur_stamp]->size) / 100,
|
|
||||||
0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Where it will go? */
|
/* Where it will go? */
|
||||||
|
|
||||||
base_x = x - (((tmp_surf->w * state_stamps[cur_stamp]->size) / 100) / 2);
|
base_x = x - (CUR_STAMP_W+1)/2;
|
||||||
base_y = y - (((tmp_surf->h * state_stamps[cur_stamp]->size) / 100) / 2);
|
base_y = y - (CUR_STAMP_H+1)/2;
|
||||||
|
|
||||||
|
|
||||||
/* And blit it! */
|
/* And blit it! */
|
||||||
|
|
@ -3272,10 +3295,10 @@ static void stamp_draw(int x, int y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_canvas(x - (((tmp_surf->w * state_stamps[cur_stamp]->size) / 100) / 2),
|
update_canvas(x - (CUR_STAMP_W+1)/2,
|
||||||
y - (((tmp_surf->h * state_stamps[cur_stamp]->size) / 100) / 2),
|
y - (CUR_STAMP_H+1)/2,
|
||||||
x + (((tmp_surf->w * state_stamps[cur_stamp]->size) / 100) / 2),
|
x + (CUR_STAMP_W+1)/2,
|
||||||
y + (((tmp_surf->h * state_stamps[cur_stamp]->size) / 100) / 2));
|
y + (CUR_STAMP_H+1)/2);
|
||||||
|
|
||||||
/* Free the temporary surfaces */
|
/* Free the temporary surfaces */
|
||||||
|
|
||||||
|
|
@ -5514,6 +5537,28 @@ static void setup(int argc, char * argv[])
|
||||||
free(homedirdir);
|
free(homedirdir);
|
||||||
|
|
||||||
|
|
||||||
|
// The original Tux Paint canvas was 608x472. The canvas can be
|
||||||
|
// other sizes now, but many old stamps are sized for the small
|
||||||
|
// canvas. So, with larger canvases, we must choose a good scale
|
||||||
|
// factor to compensate. As the canvas size grows, the user will
|
||||||
|
// want a balance of "more stamps on the screen" and "stamps not
|
||||||
|
// getting tiny". This will calculate the needed scale factor.
|
||||||
|
unsigned default_stamp_size;
|
||||||
|
{
|
||||||
|
double old_diag = sqrt(608*608+472*472);
|
||||||
|
double new_diag = sqrt(canvas->w*canvas->w+canvas->h*canvas->h);
|
||||||
|
double good_def = sqrt(new_diag/old_diag);
|
||||||
|
double good_log = log(good_def);
|
||||||
|
unsigned defsize = HARD_MAX_STAMP_SIZE;
|
||||||
|
while(defsize>0){
|
||||||
|
double this_err = good_log - log(scaletable[defsize].numer / (double)scaletable[defsize].denom);
|
||||||
|
double next_err = good_log - log(scaletable[defsize-1].numer / (double)scaletable[defsize-1].denom);
|
||||||
|
if( fabs(next_err) > fabs(this_err) ) break;
|
||||||
|
defsize--;
|
||||||
|
}
|
||||||
|
default_stamp_size = defsize;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create stamp thumbnails: */
|
/* Create stamp thumbnails: */
|
||||||
|
|
||||||
for (i = 0; i < num_stamps; i++)
|
for (i = 0; i < num_stamps; i++)
|
||||||
|
|
@ -5561,8 +5606,43 @@ static void setup(int argc, char * argv[])
|
||||||
inf_stamps[i]->mirrorable = 1;
|
inf_stamps[i]->mirrorable = 1;
|
||||||
inf_stamps[i]->tintgray = 1;
|
inf_stamps[i]->tintgray = 1;
|
||||||
inf_stamps[i]->flipable = 1;
|
inf_stamps[i]->flipable = 1;
|
||||||
|
// inf_stamps[i]->min = 0;
|
||||||
|
// inf_stamps[i]->def = 0;
|
||||||
|
// inf_stamps[i]->max = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TODO: convert inf_stamps[i]->min and such to usable data
|
||||||
|
//
|
||||||
|
{
|
||||||
|
int upper = HARD_MAX_STAMP_SIZE;
|
||||||
|
int lower = 0;
|
||||||
|
do{
|
||||||
|
scaleparams *s = &scaletable[upper];
|
||||||
|
int pw, ph; // proposed width and height
|
||||||
|
pw = (img_stamps[i]->w * s->numer + s->denom - 1) / s->denom;
|
||||||
|
ph = (img_stamps[i]->h * s->numer + s->denom - 1) / s->denom;
|
||||||
|
if(pw < canvas->w * 2 && ph < canvas->h * 2) break;
|
||||||
|
}while(--upper);
|
||||||
|
do{
|
||||||
|
scaleparams *s = &scaletable[lower];
|
||||||
|
int pw, ph; // proposed width and height
|
||||||
|
pw = (img_stamps[i]->w * s->numer + s->denom - 1) / s->denom;
|
||||||
|
ph = (img_stamps[i]->h * s->numer + s->denom - 1) / s->denom;
|
||||||
|
if(pw*ph > 20) break;
|
||||||
|
}while(++lower < HARD_MAX_STAMP_SIZE);
|
||||||
|
if(upper<lower){
|
||||||
|
// this, if it ever happens, is very bad
|
||||||
|
upper = (upper+lower)/2;
|
||||||
|
lower = upper;
|
||||||
|
}
|
||||||
|
unsigned mid = default_stamp_size;
|
||||||
|
if(mid > upper) mid = upper;
|
||||||
|
if(mid < lower) mid = lower;
|
||||||
|
state_stamps[i]->min = lower;
|
||||||
|
state_stamps[i]->size = mid;
|
||||||
|
state_stamps[i]->max = upper;
|
||||||
|
}
|
||||||
|
|
||||||
/* If Tux Paint is in mirror-image-by-default mode, mirror, if we can: */
|
/* If Tux Paint is in mirror-image-by-default mode, mirror, if we can: */
|
||||||
|
|
||||||
|
|
@ -5572,7 +5652,6 @@ static void setup(int argc, char * argv[])
|
||||||
state_stamps[i]->mirrored = 0;
|
state_stamps[i]->mirrored = 0;
|
||||||
|
|
||||||
state_stamps[i]->flipped = 0;
|
state_stamps[i]->flipped = 0;
|
||||||
state_stamps[i]->size = 100;
|
|
||||||
|
|
||||||
show_progress_bar();
|
show_progress_bar();
|
||||||
}
|
}
|
||||||
|
|
@ -8390,6 +8469,10 @@ static info_type * loadinfo(const char * const fname)
|
||||||
inf.tintgray = 1;
|
inf.tintgray = 1;
|
||||||
inf.flipable = 1;
|
inf.flipable = 1;
|
||||||
|
|
||||||
|
// inf.min = 0; // dummy values
|
||||||
|
// inf.def = 0;
|
||||||
|
// inf.max = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Load info! */
|
/* Load info! */
|
||||||
|
|
||||||
|
|
@ -11519,7 +11602,6 @@ static void stamp_xor(int x, int y)
|
||||||
Uint8 r, g, b, a, olda, abovea;
|
Uint8 r, g, b, a, olda, abovea;
|
||||||
SDL_Surface * surf_ptr;
|
SDL_Surface * surf_ptr;
|
||||||
|
|
||||||
|
|
||||||
/* Use pre-mirrored stamp image, if applicable: */
|
/* Use pre-mirrored stamp image, if applicable: */
|
||||||
|
|
||||||
if (state_stamps[cur_stamp]->mirrored &&
|
if (state_stamps[cur_stamp]->mirrored &&
|
||||||
|
|
@ -11575,8 +11657,8 @@ static void stamp_xor(int x, int y)
|
||||||
(a < 128 && abovea >= 128) ||
|
(a < 128 && abovea >= 128) ||
|
||||||
(a >= 128 && abovea < 128))
|
(a >= 128 && abovea < 128))
|
||||||
{
|
{
|
||||||
sx = x + 96 + (((xx - (img_stamps[cur_stamp]->w / 2)) * state_stamps[cur_stamp]->size) / 100) + (img_stamps[cur_stamp]->w / 2);
|
sx = x + 96 + SCALE_LIKE_STAMP(xx - img_stamps[cur_stamp]->w / 2);
|
||||||
sy = y + (((yy - (img_stamps[cur_stamp]->h / 2)) * state_stamps[cur_stamp]->size) / 100) + (img_stamps[cur_stamp]->h / 2);
|
sy = y + SCALE_LIKE_STAMP(yy - img_stamps[cur_stamp]->h / 2);
|
||||||
|
|
||||||
clipped_putpixel(screen, sx, sy,
|
clipped_putpixel(screen, sx, sy,
|
||||||
0xFFFFFFFF - getpixel(screen, sx, sy));
|
0xFFFFFFFF - getpixel(screen, sx, sy));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue