mirror of https://github.com/GNOME/gimp.git
app/paint/gimppaintcore.c applied a patch from Henning Makholm
2003-05-23 Sven Neumann <sven@gimp.org> * app/paint/gimppaintcore.c * app/tools/gimppainttool.c: applied a patch from Henning Makholm <henning@makholm.net> that improves drawing of narrow straight lines by moving the endpoints to pixel centers. Fixes bug #84145.
This commit is contained in:
parent
0fc53e0f54
commit
83a2f4983e
|
@ -1,3 +1,10 @@
|
|||
2003-05-23 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/paint/gimppaintcore.c
|
||||
* app/tools/gimppainttool.c: applied a patch from Henning Makholm
|
||||
<henning@makholm.net> that improves drawing of narrow straight lines
|
||||
by moving the endpoints to pixel centers. Fixes bug #84145.
|
||||
|
||||
2003-05-23 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* app/gui/color-notebook.c (color_notebook_new_internal): don't
|
||||
|
|
|
@ -493,48 +493,65 @@ gimp_paint_core_cleanup (GimpPaintCore *core)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_paint_core_constrain_helper:
|
||||
* @dx: the (fixed) delta-x
|
||||
* @dy: a suggested delta-y
|
||||
*
|
||||
* Returns an adjusted dy' near dy such that the slope (dx,dy') is a
|
||||
* multiple of 15 degrees.
|
||||
**/
|
||||
static gdouble
|
||||
gimp_paint_core_constrain_helper (gdouble dx,
|
||||
gdouble dy)
|
||||
{
|
||||
static gdouble slope[4] = { 0, 0.26795, 0.57735, 1 };
|
||||
static gdouble divider[3] = { 0.13165, 0.41421, 0.76732 };
|
||||
gint i;
|
||||
|
||||
if (dy < 0)
|
||||
return - gimp_paint_core_constrain_helper (dx,-dy);
|
||||
dx = fabs (dx);
|
||||
for (i = 0; i < 3; i ++)
|
||||
if (dy < dx * divider[i])
|
||||
break;
|
||||
dy = dx * slope[i];
|
||||
return dy;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_paint_core_constrain:
|
||||
* @core: the #GimpPaintCore.
|
||||
*
|
||||
* Restricts the (core->last_coords, core->curr_coords) vector to 15
|
||||
* degree steps, possibly changing core->curr_coords
|
||||
*
|
||||
* Restricts the (core->last_coords, core->cur_coords) vector to 15
|
||||
* degree steps, possibly changing core->cur_coords.
|
||||
**/
|
||||
void
|
||||
gimp_paint_core_constrain (GimpPaintCore *core)
|
||||
{
|
||||
static const gint tangens2[6] = { 34, 106, 196, 334, 618, 1944 };
|
||||
static const gint cosinus[7] = { 256, 247, 222, 181, 128, 66, 0 };
|
||||
|
||||
gint dx, dy, i, radius, frac;
|
||||
gdouble dx, dy;
|
||||
|
||||
g_return_if_fail (GIMP_IS_PAINT_CORE (core));
|
||||
|
||||
dx = core->cur_coords.x - core->last_coords.x;
|
||||
dy = core->cur_coords.y - core->last_coords.y;
|
||||
|
||||
if (dy)
|
||||
{
|
||||
radius = sqrt (SQR (dx) + SQR (dy));
|
||||
frac = abs ((dx << 8) / dy);
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (frac < tangens2[i])
|
||||
break;
|
||||
}
|
||||
|
||||
dx = (dx > 0 ?
|
||||
(cosinus[6-i] * radius) >> 8 :
|
||||
- ((cosinus[6-i] * radius) >> 8));
|
||||
|
||||
dy = (dy > 0 ?
|
||||
(cosinus[i] * radius) >> 8 :
|
||||
- ((cosinus[i] * radius) >> 8));
|
||||
}
|
||||
|
||||
core->cur_coords.x = core->last_coords.x + dx;
|
||||
core->cur_coords.y = core->last_coords.y + dy;
|
||||
/* This algorithm changes only one of dx and dy, and does not try
|
||||
* to constrain the resulting dx and dy to integers. This gives
|
||||
* at least two benefits:
|
||||
* 1. gimp_paint_core_constrain is idempotent, even if followed by
|
||||
* a rounding operation.
|
||||
* 2. For any two lines with the same starting-point and ideal
|
||||
* 15-degree direction, the points plotted by
|
||||
* gimp_paint_core_interpolate for the shorter line will always
|
||||
* be a superset of those plotted for the longer line.
|
||||
*/
|
||||
if (fabs(dx) > fabs(dy))
|
||||
core->cur_coords.y = core->last_coords.y +
|
||||
gimp_paint_core_constrain_helper (dx,dy);
|
||||
else
|
||||
core->cur_coords.x = core->last_coords.x +
|
||||
gimp_paint_core_constrain_helper (dy,dx);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -235,6 +235,31 @@ gimp_paint_tool_control (GimpTool *tool,
|
|||
GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_paint_tool_round_line:
|
||||
* @core: the #GimpPaintCore
|
||||
* @state: the modifier state
|
||||
*
|
||||
* Adjusts core->last_coords and core_cur_coords in preparation to
|
||||
* drawing a straight line. The rounding of the slope to 15 degree
|
||||
* steps if ctrl is pressed happens, as does rounding the start and
|
||||
* end coordinates (which may be fractional in high zoom modes) to
|
||||
* the center of pixels.
|
||||
**/
|
||||
static void
|
||||
gimp_paint_tool_round_line (GimpPaintCore *core,
|
||||
GdkModifierType state)
|
||||
{
|
||||
core->last_coords.x = floor (core->last_coords.x) + 0.5;
|
||||
core->last_coords.y = floor (core->last_coords.y) + 0.5;
|
||||
core->cur_coords.x = floor (core->cur_coords.x ) + 0.5;
|
||||
core->cur_coords.y = floor (core->cur_coords.y ) + 0.5;
|
||||
|
||||
/* Restrict to multiples of 15 degrees if ctrl is pressed */
|
||||
if (state & GDK_CONTROL_MASK)
|
||||
gimp_paint_core_constrain (core);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_paint_tool_button_press (GimpTool *tool,
|
||||
GimpCoords *coords,
|
||||
|
@ -313,12 +338,7 @@ gimp_paint_tool_button_press (GimpTool *tool,
|
|||
|
||||
core->start_coords = core->last_coords;
|
||||
|
||||
if (state & GDK_CONTROL_MASK)
|
||||
{
|
||||
/* Restrict to multiples of 15 degrees if ctrl is pressed */
|
||||
|
||||
gimp_paint_core_constrain (core);
|
||||
}
|
||||
gimp_paint_tool_round_line (core, state);
|
||||
}
|
||||
|
||||
gimp_tool_control_activate (tool->control);
|
||||
|
@ -532,12 +552,7 @@ gimp_paint_tool_cursor_update (GimpTool *tool,
|
|||
core->cur_coords.x -= off_x;
|
||||
core->cur_coords.y -= off_y;
|
||||
|
||||
if (state & GDK_CONTROL_MASK)
|
||||
{
|
||||
/* Restrict to multiples of 15 degrees if ctrl is pressed */
|
||||
|
||||
gimp_paint_core_constrain (core);
|
||||
}
|
||||
gimp_paint_tool_round_line (core, state);
|
||||
|
||||
dx = core->cur_coords.x - core->last_coords.x;
|
||||
dy = core->cur_coords.y - core->last_coords.y;
|
||||
|
@ -627,8 +642,8 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
|
|||
/* Draw start target */
|
||||
gimp_draw_tool_draw_handle (draw_tool,
|
||||
GIMP_HANDLE_CROSS,
|
||||
floor (core->last_coords.x) + 0.5,
|
||||
floor (core->last_coords.y) + 0.5,
|
||||
core->last_coords.x,
|
||||
core->last_coords.y,
|
||||
TARGET_SIZE,
|
||||
TARGET_SIZE,
|
||||
GTK_ANCHOR_CENTER,
|
||||
|
@ -637,8 +652,8 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
|
|||
/* Draw end target */
|
||||
gimp_draw_tool_draw_handle (draw_tool,
|
||||
GIMP_HANDLE_CROSS,
|
||||
floor (core->cur_coords.x) + 0.5,
|
||||
floor (core->cur_coords.y) + 0.5,
|
||||
core->cur_coords.x,
|
||||
core->cur_coords.y,
|
||||
TARGET_SIZE,
|
||||
TARGET_SIZE,
|
||||
GTK_ANCHOR_CENTER,
|
||||
|
@ -646,10 +661,10 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
|
|||
|
||||
/* Draw the line between the start and end coords */
|
||||
gimp_draw_tool_draw_line (draw_tool,
|
||||
floor (core->last_coords.x) + 0.5,
|
||||
floor (core->last_coords.y) + 0.5,
|
||||
floor (core->cur_coords.x) + 0.5,
|
||||
floor (core->cur_coords.y) + 0.5,
|
||||
core->last_coords.x,
|
||||
core->last_coords.y,
|
||||
core->cur_coords.x,
|
||||
core->cur_coords.y,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -235,6 +235,31 @@ gimp_paint_tool_control (GimpTool *tool,
|
|||
GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_paint_tool_round_line:
|
||||
* @core: the #GimpPaintCore
|
||||
* @state: the modifier state
|
||||
*
|
||||
* Adjusts core->last_coords and core_cur_coords in preparation to
|
||||
* drawing a straight line. The rounding of the slope to 15 degree
|
||||
* steps if ctrl is pressed happens, as does rounding the start and
|
||||
* end coordinates (which may be fractional in high zoom modes) to
|
||||
* the center of pixels.
|
||||
**/
|
||||
static void
|
||||
gimp_paint_tool_round_line (GimpPaintCore *core,
|
||||
GdkModifierType state)
|
||||
{
|
||||
core->last_coords.x = floor (core->last_coords.x) + 0.5;
|
||||
core->last_coords.y = floor (core->last_coords.y) + 0.5;
|
||||
core->cur_coords.x = floor (core->cur_coords.x ) + 0.5;
|
||||
core->cur_coords.y = floor (core->cur_coords.y ) + 0.5;
|
||||
|
||||
/* Restrict to multiples of 15 degrees if ctrl is pressed */
|
||||
if (state & GDK_CONTROL_MASK)
|
||||
gimp_paint_core_constrain (core);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_paint_tool_button_press (GimpTool *tool,
|
||||
GimpCoords *coords,
|
||||
|
@ -313,12 +338,7 @@ gimp_paint_tool_button_press (GimpTool *tool,
|
|||
|
||||
core->start_coords = core->last_coords;
|
||||
|
||||
if (state & GDK_CONTROL_MASK)
|
||||
{
|
||||
/* Restrict to multiples of 15 degrees if ctrl is pressed */
|
||||
|
||||
gimp_paint_core_constrain (core);
|
||||
}
|
||||
gimp_paint_tool_round_line (core, state);
|
||||
}
|
||||
|
||||
gimp_tool_control_activate (tool->control);
|
||||
|
@ -532,12 +552,7 @@ gimp_paint_tool_cursor_update (GimpTool *tool,
|
|||
core->cur_coords.x -= off_x;
|
||||
core->cur_coords.y -= off_y;
|
||||
|
||||
if (state & GDK_CONTROL_MASK)
|
||||
{
|
||||
/* Restrict to multiples of 15 degrees if ctrl is pressed */
|
||||
|
||||
gimp_paint_core_constrain (core);
|
||||
}
|
||||
gimp_paint_tool_round_line (core, state);
|
||||
|
||||
dx = core->cur_coords.x - core->last_coords.x;
|
||||
dy = core->cur_coords.y - core->last_coords.y;
|
||||
|
@ -627,8 +642,8 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
|
|||
/* Draw start target */
|
||||
gimp_draw_tool_draw_handle (draw_tool,
|
||||
GIMP_HANDLE_CROSS,
|
||||
floor (core->last_coords.x) + 0.5,
|
||||
floor (core->last_coords.y) + 0.5,
|
||||
core->last_coords.x,
|
||||
core->last_coords.y,
|
||||
TARGET_SIZE,
|
||||
TARGET_SIZE,
|
||||
GTK_ANCHOR_CENTER,
|
||||
|
@ -637,8 +652,8 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
|
|||
/* Draw end target */
|
||||
gimp_draw_tool_draw_handle (draw_tool,
|
||||
GIMP_HANDLE_CROSS,
|
||||
floor (core->cur_coords.x) + 0.5,
|
||||
floor (core->cur_coords.y) + 0.5,
|
||||
core->cur_coords.x,
|
||||
core->cur_coords.y,
|
||||
TARGET_SIZE,
|
||||
TARGET_SIZE,
|
||||
GTK_ANCHOR_CENTER,
|
||||
|
@ -646,10 +661,10 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
|
|||
|
||||
/* Draw the line between the start and end coords */
|
||||
gimp_draw_tool_draw_line (draw_tool,
|
||||
floor (core->last_coords.x) + 0.5,
|
||||
floor (core->last_coords.y) + 0.5,
|
||||
floor (core->cur_coords.x) + 0.5,
|
||||
floor (core->cur_coords.y) + 0.5,
|
||||
core->last_coords.x,
|
||||
core->last_coords.y,
|
||||
core->cur_coords.x,
|
||||
core->cur_coords.y,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue