Skip to content

Commit 4f5bc02

Browse files
committed
Merge pull request matplotlib#2665 from piannucci/retina
MacOSX backend supports 2x DPI images and MathTeX.
2 parents e66039b + 145982e commit 4f5bc02

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

lib/matplotlib/backends/backend_macosx.py

100644100755
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ def draw_gouraud_triangle(self, gc, points, colors, transform):
107107
points = transform.transform(points)
108108
gc.draw_gouraud_triangle(points, colors)
109109

110+
def get_image_magnification(self):
111+
return self.gc.get_image_magnification()
112+
110113
def draw_image(self, gc, x, y, im):
111114
im.flipud_out()
112115
nrows, ncols, data = im.as_rgba_str()
@@ -115,19 +118,21 @@ def draw_image(self, gc, x, y, im):
115118

116119
def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
117120
# todo, handle props, angle, origins
121+
scale = self.gc.get_image_magnification()
118122
size = prop.get_size_in_points()
119123
texmanager = self.get_texmanager()
120124
key = s, size, self.dpi, angle, texmanager.get_font_config()
121125
im = self.texd.get(key) # Not sure what this does; just copied from backend_agg.py
122126
if im is None:
123-
Z = texmanager.get_grey(s, size, self.dpi)
127+
Z = texmanager.get_grey(s, size, self.dpi*scale)
124128
Z = numpy.array(255.0 - Z * 255.0, numpy.uint8)
125129

126130
gc.draw_mathtext(x, y, angle, Z)
127131

128132
def _draw_mathtext(self, gc, x, y, s, prop, angle):
133+
scale = self.gc.get_image_magnification()
129134
ox, oy, width, height, descent, image, used_characters = \
130-
self.mathtext_parser.parse(s, self.dpi, prop)
135+
self.mathtext_parser.parse(s, self.dpi*scale, prop)
131136
gc.draw_mathtext(x, y, angle, 255 - image.as_array())
132137

133138
def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):

src/_macosx.m

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2996,6 +2996,18 @@ static void _data_provider_release(void* info, const void* data, size_t size)
29962996
Py_DECREF(image);
29972997
}
29982998

2999+
/* Consider the drawing origin to be in user coordinates
3000+
* but the image size to be in device coordinates */
3001+
static void draw_image_user_coords_device_size(CGContextRef cr, CGImageRef im,
3002+
float x, float y, npy_intp ncols, npy_intp nrows)
3003+
{
3004+
CGRect dst;
3005+
dst.origin = CGPointMake(x,y);
3006+
dst.size = CGContextConvertSizeToUserSpace(cr, CGSizeMake(ncols,nrows));
3007+
dst.size.height = fabs(dst.size.height); /* believe it or not... */
3008+
CGContextDrawImage(cr, dst, im);
3009+
}
3010+
29993011
static PyObject*
30003012
GraphicsContext_draw_mathtext(GraphicsContext* self, PyObject* args)
30013013
{
@@ -3078,14 +3090,14 @@ static void _data_provider_release(void* info, const void* data, size_t size)
30783090

30793091
if (angle==0.0)
30803092
{
3081-
CGContextDrawImage(cr, CGRectMake(x,y,ncols,nrows), bitmap);
3093+
draw_image_user_coords_device_size(cr, bitmap, x, y, ncols, nrows);
30823094
}
30833095
else
30843096
{
30853097
CGContextSaveGState(cr);
30863098
CGContextTranslateCTM(cr, x, y);
30873099
CGContextRotateCTM(cr, angle*M_PI/180);
3088-
CGContextDrawImage(cr, CGRectMake(0,0,ncols,nrows), bitmap);
3100+
draw_image_user_coords_device_size(cr, bitmap, 0, 0, ncols, nrows);
30893101
CGContextRestoreGState(cr);
30903102
}
30913103
CGImageRelease(bitmap);
@@ -3175,13 +3187,27 @@ static void _data_provider_release(void* info, const void* data, size_t size)
31753187
return NULL;
31763188
}
31773189

3178-
CGContextDrawImage(cr, CGRectMake(x,y,ncols,nrows), bitmap);
3190+
draw_image_user_coords_device_size(cr, bitmap, x, y, ncols, nrows);
31793191
CGImageRelease(bitmap);
31803192

31813193
Py_INCREF(Py_None);
31823194
return Py_None;
31833195
}
31843196

3197+
static PyObject*
3198+
GraphicsContext_get_image_magnification(GraphicsContext* self)
3199+
{
3200+
CGContextRef cr = self->cr;
3201+
if (!cr)
3202+
{
3203+
PyErr_SetString(PyExc_RuntimeError, "CGContextRef is NULL");
3204+
return NULL;
3205+
}
3206+
3207+
CGSize pixelSize = CGContextConvertSizeToDeviceSpace(cr, CGSizeMake(1,1));
3208+
return PyFloat_FromDouble(pixelSize.width);
3209+
}
3210+
31853211

31863212
static PyMethodDef GraphicsContext_methods[] = {
31873213
{"save",
@@ -3294,6 +3320,11 @@ static void _data_provider_release(void* info, const void* data, size_t size)
32943320
METH_VARARGS,
32953321
"Draw an image at (x,y) in the graphics context."
32963322
},
3323+
{"get_image_magnification",
3324+
(PyCFunction)GraphicsContext_get_image_magnification,
3325+
METH_NOARGS,
3326+
"Returns the scale factor between user and device coordinates."
3327+
},
32973328
{NULL} /* Sentinel */
32983329
};
32993330

0 commit comments

Comments
 (0)