diff options
author | Keith Packard <keithp@keithp.com> | 2018-10-04 13:39:58 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2018-10-04 14:22:09 -0700 |
commit | 32de520d2161d7f4ff759b563735d865b9e842f4 (patch) | |
tree | 7788307ba3d9cf2ea2077a963b23abd9e86acf64 | |
parent | 5f0a289957ef315e03029b1be57986a8c292f6cf (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.h | 1 | ||||
-rw-r--r-- | src/surface.c | 10 | ||||
-rw-r--r-- | src/text.c | 3 | ||||
-rw-r--r-- | src/xlib.c | 90 |
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); @@ -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); } @@ -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); } |