Skip to content

Commit

Permalink
Spray tool now works with small widths and speeds. (fix aseprite#838)
Browse files Browse the repository at this point in the history
  • Loading branch information
Fojar committed Oct 27, 2015
1 parent 41f4fcf commit 7238ebb
Showing 1 changed file with 22 additions and 16 deletions.
38 changes: 22 additions & 16 deletions src/app/tools/point_shapes.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ class FloodFillPointShape : public PointShape {

class SprayPointShape : public PointShape {
BrushPointShape m_subPointShape;
float pixel_remainder = 0;

public:

Expand All @@ -143,31 +144,36 @@ class SprayPointShape : public PointShape {
void transformPoint(ToolLoop* loop, int x, int y) override {
int spray_width = loop->getSprayWidth();
int spray_speed = loop->getSpraySpeed();
int c, u, v, times = (spray_width*spray_width/4) * spray_speed / 100;

// In Windows, rand() has a RAND_MAX too small
#if RAND_MAX <= 0xffff
fixmath::fixed angle, radius;
// The number of pixels to spray is proportional to the area of the brush,
// and we calculate it as a float to handle very low spray rates properly.
float pixels_to_spray = (spray_width * spray_width / 4.0f) * spray_speed / 100.0f;

for (c=0; c<times; c++) {
angle = fixmath::itofix(rand() * 256 / RAND_MAX);
radius = fixmath::itofix(rand() * (spray_width*10) / RAND_MAX) / 10;
u = fixmath::fixtoi(fixmath::fixmul(radius, fixmath::fixcos(angle)));
v = fixmath::fixtoi(fixmath::fixmul(radius, fixmath::fixsin(angle)));
// We add the fractional pixels from last time before computing the total
// number of pixels to paint this time.
pixels_to_spray += pixel_remainder;
int integral_pixels = (int)pixels_to_spray;

// Save any leftover fraction of a pixel for next time.
pixel_remainder = pixels_to_spray - integral_pixels;

m_subPointShape.transformPoint(loop, x+u, y+v);
}
#else
fixmath::fixed angle, radius;

for (c=0; c<times; c++) {
for (int c=0; c<integral_pixels; c++) {

#if RAND_MAX <= 0xffff
// In Windows, rand() has a RAND_MAX too small
angle = fixmath::itofix(rand() * 255 / RAND_MAX);
radius = fixmath::itofix(rand() * spray_width / RAND_MAX);
#else
angle = rand();
radius = rand() % fixmath::itofix(spray_width);
u = fixmath::fixtoi(fixmath::fixmul(radius, fixmath::fixcos(angle)));
v = fixmath::fixtoi(fixmath::fixmul(radius, fixmath::fixsin(angle)));
#endif

int u = fixmath::fixtoi(fixmath::fixmul(radius, fixmath::fixcos(angle)));
int v = fixmath::fixtoi(fixmath::fixmul(radius, fixmath::fixsin(angle)));
m_subPointShape.transformPoint(loop, x+u, y+v);
}
#endif
}

void getModifiedArea(ToolLoop* loop, int x, int y, Rect& area) override {
Expand Down

0 comments on commit 7238ebb

Please sign in to comment.