mirror of https://github.com/GNOME/gimp.git
new utility function which takes GimpZoomType and zooms "scalesrc" and
2003-05-05 Michael Natterer <mitch@gimp.org> * app/display/gimpdisplayshell-scale.[ch] (gimp_display_shell_scale_zoom_fraction): new utility function which takes GimpZoomType and zooms "scalesrc" and "scaledest". (gimp_display_shell_scale_calc_fraction): new utility function which takes an exact double scale factor and calculates "scalesrc" and "scaledest". (gimp_display_shell_scale): use the first. (gimp_display_shell_scale_fit): use the second. * app/tools/gimpmagnifytool.[ch]: use the first to click-zoom and the second to area-zoom. Fixes bug #112115. Removed zoom_in() and zoom_out() utiliy functions. Removed "GimpZoomType op" from the GimpMagnifyTool struct. Cleanup.
This commit is contained in:
parent
5067bec93b
commit
1204865d04
17
ChangeLog
17
ChangeLog
|
@ -1,3 +1,20 @@
|
||||||
|
2003-05-05 Michael Natterer <mitch@gimp.org>
|
||||||
|
|
||||||
|
* app/display/gimpdisplayshell-scale.[ch]
|
||||||
|
(gimp_display_shell_scale_zoom_fraction): new utility function
|
||||||
|
which takes GimpZoomType and zooms "scalesrc" and "scaledest".
|
||||||
|
(gimp_display_shell_scale_calc_fraction): new utility function
|
||||||
|
which takes an exact double scale factor and calculates "scalesrc"
|
||||||
|
and "scaledest".
|
||||||
|
|
||||||
|
(gimp_display_shell_scale): use the first.
|
||||||
|
(gimp_display_shell_scale_fit): use the second.
|
||||||
|
|
||||||
|
* app/tools/gimpmagnifytool.[ch]: use the first to click-zoom and
|
||||||
|
the second to area-zoom. Fixes bug #112115. Removed zoom_in() and
|
||||||
|
zoom_out() utiliy functions. Removed "GimpZoomType op" from the
|
||||||
|
GimpMagnifyTool struct. Cleanup.
|
||||||
|
|
||||||
2003-05-05 Michael Natterer <mitch@gimp.org>
|
2003-05-05 Michael Natterer <mitch@gimp.org>
|
||||||
|
|
||||||
* app/display/gimpdisplayshell.c (gimp_display_shell_snap_coords):
|
* app/display/gimpdisplayshell.c (gimp_display_shell_snap_coords):
|
||||||
|
|
|
@ -62,6 +62,112 @@ static gdouble img2real (GimpDisplayShell *shell,
|
||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
|
|
||||||
|
void
|
||||||
|
gimp_display_shell_scale_zoom_fraction (GimpZoomType zoom_type,
|
||||||
|
gint *scalesrc,
|
||||||
|
gint *scaledest)
|
||||||
|
{
|
||||||
|
gint src, dest;
|
||||||
|
|
||||||
|
g_return_if_fail (scalesrc != NULL);
|
||||||
|
g_return_if_fail (scaledest != NULL);
|
||||||
|
|
||||||
|
src = *scalesrc;
|
||||||
|
dest = *scaledest;
|
||||||
|
|
||||||
|
switch (zoom_type)
|
||||||
|
{
|
||||||
|
case GIMP_ZOOM_IN:
|
||||||
|
if (src > 1)
|
||||||
|
src--;
|
||||||
|
else if (dest < 0xFF)
|
||||||
|
dest++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GIMP_ZOOM_OUT:
|
||||||
|
if (dest > 1)
|
||||||
|
dest--;
|
||||||
|
else if (src < 0xFF)
|
||||||
|
src++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
src = CLAMP (zoom_type % 100, 1, 0xFF);
|
||||||
|
dest = CLAMP (zoom_type / 100, 1, 0xFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*scalesrc = src;
|
||||||
|
*scaledest = dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gimp_display_shell_scale_calc_fraction (gdouble zoom_factor,
|
||||||
|
gint *scalesrc,
|
||||||
|
gint *scaledest)
|
||||||
|
{
|
||||||
|
gdouble zoom_delta;
|
||||||
|
gdouble min_zoom_delta = G_MAXFLOAT;
|
||||||
|
gint best_i = 0xFF;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_return_if_fail (scalesrc != NULL);
|
||||||
|
g_return_if_fail (scaledest != NULL);
|
||||||
|
|
||||||
|
if (zoom_factor < 1.0)
|
||||||
|
{
|
||||||
|
for (i = 0xFF; i > 0; i--)
|
||||||
|
{
|
||||||
|
*scalesrc = i;
|
||||||
|
*scaledest = floor ((gdouble) *scalesrc * zoom_factor);
|
||||||
|
|
||||||
|
if (*scaledest < 0x1)
|
||||||
|
*scaledest = 0x1;
|
||||||
|
|
||||||
|
zoom_delta = ABS ((gdouble) *scaledest / (gdouble) *scalesrc -
|
||||||
|
zoom_factor);
|
||||||
|
|
||||||
|
if (zoom_delta <= min_zoom_delta)
|
||||||
|
{
|
||||||
|
min_zoom_delta = zoom_delta;
|
||||||
|
best_i = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*scalesrc = best_i;
|
||||||
|
*scaledest = floor ((gdouble) *scalesrc * zoom_factor);
|
||||||
|
|
||||||
|
if (*scaledest < 0x1)
|
||||||
|
*scaledest = 0x1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0xFF; i > 0; i--)
|
||||||
|
{
|
||||||
|
*scaledest = i;
|
||||||
|
*scalesrc = ceil ((gdouble) *scaledest / zoom_factor);
|
||||||
|
|
||||||
|
if (*scalesrc < 0x1)
|
||||||
|
*scalesrc = 0x1;
|
||||||
|
|
||||||
|
zoom_delta = ABS ((gdouble) *scaledest / (gdouble) *scalesrc -
|
||||||
|
zoom_factor);
|
||||||
|
|
||||||
|
if (zoom_delta <= min_zoom_delta)
|
||||||
|
{
|
||||||
|
min_zoom_delta = zoom_delta;
|
||||||
|
best_i = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*scaledest = best_i;
|
||||||
|
*scalesrc = ceil ((gdouble) *scaledest / zoom_factor);
|
||||||
|
|
||||||
|
if (*scalesrc < 0x1)
|
||||||
|
*scalesrc = 0x1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gimp_display_shell_scale_setup (GimpDisplayShell *shell)
|
gimp_display_shell_scale_setup (GimpDisplayShell *shell)
|
||||||
{
|
{
|
||||||
|
@ -204,9 +310,8 @@ gimp_display_shell_scale (GimpDisplayShell *shell,
|
||||||
GimpZoomType zoom_type)
|
GimpZoomType zoom_type)
|
||||||
{
|
{
|
||||||
GimpDisplayConfig *config;
|
GimpDisplayConfig *config;
|
||||||
|
gint scalesrc, scaledest;
|
||||||
guchar scalesrc, scaledest;
|
gdouble offset_x, offset_y;
|
||||||
gdouble offset_x, offset_y;
|
|
||||||
|
|
||||||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||||||
|
|
||||||
|
@ -220,40 +325,13 @@ gimp_display_shell_scale (GimpDisplayShell *shell,
|
||||||
offset_x *= ((gdouble) scalesrc / (gdouble) scaledest);
|
offset_x *= ((gdouble) scalesrc / (gdouble) scaledest);
|
||||||
offset_y *= ((gdouble) scalesrc / (gdouble) scaledest);
|
offset_y *= ((gdouble) scalesrc / (gdouble) scaledest);
|
||||||
|
|
||||||
switch (zoom_type)
|
gimp_display_shell_scale_zoom_fraction (zoom_type, &scalesrc, &scaledest);
|
||||||
{
|
|
||||||
case GIMP_ZOOM_IN:
|
|
||||||
if (scalesrc > 1)
|
|
||||||
scalesrc--;
|
|
||||||
else
|
|
||||||
if (scaledest < 0xFF)
|
|
||||||
scaledest++;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GIMP_ZOOM_OUT:
|
|
||||||
if (scaledest > 1)
|
|
||||||
scaledest--;
|
|
||||||
else
|
|
||||||
if (scalesrc < 0xFF)
|
|
||||||
scalesrc++;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
scalesrc = CLAMP (zoom_type % 100, 1, 0xFF);
|
|
||||||
scaledest = CLAMP (zoom_type / 100, 1, 0xFF);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set the offsets */
|
|
||||||
offset_x *= ((gdouble) scaledest / (gdouble) scalesrc);
|
offset_x *= ((gdouble) scaledest / (gdouble) scalesrc);
|
||||||
offset_y *= ((gdouble) scaledest / (gdouble) scalesrc);
|
offset_y *= ((gdouble) scaledest / (gdouble) scalesrc);
|
||||||
|
|
||||||
config = GIMP_DISPLAY_CONFIG (shell->gdisp->gimage->gimp->config);
|
config = GIMP_DISPLAY_CONFIG (shell->gdisp->gimage->gimp->config);
|
||||||
|
|
||||||
gimp_display_shell_scale_by_values (shell,
|
gimp_display_shell_scale_by_values (shell,
|
||||||
(scaledest << 8) + scalesrc,
|
(scaledest << 8) + scalesrc,
|
||||||
(offset_x - (shell->disp_width / 2)),
|
(offset_x - (shell->disp_width / 2)),
|
||||||
|
@ -270,12 +348,8 @@ gimp_display_shell_scale_fit (GimpDisplayShell *shell)
|
||||||
gdouble zoom_x;
|
gdouble zoom_x;
|
||||||
gdouble zoom_y;
|
gdouble zoom_y;
|
||||||
gdouble zoom_factor;
|
gdouble zoom_factor;
|
||||||
gdouble zoom_delta;
|
gint scalesrc;
|
||||||
gdouble min_zoom_delta = G_MAXFLOAT;
|
gint scaledest;
|
||||||
gint scalesrc = 1;
|
|
||||||
gint scaledest = 1;
|
|
||||||
gint i;
|
|
||||||
gint best_i = 0xFF;
|
|
||||||
|
|
||||||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||||||
|
|
||||||
|
@ -298,74 +372,12 @@ gimp_display_shell_scale_fit (GimpDisplayShell *shell)
|
||||||
zoom_y = (gdouble) shell->disp_height / (gdouble) image_height;
|
zoom_y = (gdouble) shell->disp_height / (gdouble) image_height;
|
||||||
|
|
||||||
if ((gdouble) image_height * zoom_x <= (gdouble) shell->disp_height)
|
if ((gdouble) image_height * zoom_x <= (gdouble) shell->disp_height)
|
||||||
{
|
zoom_factor = zoom_x;
|
||||||
zoom_factor = zoom_x;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
zoom_factor = zoom_y;
|
||||||
zoom_factor = zoom_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (zoom_factor < 1.0)
|
gimp_display_shell_scale_calc_fraction (zoom_factor,
|
||||||
{
|
&scalesrc, &scaledest);
|
||||||
for (i = 0xFF; i > 0; i--)
|
|
||||||
{
|
|
||||||
scalesrc = i;
|
|
||||||
scaledest = floor ((gdouble) scalesrc * zoom_factor);
|
|
||||||
|
|
||||||
if (scaledest < 0x1)
|
|
||||||
{
|
|
||||||
scaledest = 0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
zoom_delta = ABS ((gdouble) scaledest / (gdouble) scalesrc -
|
|
||||||
zoom_factor);
|
|
||||||
|
|
||||||
if (zoom_delta <= min_zoom_delta)
|
|
||||||
{
|
|
||||||
min_zoom_delta = zoom_delta;
|
|
||||||
best_i = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scalesrc = best_i;
|
|
||||||
scaledest = floor ((gdouble) scalesrc * zoom_factor);
|
|
||||||
|
|
||||||
if (scaledest < 0x1)
|
|
||||||
{
|
|
||||||
scaledest = 0x1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0xFF; i > 0; i--)
|
|
||||||
{
|
|
||||||
scaledest = i;
|
|
||||||
scalesrc = ceil ((gdouble) scaledest / zoom_factor);
|
|
||||||
|
|
||||||
if (scalesrc < 0x1)
|
|
||||||
{
|
|
||||||
scalesrc = 0x1;
|
|
||||||
}
|
|
||||||
|
|
||||||
zoom_delta = ABS ((gdouble) scaledest / (gdouble) scalesrc -
|
|
||||||
zoom_factor);
|
|
||||||
|
|
||||||
if (zoom_delta <= min_zoom_delta)
|
|
||||||
{
|
|
||||||
min_zoom_delta = zoom_delta;
|
|
||||||
best_i = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scaledest = best_i;
|
|
||||||
scalesrc = ceil ((gdouble) scaledest / zoom_factor);
|
|
||||||
|
|
||||||
if (scalesrc < 0x1)
|
|
||||||
{
|
|
||||||
scalesrc = 0x1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gimp_display_shell_scale_by_values (shell,
|
gimp_display_shell_scale_by_values (shell,
|
||||||
(scaledest << 8) + scalesrc,
|
(scaledest << 8) + scalesrc,
|
||||||
|
|
|
@ -20,6 +20,13 @@
|
||||||
#define __GIMP_DISPLAY_SHELL_SCALE_H__
|
#define __GIMP_DISPLAY_SHELL_SCALE_H__
|
||||||
|
|
||||||
|
|
||||||
|
void gimp_display_shell_scale_zoom_fraction (GimpZoomType zoom_type,
|
||||||
|
gint *scalesrc,
|
||||||
|
gint *scaledest);
|
||||||
|
void gimp_display_shell_scale_calc_fraction (gdouble zoom_factor,
|
||||||
|
gint *scalesrc,
|
||||||
|
gint *scaledest);
|
||||||
|
|
||||||
void gimp_display_shell_scale_setup (GimpDisplayShell *shell);
|
void gimp_display_shell_scale_setup (GimpDisplayShell *shell);
|
||||||
|
|
||||||
void gimp_display_shell_scale_set_dot_for_dot (GimpDisplayShell *gdisp,
|
void gimp_display_shell_scale_set_dot_for_dot (GimpDisplayShell *gdisp,
|
||||||
|
|
|
@ -77,13 +77,6 @@ static void gimp_magnify_tool_cursor_update (GimpTool *tool,
|
||||||
|
|
||||||
static void gimp_magnify_tool_draw (GimpDrawTool *draw_tool);
|
static void gimp_magnify_tool_draw (GimpDrawTool *draw_tool);
|
||||||
|
|
||||||
static void zoom_in (gint *src,
|
|
||||||
gint *dest,
|
|
||||||
gint scale);
|
|
||||||
static void zoom_out (gint *src,
|
|
||||||
gint *dest,
|
|
||||||
gint scale);
|
|
||||||
|
|
||||||
|
|
||||||
static GimpDrawToolClass *parent_class = NULL;
|
static GimpDrawToolClass *parent_class = NULL;
|
||||||
|
|
||||||
|
@ -220,11 +213,6 @@ gimp_magnify_tool_button_release (GimpTool *tool,
|
||||||
GimpMagnifyTool *magnify;
|
GimpMagnifyTool *magnify;
|
||||||
GimpMagnifyOptions *options;
|
GimpMagnifyOptions *options;
|
||||||
GimpDisplayShell *shell;
|
GimpDisplayShell *shell;
|
||||||
gint win_width, win_height;
|
|
||||||
gint width, height;
|
|
||||||
gint scalesrc, scaledest;
|
|
||||||
gint scale;
|
|
||||||
gint x1, y1, x2, y2, w, h;
|
|
||||||
|
|
||||||
magnify = GIMP_MAGNIFY_TOOL (tool);
|
magnify = GIMP_MAGNIFY_TOOL (tool);
|
||||||
options = GIMP_MAGNIFY_OPTIONS (tool->tool_info->tool_options);
|
options = GIMP_MAGNIFY_OPTIONS (tool->tool_info->tool_options);
|
||||||
|
@ -238,8 +226,13 @@ gimp_magnify_tool_button_release (GimpTool *tool,
|
||||||
/* First take care of the case where the user "cancels" the action */
|
/* First take care of the case where the user "cancels" the action */
|
||||||
if (! (state & GDK_BUTTON3_MASK))
|
if (! (state & GDK_BUTTON3_MASK))
|
||||||
{
|
{
|
||||||
x1 = (magnify->w < 0) ? magnify->x + magnify->w : magnify->x;
|
gint x1, y1, x2, y2, w, h;
|
||||||
y1 = (magnify->h < 0) ? magnify->y + magnify->h : magnify->y;
|
gint scalesrc, scaledest;
|
||||||
|
gint win_width, win_height;
|
||||||
|
gint offset_x, offset_y;
|
||||||
|
|
||||||
|
x1 = (magnify->w < 0) ? magnify->x + magnify->w : magnify->x;
|
||||||
|
y1 = (magnify->h < 0) ? magnify->y + magnify->h : magnify->y;
|
||||||
w = (magnify->w < 0) ? -magnify->w : magnify->w;
|
w = (magnify->w < 0) ? -magnify->w : magnify->w;
|
||||||
h = (magnify->h < 0) ? -magnify->h : magnify->h;
|
h = (magnify->h < 0) ? -magnify->h : magnify->h;
|
||||||
x2 = x1 + w;
|
x2 = x1 + w;
|
||||||
|
@ -253,34 +246,47 @@ gimp_magnify_tool_button_release (GimpTool *tool,
|
||||||
|
|
||||||
win_width = shell->disp_width;
|
win_width = shell->disp_width;
|
||||||
win_height = shell->disp_height;
|
win_height = shell->disp_height;
|
||||||
width = (win_width * scalesrc) / scaledest;
|
|
||||||
height = (win_height * scalesrc) / scaledest;
|
|
||||||
|
|
||||||
/* we need to compute the mouse movement in screen coordinates */
|
/* we need to compute the mouse movement in screen coordinates */
|
||||||
if ( (SCALEX (shell, w) < options->threshold) ||
|
if ((SCALEX (shell, w) < options->threshold) ||
|
||||||
(SCALEY (shell, h) < options->threshold) )
|
(SCALEY (shell, h) < options->threshold))
|
||||||
scale = 1;
|
{
|
||||||
|
gimp_display_shell_scale_zoom_fraction (options->zoom_type,
|
||||||
|
&scalesrc, &scaledest);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
scale = MIN ((width / w), (height / h));
|
{
|
||||||
|
gint width, height;
|
||||||
|
gdouble scale;
|
||||||
|
|
||||||
magnify->op = options->zoom_type;
|
width = UNSCALEX (shell, win_width);
|
||||||
|
height = UNSCALEY (shell, win_height);
|
||||||
|
|
||||||
switch (magnify->op)
|
switch (options->zoom_type)
|
||||||
{
|
{
|
||||||
case GIMP_ZOOM_IN:
|
case GIMP_ZOOM_IN:
|
||||||
zoom_in (&scalesrc, &scaledest, scale);
|
scale = MIN (((gdouble) width / (gdouble) w),
|
||||||
break;
|
((gdouble) height / (gdouble) h));
|
||||||
case GIMP_ZOOM_OUT:
|
break;
|
||||||
zoom_out (&scalesrc, &scaledest, scale);
|
|
||||||
break;
|
case GIMP_ZOOM_OUT:
|
||||||
}
|
scale = MIN (((gdouble) w / (gdouble) width),
|
||||||
|
((gdouble) h / (gdouble) height));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale = scale * (gdouble) scaledest / (gdouble) scalesrc;
|
||||||
|
|
||||||
|
gimp_display_shell_scale_calc_fraction (scale,
|
||||||
|
&scalesrc, &scaledest);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset_x = (scaledest * ((x1 + x2) / 2)) / scalesrc - (win_width / 2);
|
||||||
|
offset_y = (scaledest * ((y1 + y2) / 2)) / scalesrc - (win_height / 2);
|
||||||
|
|
||||||
gimp_display_shell_scale_by_values (shell,
|
gimp_display_shell_scale_by_values (shell,
|
||||||
(scaledest << 8) + scalesrc,
|
(scaledest << 8) + scalesrc,
|
||||||
((scaledest * ((x1 + x2) / 2)) / scalesrc -
|
offset_x, offset_y,
|
||||||
(win_width / 2)),
|
|
||||||
((scaledest * ((y1 + y2) / 2)) / scalesrc -
|
|
||||||
(win_height / 2)),
|
|
||||||
options->allow_resize);
|
options->allow_resize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,37 +375,3 @@ gimp_magnify_tool_draw (GimpDrawTool *draw_tool)
|
||||||
magnify->h,
|
magnify->h,
|
||||||
FALSE);
|
FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* magnify utility functions */
|
|
||||||
|
|
||||||
static void
|
|
||||||
zoom_in (gint *src,
|
|
||||||
gint *dest,
|
|
||||||
gint scale)
|
|
||||||
{
|
|
||||||
while (scale--)
|
|
||||||
{
|
|
||||||
if (*src > 1)
|
|
||||||
(*src)--;
|
|
||||||
else
|
|
||||||
if (*dest < 0x10)
|
|
||||||
(*dest)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
zoom_out (gint *src,
|
|
||||||
gint *dest,
|
|
||||||
gint scale)
|
|
||||||
{
|
|
||||||
while (scale--)
|
|
||||||
{
|
|
||||||
if (*dest > 1)
|
|
||||||
(*dest)--;
|
|
||||||
else
|
|
||||||
if (*src < 0x10)
|
|
||||||
(*src)++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -38,10 +38,8 @@ struct _GimpMagnifyTool
|
||||||
{
|
{
|
||||||
GimpDrawTool parent_instance;
|
GimpDrawTool parent_instance;
|
||||||
|
|
||||||
gint x, y; /* upper left hand coordinate */
|
gint x, y; /* upper left hand coordinate */
|
||||||
gint w, h; /* width and height */
|
gint w, h; /* width and height */
|
||||||
|
|
||||||
GimpZoomType op; /* magnify operation */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GimpMagnifyToolClass
|
struct _GimpMagnifyToolClass
|
||||||
|
|
Loading…
Reference in New Issue