summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2018-10-04 13:39:58 -0700
committerKeith Packard <keithp@keithp.com>2018-10-04 14:22:09 -0700
commit32de520d2161d7f4ff759b563735d865b9e842f4 (patch)
tree7788307ba3d9cf2ea2077a963b23abd9e86acf64
parent5f0a289957ef315e03029b1be57986a8c292f6cf (diff)
Add per-surface DPI value, fetch from X, use to scale fonts.
Fetch the DPI for X from either X resources, or use the screen DPI. For other surfaces, set the dpi value to 72.0. When a font is provided with a size value, that's supposed to be points, not device units. Take that and scale it by the surface DPI. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--src/cairo-5c.h1
-rw-r--r--src/surface.c10
-rw-r--r--src/text.c3
-rw-r--r--src/xlib.c90
4 files changed, 66 insertions, 38 deletions
diff --git a/src/cairo-5c.h b/src/cairo-5c.h
index 784da41..a3a1f09 100644
--- a/src/cairo-5c.h
+++ b/src/cairo-5c.h
@@ -107,6 +107,7 @@ typedef struct _cairo_5c_surface_t {
cairo_surface_t *surface;
double width;
double height;
+ double dpi;
Bool dirty;
Value recv_events;
Bool copied;
diff --git a/src/surface.c b/src/surface.c
index 2d1e44d..3596a46 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -215,6 +215,7 @@ create_window (Value namev, Value wv, Value hv, Value sv)
c5s->copied = False;
c5s->recv_events = Void;
c5s->u.window.gui = NULL;
+ c5s->dpi = 72.0;
if (!cairo_5c_gui_create (c5s, name, width, height, shown))
{
@@ -341,6 +342,7 @@ do_Cairo_Surface_create_similar (Value sv, Value cv, Value wv, Value hv)
c5s->dirty = False;
c5s->copied = False;
c5s->recv_events = Void;
+ c5s->dpi = 72.0;
c5s->surface = cairo_surface_create_similar (c5os->surface,
content,
@@ -430,6 +432,7 @@ do_Cairo_Image_surface_create (Value fv, Value wv, Value hv)
c5s->dirty = False;
c5s->recv_events = Void;
c5s->copied = False;
+ c5s->dpi = 72.0;
c5s->surface = cairo_image_surface_create (format,
width,
@@ -476,6 +479,8 @@ do_Cairo_Image_surface_create_from_png (Value filenamev)
c5s->dirty = False;
c5s->recv_events = Void;
c5s->copied = False;
+ c5s->dpi = 72.0;
+
ret = NewForeign (CairoSurfaceId, c5s,
cairo_surface_foreign_mark, cairo_surface_foreign_free);
@@ -658,6 +663,7 @@ do_Cairo_Pdf_surface_create (Value fnv, Value wv, Value hv)
c5s->dirty = False;
c5s->copied = False;
c5s->recv_events = Void;
+ c5s->dpi = 72.0;
c5s->u.pdf.file = Void;
@@ -692,6 +698,7 @@ do_Cairo_Svg_surface_create (Value fnv, Value wv, Value hv)
c5s->dirty = False;
c5s->copied = False;
c5s->recv_events = Void;
+ c5s->dpi = 72.0;
c5s->u.svg.file = Void;
@@ -726,7 +733,8 @@ do_Cairo_Ps_surface_create (Value fnv, Value wv, Value hv)
c5s->dirty = False;
c5s->copied = False;
c5s->recv_events = Void;
-
+ c5s->dpi = 72.0;
+
c5s->u.ps.file = Void;
c5s->surface = cairo_ps_surface_create (filename, width, height);
diff --git a/src/text.c b/src/text.c
index c5bb649..39cd4ba 100644
--- a/src/text.c
+++ b/src/text.c
@@ -195,13 +195,14 @@ do_Cairo_set_font (Value cv, Value fv)
{
ENTER ();
cairo_5c_t *c5c = cairo_5c_get (cv);
+ cairo_5c_surface_t *c5s = cairo_5c_surface_get(c5c->surface);
cairo_5c_font_t *c5f = cairo_5c_font_find (fv);
if (!c5f)
RETURN (Void);
cairo_set_font_face (c5c->cr, c5f->font_face);
- cairo_set_font_size (c5c->cr, c5f->size);
+ cairo_set_font_size (c5c->cr, c5f->size * c5s->dpi / 72.0);
RETURN(Void);
}
diff --git a/src/xlib.c b/src/xlib.c
index 7e552ef..a4b2270 100644
--- a/src/xlib.c
+++ b/src/xlib.c
@@ -53,6 +53,7 @@ typedef struct _x_global {
int ref_count;
int running;
int pipe[2];
+ double dpi;
pthread_t x_thread;
pthread_mutex_t repaint_mutex;
XContext context;
@@ -145,7 +146,7 @@ set_window_surface (x_global_t *xg, Window wid, cairo_5c_surface_t *c5s)
static void
configure_event (x_global_t *xg, XConfigureEvent *event)
{
- cairo_5c_surface_t *c5s = get_window_surface (xg, event->window);
+ cairo_5c_surface_t *c5s = get_window_surface (xg, event->window);
cairo_5c_gui_t *gui;
if (!c5s)
@@ -169,7 +170,7 @@ expose_event (x_global_t *xg, XExposeEvent *event)
{
cairo_5c_surface_t *c5s = get_window_surface (xg, event->window);
cairo_5c_gui_t *gui;
-
+
if (!c5s)
return;
gui = c5s->u.window.gui;
@@ -191,7 +192,7 @@ expose_event (x_global_t *xg, XExposeEvent *event)
*/
static void
delete_drawing_area (x_global_t *xg, cairo_5c_surface_t *c5s)
-{
+{
cairo_5c_gui_t *gui = c5s->u.window.gui;
if (gui->send_events)
{
@@ -204,7 +205,7 @@ static void
client_message_event (x_global_t *xg, XClientMessageEvent *event)
{
cairo_5c_surface_t *c5s = get_window_surface (xg, event->window);
-
+
if (!c5s)
return;
if (event->message_type == xg->wm_protocols && event->format == 32)
@@ -222,7 +223,7 @@ motion_notify_event (x_global_t *xg, XMotionEvent *event)
{
cairo_5c_surface_t *c5s = get_window_surface (xg, event->window);
cairo_5c_gui_t *gui;
-
+
if (!c5s)
return;
gui = c5s->u.window.gui;
@@ -243,7 +244,7 @@ button_event (x_global_t *xg, XButtonEvent *event)
{
cairo_5c_surface_t *c5s = get_window_surface (xg, event->window);
cairo_5c_gui_t *gui;
-
+
if (!c5s)
return;
gui = c5s->u.window.gui;
@@ -264,7 +265,7 @@ key_event (x_global_t *xg, XKeyEvent *event)
{
cairo_5c_surface_t *c5s = get_window_surface (xg, event->window);
cairo_5c_gui_t *gui;
-
+
if (!c5s)
return;
gui = c5s->u.window.gui;
@@ -290,7 +291,7 @@ focus_change_event (x_global_t *xg, XFocusChangeEvent *event)
{
cairo_5c_surface_t *c5s = get_window_surface (xg, event->window);
cairo_5c_gui_t *gui;
-
+
if (!c5s)
return;
gui = c5s->u.window.gui;
@@ -310,17 +311,17 @@ static void
repaint (cairo_5c_surface_t *c5s, int x, int y, int w, int h)
{
cairo_5c_gui_t *gui = c5s->u.window.gui;
- if (gui->window &&
+ if (gui->window &&
(gui->new_width != c5s->width ||
gui->new_height != c5s->height))
{
allocate_pixmap (c5s);
}
-
+
if (gui->window && gui->pixmap && gui->gc)
{
Display *dpy = gui->global->dpy;
-
+
if (w == 0)
w = c5s->width - x;
if (h == 0)
@@ -336,7 +337,7 @@ static void
_repaint_timeout (x_global_t *xg, int when)
{
x_repaint_t *xr;
-
+
while ((xr = xg->repaint) && xr->when - when <= 0)
{
cairo_5c_surface_t *c5s = xr->c5s;
@@ -383,7 +384,7 @@ x_thread_main (void *closure)
sigaddset (&mask, SIGCHLD);
sigaddset (&mask, SIGINT);
pthread_sigmask (SIG_BLOCK, &mask, NULL);
-
+
fds[0].fd = ConnectionNumber (xg->dpy);
fds[0].events = POLLIN;
fds[1].fd = xg->pipe[0];
@@ -497,18 +498,19 @@ x_global_create (void)
static int been_here = 0;
Display *dpy;
x_global_t *xg;
+ char *dpi_string;
if (!been_here)
{
XInitThreads ();
been_here = 1;
}
-
+
if (x_global)
return x_global;
dpy = XOpenDisplay (NULL);
-
+
if (!dpy)
{
int err = errno;
@@ -518,15 +520,23 @@ x_global_create (void)
FileGetError (err), NewStrString (display_name_arg));
return NULL;
}
-
+
xg = malloc (sizeof (x_global_t));
-
+
xg->ref_count = 0;
xg->dpy = dpy;
xg->running = 1;
xg->repaint = NULL;
+ xg->dpi = 0.0;
+ dpi_string = XGetDefault(dpy, "Xft", "dpi");
+ if (dpi_string) {
+ char *dpi_end;
+ xg->dpi = strtod(dpi_string, &dpi_end);
+ if (dpi_end == dpi_string)
+ xg->dpi = 0.0;
+ }
pipe (xg->pipe);
-
+
pthread_mutex_init(&xg->repaint_mutex, NULL);
pthread_create (&xg->x_thread, 0, x_thread_main, xg);
x_global = xg;
@@ -550,7 +560,7 @@ cairo_5c_gui_create (cairo_5c_surface_t *c5s, char *name, int width, int height,
XWMHints wmHints;
XClassHint classHints;
XSetWindowAttributes attr;
-
+
xg = x_global_create ();
if (aborting)
@@ -561,14 +571,14 @@ cairo_5c_gui_create (cairo_5c_surface_t *c5s, char *name, int width, int height,
dpy = xg->dpy;
screen = DefaultScreen (dpy);
-
+
if (!width)
- width = XDisplayWidth (dpy, screen) / 3;
+ width = DisplayWidth (dpy, screen) / 3;
if (!height)
- height = XDisplayWidth (dpy, screen) / 3;
+ height = DisplayWidth (dpy, screen) / 3;
gui = malloc (sizeof (cairo_5c_gui_t));
-
+
xg->ref_count++;
gui->global = xg;
gui->pixmap = None;
@@ -577,12 +587,12 @@ cairo_5c_gui_create (cairo_5c_surface_t *c5s, char *name, int width, int height,
gui->dirty = 0;
gui->disable = 0;
gui->depth = DefaultDepth (dpy, screen);
-
+
gui->new_width = width;
gui->new_height = height;
-
+
gui->send_events = NULL;
-
+
attr.background_pixmap = None;
attr.event_mask = (KeyPressMask|
KeyReleaseMask|
@@ -594,7 +604,7 @@ cairo_5c_gui_create (cairo_5c_surface_t *c5s, char *name, int width, int height,
ExposureMask|
StructureNotifyMask|
FocusChangeMask);
-
+
gui->window = XCreateWindow (dpy, gui->root,
0, 0, gui->new_width, gui->new_height, 0,
gui->depth,
@@ -606,30 +616,38 @@ cairo_5c_gui_create (cairo_5c_surface_t *c5s, char *name, int width, int height,
gui->gc = XCreateGC (dpy, gui->window,
GCForeground | GCGraphicsExposures,
&gcv);
-
+
set_window_surface (xg, gui->window, c5s);
-
+
sizeHints.flags = 0;
wmHints.flags = InputHint;
wmHints.input = True;
classHints.res_name = name;
classHints.res_class = name;
-
+
xg->wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
xg->wm_protocols = XInternAtom (dpy, "WM_PROTOCOLS", False);
Xutf8SetWMProperties (dpy, gui->window, name, name,
NULL, 0, &sizeHints, &wmHints, &classHints);
XSetWMProtocols (dpy, gui->window, &xg->wm_delete_window, 1);
-
+
if (shown)
XMapWindow (dpy, gui->window);
c5s->u.window.gui = gui;
-
+ if (xg->dpi != 0.0) {
+ c5s->dpi = xg->dpi;
+ } else {
+ int height_pix = DisplayHeight(dpy, screen);
+ int height_mm = DisplayHeightMM(dpy, screen);
+
+ c5s->dpi = (double) height_pix / ((double) height_mm / 25.4);
+ }
+
/* create the pixmap */
allocate_pixmap (c5s);
-
+
EXIT ();
return True;
}
@@ -742,8 +760,8 @@ void
cairo_5c_gui_check_size (cairo_5c_surface_t *c5s)
{
cairo_5c_gui_t *gui = c5s->u.window.gui;
-
- if (gui->disable == 0 &&
+
+ if (gui->disable == 0 &&
(gui->new_width != c5s->width ||
gui->new_height != c5s->height))
allocate_pixmap (c5s);
@@ -795,7 +813,7 @@ cairo_5c_gui_open_event (cairo_5c_surface_t *c5s)
err = errno;
RaiseStandardException (exception_open_error, 3,
FileGetErrorMessage (err),
- FileGetError (err),
+ FileGetError (err),
NewStrString ("event"));
RETURN (Void);
}