1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-12 09:28:24 +00:00

Don't smooth images when scaling up (bug#38394)

* src/image.c (image_set_transform [HAVE_XRENDER]): Use different filter
when scaling up vs scaling down.
* src/nsimage.m (ns_image_set_smoothing):
([EmacsImage setSmoothing:]): New functions.
* src/nsterm.h: Add definitions.
* src/nsterm.m (ns_dumpglyphs_image): Disable smoothing if requested.
This commit is contained in:
Alan Third 2020-08-02 20:43:56 +01:00
parent 6e70b3793b
commit 519a93e067
4 changed files with 44 additions and 3 deletions

View File

@ -259,6 +259,8 @@ cr_put_image_to_cr_data (struct image *img)
cairo_matrix_t matrix;
cairo_pattern_get_matrix (img->cr_data, &matrix);
cairo_pattern_set_matrix (pattern, &matrix);
cairo_pattern_set_filter
(pattern, cairo_pattern_get_filter (img->cr_data));
cairo_pattern_destroy (img->cr_data);
}
cairo_surface_destroy (surface);
@ -2114,6 +2116,15 @@ image_set_transform (struct frame *f, struct image *img)
double rotation = 0.0;
compute_image_rotation (img, &rotation);
# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS
/* We want scale up operations to use a nearest neighbour filter to
show real pixels instead of munging them, but scale down
operations to use a blended filter, to avoid aliasing and the like.
TODO: implement for Windows. */
bool scale_down = (width < img->width) || (height < img->height);
# endif
/* Perform scale transformation. */
matrix3x3 matrix
@ -2225,11 +2236,14 @@ image_set_transform (struct frame *f, struct image *img)
/* Under NS the transform is applied to the drawing surface at
drawing time, so store it for later. */
ns_image_set_transform (img->pixmap, matrix);
ns_image_set_smoothing (img->pixmap, scale_down);
# elif defined USE_CAIRO
cairo_matrix_t cr_matrix = {matrix[0][0], matrix[0][1], matrix[1][0],
matrix[1][1], matrix[2][0], matrix[2][1]};
cairo_pattern_t *pattern = cairo_pattern_create_rgb (0, 0, 0);
cairo_pattern_set_matrix (pattern, &cr_matrix);
cairo_pattern_set_filter (pattern, scale_down
? CAIRO_FILTER_BEST : CAIRO_FILTER_NEAREST);
/* Dummy solid color pattern just to record pattern matrix. */
img->cr_data = pattern;
# elif defined (HAVE_XRENDER)
@ -2246,14 +2260,14 @@ image_set_transform (struct frame *f, struct image *img)
XDoubleToFixed (matrix[1][2]),
XDoubleToFixed (matrix[2][2])}}};
XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture, FilterBest,
0, 0);
XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture,
scale_down ? FilterBest : FilterNearest, 0, 0);
XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat);
if (img->mask_picture)
{
XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->mask_picture,
FilterBest, 0, 0);
scale_down ? FilterBest : FilterNearest, 0, 0);
XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->mask_picture,
&tmat);
}

View File

@ -199,6 +199,12 @@ Updated by Christian Limpach (chris@nice.ch)
[(EmacsImage *)img setTransform:m];
}
void
ns_image_set_smoothing (void *img, bool smooth)
{
[(EmacsImage *)img setSmoothing:smooth];
}
unsigned long
ns_get_pixel (void *img, int x, int y)
{
@ -591,4 +597,10 @@ - (void)setTransform: (double[3][3]) m
[transform setTransformStruct:tm];
}
- (void)setSmoothing: (BOOL) s
{
smoothing = s;
}
@end

View File

@ -640,6 +640,7 @@ typedef id instancetype;
unsigned long xbm_fg;
@public
NSAffineTransform *transform;
BOOL smoothing;
}
+ (instancetype)allocInitFromFile: (Lisp_Object)file;
- (void)dealloc;
@ -658,6 +659,7 @@ typedef id instancetype;
- (Lisp_Object)getMetadata;
- (BOOL)setFrame: (unsigned int) index;
- (void)setTransform: (double[3][3]) m;
- (void)setSmoothing: (BOOL)s;
@end
@ -1200,6 +1202,7 @@ extern int ns_image_width (void *img);
extern int ns_image_height (void *img);
extern void ns_image_set_size (void *img, int width, int height);
extern void ns_image_set_transform (void *img, double m[3][3]);
extern void ns_image_set_smoothing (void *img, bool smooth);
extern unsigned long ns_get_pixel (void *img, int x, int y);
extern void ns_put_pixel (void *img, int x, int y, unsigned long argb);
extern void ns_set_alpha (void *img, int x, int y, unsigned char a);

View File

@ -4043,10 +4043,22 @@ Function modeled after x_draw_glyph_string_box ().
[doTransform concat];
/* Smoothing is the default, so if we don't want smoothing we
have to turn it off. */
if (! img->smoothing)
[[NSGraphicsContext currentContext]
setImageInterpolation:NSImageInterpolationNone];
[img drawInRect:ir fromRect:ir
operation:NSCompositingOperationSourceOver
fraction:1.0 respectFlipped:YES hints:nil];
/* Apparently image interpolation is not reset with
restoreGraphicsState, so we have to manually reset it. */
if (! img->smoothing)
[[NSGraphicsContext currentContext]
setImageInterpolation:NSImageInterpolationDefault];
[[NSGraphicsContext currentContext] restoreGraphicsState];
}