mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-11 18:41:05 +00:00
Related to this bug report: https://community.aseprite.org/t/1045
This commit is contained in:
parent
8106aeee44
commit
7c2038e7b5
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -10,6 +11,7 @@
|
||||
|
||||
#include "app/tools/intertwine.h"
|
||||
|
||||
#include "app/tools/controller.h"
|
||||
#include "app/tools/point_shape.h"
|
||||
#include "app/tools/stroke.h"
|
||||
#include "app/tools/symmetry.h"
|
||||
@ -52,12 +54,23 @@ void Intertwine::doPointshapePoint(int x, int y, ToolLoop* loop)
|
||||
|
||||
void Intertwine::doPointshapeHline(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
algo_line(x1, y, x2, y, loop, (AlgoPixel)doPointshapePoint);
|
||||
algo_line_perfect(x1, y, x2, y, loop, (AlgoPixel)doPointshapePoint);
|
||||
}
|
||||
|
||||
void Intertwine::doPointshapeLine(int x1, int y1, int x2, int y2, ToolLoop* loop)
|
||||
{
|
||||
algo_line(x1, y1, x2, y2, loop, (AlgoPixel)doPointshapePoint);
|
||||
if (// When "Snap Angle" in being used or...
|
||||
(int(loop->getModifiers()) & int(ToolLoopModifiers::kSquareAspect)) ||
|
||||
// "Snap to Grid" is enabled
|
||||
(loop->getController()->canSnapToGrid() && loop->getSnapToGrid())) {
|
||||
// We prefer the perfect pixel lines that matches grid tiles
|
||||
algo_line_perfect(x1, y1, x2, y2, loop, (AlgoPixel)doPointshapePoint);
|
||||
}
|
||||
else {
|
||||
// In other case we use the regular algorithm that is useful to
|
||||
// draw continuous lines/strokes.
|
||||
algo_line_continuous(x1, y1, x2, y2, loop, (AlgoPixel)doPointshapePoint);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tools
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -57,15 +58,15 @@ public:
|
||||
int x2 = stroke[c+1].x;
|
||||
int y2 = stroke[c+1].y;
|
||||
|
||||
algo_line(x1, y1, x2, y2, loop, (AlgoPixel)doPointshapePoint);
|
||||
doPointshapeLine(x1, y1, x2, y2, loop);
|
||||
}
|
||||
}
|
||||
|
||||
// Closed shape (polygon outline)
|
||||
if (loop->getFilled()) {
|
||||
algo_line(stroke[0].x, stroke[0].y,
|
||||
stroke[stroke.size()-1].x,
|
||||
stroke[stroke.size()-1].y, loop, (AlgoPixel)doPointshapePoint);
|
||||
doPointshapeLine(stroke[0].x, stroke[0].y,
|
||||
stroke[stroke.size()-1].x,
|
||||
stroke[stroke.size()-1].y, loop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,20 +309,22 @@ public:
|
||||
doPointshapePoint(stroke[c].x, stroke[c].y, loop);
|
||||
}
|
||||
else if (stroke.size()-c == 2) {
|
||||
algo_line(stroke[c].x, stroke[c].y,
|
||||
stroke[c+1].x, stroke[c+1].y, loop, (AlgoPixel)doPointshapePoint);
|
||||
doPointshapeLine(stroke[c].x, stroke[c].y,
|
||||
stroke[c+1].x, stroke[c+1].y, loop);
|
||||
}
|
||||
else if (stroke.size()-c == 3) {
|
||||
algo_spline(stroke[c ].x, stroke[c ].y,
|
||||
stroke[c+1].x, stroke[c+1].y,
|
||||
stroke[c+1].x, stroke[c+1].y,
|
||||
stroke[c+2].x, stroke[c+2].y, loop, (AlgoLine)doPointshapeLine);
|
||||
stroke[c+2].x, stroke[c+2].y, loop,
|
||||
(AlgoLine)doPointshapeLine);
|
||||
}
|
||||
else {
|
||||
algo_spline(stroke[c ].x, stroke[c ].y,
|
||||
stroke[c+1].x, stroke[c+1].y,
|
||||
stroke[c+2].x, stroke[c+2].y,
|
||||
stroke[c+3].x, stroke[c+3].y, loop, (AlgoLine)doPointshapeLine);
|
||||
stroke[c+3].x, stroke[c+3].y, loop,
|
||||
(AlgoLine)doPointshapeLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -363,12 +366,16 @@ public:
|
||||
|
||||
if (stroke.size() == 0)
|
||||
return;
|
||||
else if (stroke.size() == 2) {
|
||||
doPointshapeLine(stroke[0].x, stroke[0].y,
|
||||
stroke[1].x, stroke[1].y, loop);
|
||||
}
|
||||
else if (m_pts.empty() && stroke.size() == 1) {
|
||||
m_pts = stroke;
|
||||
}
|
||||
else {
|
||||
for (int c=0; c+1<stroke.size(); ++c) {
|
||||
algo_line(
|
||||
algo_line_continuous(
|
||||
stroke[c].x,
|
||||
stroke[c].y,
|
||||
stroke[c+1].x,
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -20,7 +21,7 @@
|
||||
|
||||
namespace doc {
|
||||
|
||||
void algo_line(int x1, int y1, int x2, int y2, void* data, AlgoPixel proc)
|
||||
void algo_line_perfect(int x1, int y1, int x2, int y2, void* data, AlgoPixel proc)
|
||||
{
|
||||
bool yaxis;
|
||||
|
||||
@ -64,6 +65,32 @@ void algo_line(int x1, int y1, int x2, int y2, void* data, AlgoPixel proc)
|
||||
}
|
||||
}
|
||||
|
||||
// Line code based on Alois Zingl work released under the
|
||||
// MIT license http://members.chello.at/easyfilter/bresenham.html
|
||||
void algo_line_continuous(int x0, int y0, int x1, int y1, void* data, AlgoPixel proc)
|
||||
{
|
||||
int dx = ABS(x1-x0), sx = (x0 < x1 ? 1: -1);
|
||||
int dy = -ABS(y1-y0), sy = (y0 < y1 ? 1: -1);
|
||||
int err = dx+dy, e2; // error value e_xy
|
||||
|
||||
for (;;) {
|
||||
proc(x0, y0, data);
|
||||
e2 = 2*err;
|
||||
if (e2 >= dy) { // e_xy+e_x > 0
|
||||
if (x0 == x1)
|
||||
break;
|
||||
err += dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 <= dx) { // e_xy+e_y < 0
|
||||
if (y0 == y1)
|
||||
break;
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Additional helper functions for the ellipse-drawing helper function
|
||||
below corresponding to routines in Bresenham's algorithm. */
|
||||
namespace {
|
||||
@ -132,11 +159,11 @@ void algo_ellipse(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc)
|
||||
rx = ABS(x1 - x2);
|
||||
ry = ABS(y1 - y2);
|
||||
|
||||
if (rx == 1) { algo_line(x2, y1, x2, y2, data, proc); rx--; }
|
||||
if (rx == 0) { algo_line(x1, y1, x1, y2, data, proc); return; }
|
||||
if (rx == 1) { algo_line_perfect(x2, y1, x2, y2, data, proc); rx--; }
|
||||
if (rx == 0) { algo_line_perfect(x1, y1, x1, y2, data, proc); return; }
|
||||
|
||||
if (ry == 1) { algo_line(x1, y2, x2, y2, data, proc); ry--; }
|
||||
if (ry == 0) { algo_line(x1, y1, x2, y1, data, proc); return; }
|
||||
if (ry == 1) { algo_line_perfect(x1, y2, x2, y2, data, proc); ry--; }
|
||||
if (ry == 0) { algo_line_perfect(x1, y1, x2, y1, data, proc); return; }
|
||||
|
||||
rx /= 2;
|
||||
ry /= 2;
|
||||
@ -316,7 +343,7 @@ static void draw_quad_rational_bezier_seg(int x0, int y0,
|
||||
}
|
||||
} while (dy <= xy && dx >= xy); // gradient negates -> algorithm fails
|
||||
}
|
||||
algo_line(x0, y0, x2, y2, data, proc); // plot remaining needle to end
|
||||
algo_line_continuous(x0, y0, x2, y2, data, proc); // plot remaining needle to end
|
||||
}
|
||||
|
||||
static void draw_rotated_ellipse_rect(int x0, int y0, int x1, int y1, double zd, void* data, AlgoPixel proc)
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite Document Library
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (c) 2001-2018 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
@ -18,7 +19,22 @@ namespace doc {
|
||||
typedef void (*AlgoPixel)(int x, int y, void *data);
|
||||
typedef void (*AlgoLine)(int x1, int y1, int x2, int y2, void *data);
|
||||
|
||||
void algo_line(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc);
|
||||
// Useful to create lines with more predictable behavior and perfect
|
||||
// pixel block of lines where we'll have a number of lines/rows that
|
||||
// looks the same.
|
||||
//
|
||||
// Related to: https://github.com/aseprite/aseprite/issues/1395
|
||||
void algo_line_perfect(int x1, int y1, int x2, int y2, void* data, AlgoPixel proc);
|
||||
|
||||
// Useful to create continuous lines (you can draw from one point to
|
||||
// another, and continue from that point to another in the same
|
||||
// angle and the line will look continous).
|
||||
//
|
||||
// Related to:
|
||||
// https://community.aseprite.org/t/1045
|
||||
// https://github.com/aseprite/aseprite/issues/1894
|
||||
void algo_line_continuous(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc);
|
||||
|
||||
void algo_ellipse(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc);
|
||||
void algo_ellipsefill(int x1, int y1, int x2, int y2, void *data, AlgoHLine proc);
|
||||
|
||||
|
@ -279,7 +279,7 @@ static void hline_for_image(int x1, int y, int x2, Data* data)
|
||||
void draw_line(Image* image, int x1, int y1, int x2, int y2, color_t color)
|
||||
{
|
||||
Data data = { image, color };
|
||||
algo_line(x1, y1, x2, y2, &data, (AlgoPixel)pixel_for_image);
|
||||
algo_line_continuous(x1, y1, x2, y2, &data, (AlgoPixel)pixel_for_image);
|
||||
}
|
||||
|
||||
void draw_ellipse(Image* image, int x1, int y1, int x2, int y2, color_t color)
|
||||
|
Loading…
x
Reference in New Issue
Block a user