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:
parent
6e70b3793b
commit
519a93e067
20
src/image.c
20
src/image.c
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
12
src/nsterm.m
12
src/nsterm.m
@ -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];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user