root/lwlib/lwlib-utils.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. XtNoClearRefreshWidget
  2. XtApplyToWidgets
  3. XtApplyUntilToWidgets
  4. XtCompositeChildren
  5. XtWidgetBeingDestroyedP
  6. crxft_font_open_name
  7. crxft_font_close
  8. crxft_draw_create
  9. crxft_set_source_color
  10. crxft_draw_rect
  11. crxft_draw_string
  12. crxft_text_extents

     1 /* Defines some widget utility functions.
     2 
     3 Copyright (C) 1992 Lucid, Inc.
     4 Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
     5 
     6 This file is part of the Lucid Widget Library.
     7 
     8 The Lucid Widget Library is free software; you can redistribute it and/or
     9 modify it under the terms of the GNU General Public License as published by
    10 the Free Software Foundation; either version 1, or (at your option)
    11 any later version.
    12 
    13 The Lucid Widget Library is distributed in the hope that it will be useful,
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16 GNU General Public License for more details.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    20 
    21 #include <config.h>
    22 
    23 #include <setjmp.h>
    24 #include <lisp.h>
    25 
    26 #include <X11/Xatom.h>
    27 #include <X11/IntrinsicP.h>
    28 #include <X11/ObjectP.h>
    29 #include "lwlib-utils.h"
    30 #include "lwlib.h"
    31 
    32 /* Redisplay the contents of the widget, without first clearing it. */
    33 void
    34 XtNoClearRefreshWidget (Widget widget)
    35 {
    36   XEvent event;
    37 
    38   event.type = Expose;
    39   event.xexpose.serial = 0;
    40   event.xexpose.send_event = 0;
    41   event.xexpose.display = XtDisplay (widget);
    42   event.xexpose.window = XtWindow (widget);
    43   event.xexpose.x = 0;
    44   event.xexpose.y = 0;
    45   event.xexpose.width = widget->core.width;
    46   event.xexpose.height = widget->core.height;
    47   event.xexpose.count = 0;
    48 
    49   (*widget->core.widget_class->core_class.expose)
    50     (widget, &event, (Region)NULL);
    51 }
    52 
    53 
    54 /*
    55  * Apply a function to all the subwidgets of a given widget recursively.
    56 */
    57 void
    58 XtApplyToWidgets (Widget w, XtApplyToWidgetsProc proc, XtPointer arg)
    59 {
    60   if (XtIsComposite (w))
    61     {
    62       CompositeWidget cw = (CompositeWidget) w;
    63       /* We have to copy the children list before mapping over it, because
    64          the procedure might add/delete elements, which would lose badly.
    65          */
    66       int nkids = cw->composite.num_children;
    67       Widget *kids = (Widget *) xmalloc (sizeof (Widget) * nkids);
    68       int i;
    69       memcpy ((char *) kids, (char *) cw->composite.children,
    70               sizeof (Widget) * nkids);
    71       for (i = 0; i < nkids; i++)
    72 /* This prevent us from using gadgets, why is it here? */
    73 /*      if (XtIsWidget (kids [i])) */
    74           {
    75             /* do the kiddies first in case we're destroying */
    76             XtApplyToWidgets (kids [i], proc, arg);
    77             proc (kids [i], arg);
    78           }
    79       xfree (kids);
    80     }
    81 }
    82 
    83 
    84 /*
    85  * Apply a function to all the subwidgets of a given widget recursively.
    86  * Stop as soon as the function returns non NULL and returns this as a value.
    87  */
    88 void *
    89 XtApplyUntilToWidgets (Widget w, XtApplyUntilToWidgetsProc proc, XtPointer arg)
    90 {
    91   void* result;
    92   if (XtIsComposite (w))
    93     {
    94       CompositeWidget cw = (CompositeWidget)w;
    95       int i;
    96       for (i = 0; i < cw->composite.num_children; i++)
    97         if (XtIsWidget (cw->composite.children [i])){
    98           result = proc (cw->composite.children [i], arg);
    99           if (result)
   100             return result;
   101           result = XtApplyUntilToWidgets (cw->composite.children [i], proc,
   102                                           arg);
   103           if (result)
   104             return result;
   105         }
   106     }
   107   return NULL;
   108 }
   109 
   110 
   111 /*
   112  * Returns a copy of the list of all children of a composite widget
   113  */
   114 Widget *
   115 XtCompositeChildren (Widget widget, unsigned int *number)
   116 {
   117   CompositeWidget cw = (CompositeWidget)widget;
   118   Widget* result;
   119   int n;
   120   int i;
   121 
   122   if (!XtIsComposite (widget))
   123     {
   124       *number = 0;
   125       return NULL;
   126     }
   127   n = cw->composite.num_children;
   128   result = (Widget*)(void*)XtMalloc (n * sizeof (Widget));
   129   *number = n;
   130   for (i = 0; i < n; i++)
   131     result [i] = cw->composite.children [i];
   132   return result;
   133 }
   134 
   135 Boolean
   136 XtWidgetBeingDestroyedP (Widget widget)
   137 {
   138   return widget->core.being_destroyed;
   139 }
   140 
   141 #ifdef USE_CAIRO
   142 /* Xft emulation on cairo.  */
   143 #include <math.h>
   144 #include <cairo-ft.h>
   145 #include <cairo-xlib.h>
   146 
   147 XftFont *
   148 crxft_font_open_name (Display *dpy, int screen, const char *name)
   149 {
   150   XftFont *pub = NULL;
   151   FcPattern *match = NULL;
   152   FcPattern *pattern = FcNameParse ((FcChar8 *) name);
   153   if (pattern)
   154     {
   155       FcConfigSubstitute (NULL, pattern, FcMatchPattern);
   156       double dpi;
   157       if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) == FcResultNoMatch)
   158         {
   159           char *v = XGetDefault (dpy, "Xft", FC_DPI);
   160           if (v == NULL || sscanf (v, "%lf", &dpi) != 1)
   161             dpi = ((DisplayHeight (dpy, screen) * 25.4)
   162                    / DisplayHeightMM (dpy, screen));
   163           FcPatternAddDouble (pattern, FC_DPI, dpi);
   164         }
   165       FcDefaultSubstitute (pattern);
   166       FcResult result;
   167       match = FcFontMatch (NULL, pattern, &result);
   168       FcPatternDestroy (pattern);
   169     }
   170   if (match)
   171     {
   172       cairo_font_face_t *font_face
   173         = cairo_ft_font_face_create_for_pattern (match);
   174       if (font_face)
   175         {
   176           double pixel_size;
   177           if ((FcPatternGetDouble (match, FC_PIXEL_SIZE, 0, &pixel_size)
   178                != FcResultMatch)
   179               || pixel_size < 1)
   180             pixel_size = 10;
   181 
   182           pub = xmalloc (sizeof (*pub));
   183           cairo_matrix_t font_matrix, ctm;
   184           cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size);
   185           cairo_matrix_init_identity (&ctm);
   186           cairo_font_options_t *options = cairo_font_options_create ();
   187           cairo_ft_font_options_substitute (options, match);
   188           pub->scaled_font = cairo_scaled_font_create (font_face, &font_matrix,
   189                                                        &ctm, options);
   190           cairo_font_face_destroy (font_face);
   191           cairo_font_options_destroy (options);
   192 
   193           cairo_font_extents_t extents;
   194           cairo_scaled_font_extents (pub->scaled_font, &extents);
   195           pub->ascent = lround (extents.ascent);
   196           pub->descent = lround (extents.descent);
   197           pub->height = lround (extents.height);
   198           pub->max_advance_width = lround (extents.max_x_advance);
   199         }
   200       FcPatternDestroy (match);
   201     }
   202   if (pub && pub->height <= 0)
   203     {
   204       crxft_font_close (pub);
   205       pub = NULL;
   206     }
   207   return pub;
   208 }
   209 
   210 void
   211 crxft_font_close (XftFont *pub)
   212 {
   213   cairo_scaled_font_destroy (pub->scaled_font);
   214   xfree (pub);
   215 }
   216 
   217 cairo_t *
   218 crxft_draw_create (Display *dpy, Drawable drawable, Visual *visual)
   219 {
   220   cairo_t *cr = NULL;
   221   Window root;
   222   int x, y;
   223   unsigned int width, height, border_width, depth;
   224 
   225   if (!XGetGeometry (dpy, drawable, &root, &x, &y, &width, &height,
   226                      &border_width, &depth))
   227     return NULL;
   228 
   229   cairo_surface_t *surface = cairo_xlib_surface_create (dpy, drawable, visual,
   230                                                         width, height);
   231   if (surface)
   232     {
   233       cr = cairo_create (surface);
   234       cairo_surface_destroy (surface);
   235     }
   236 
   237   return cr;
   238 }
   239 
   240 static void
   241 crxft_set_source_color (cairo_t *cr, const XftColor *color)
   242 {
   243   cairo_set_source_rgba (cr, color->color.red / 65535.0,
   244                          color->color.green / 65535.0,
   245                          color->color.blue / 65535.0,
   246                          color->color.alpha / 65535.0);
   247 }
   248 
   249 void
   250 crxft_draw_rect (cairo_t *cr, const XftColor *color, int x, int y,
   251                  unsigned int width, unsigned int height)
   252 {
   253   crxft_set_source_color (cr, color);
   254   cairo_rectangle (cr, x, y, width, height);
   255   cairo_fill (cr);
   256 }
   257 
   258 void
   259 crxft_draw_string (cairo_t *cr, const XftColor *color, XftFont *pub,
   260                    int x, int y, const FcChar8 *string, int len)
   261 {
   262   char *buf = xmalloc (len + 1);
   263   memcpy (buf, string, len);
   264   buf[len] = '\0';
   265   crxft_set_source_color (cr, color);
   266   cairo_set_scaled_font (cr, pub->scaled_font);
   267   cairo_move_to (cr, x, y);
   268   cairo_show_text (cr, buf);
   269   xfree (buf);
   270 }
   271 
   272 void
   273 crxft_text_extents (XftFont *pub, const FcChar8 *string, int len,
   274                     XGlyphInfo *extents)
   275 {
   276   char *buf = xmalloc (len + 1);
   277   memcpy (buf, string, len);
   278   buf[len] = '\0';
   279   cairo_text_extents_t text_extents;
   280   cairo_scaled_font_text_extents (pub->scaled_font, buf, &text_extents);
   281   xfree (buf);
   282   extents->x = ceil (- text_extents.x_bearing);
   283   extents->y = ceil (- text_extents.y_bearing);
   284   extents->width = (ceil (text_extents.x_bearing + text_extents.width)
   285                     + extents->x);
   286   extents->height = (ceil (text_extents.y_bearing + text_extents.height)
   287                      + extents->y);
   288   extents->xOff = lround (text_extents.x_advance);
   289   extents->yOff = lround (text_extents.y_advance);
   290 }
   291 #endif  /* USE_CAIRO */

/* [<][>][^][v][top][bottom][index][help] */