home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / visual.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  10.7 KB  |  327 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.    visual.c --- hackery involving X visuals
  20.    Created: Jamie Zawinski <jwz@netscape.com>, 7-Jul-94.
  21.  
  22.    This file is based on code I wrote for xscreensaver, which I previously
  23.    released under the standard X copyright (that is, not CopyLeft.)
  24.  */
  25.  
  26.  
  27. #include "mozilla.h"
  28. #include "xfe.h"
  29.  
  30. static Visual *fe_pick_best_visual (Screen *screen);
  31. static Visual *fe_pick_best_visual_of_class (Screen *screen, int visual_class);
  32. static Visual *fe_id_to_visual (Screen *screen, int id);
  33. int fe_VisualDepth (Display *dpy, Visual *visual);
  34.  
  35. #define DEFAULT_VISUAL    -1
  36. #define BEST_VISUAL    -2
  37. #define SPECIFIC_VISUAL    -3
  38.  
  39.  
  40. /* for XP_GetString() */
  41. #include <xpgetstr.h>
  42. extern int XFE_UNRECOGNISED_VISUAL;
  43. extern int XFE_NO_VISUAL_WITH_ID;
  44. extern int XFE_NO_VISUAL_OF_CLASS;
  45.  
  46.  
  47. Visual *
  48. fe_ParseVisual (Screen *screen, const char *v)
  49. {
  50.   int vclass;
  51.   unsigned long id;
  52.   char c;
  53.  
  54.   if (!v)                      vclass = BEST_VISUAL;
  55.   else if (!XP_STRCASECMP(v, "default"))      vclass = DEFAULT_VISUAL;
  56.   else if (!XP_STRCASECMP(v, "best"))           vclass = BEST_VISUAL;
  57.   else if (!XP_STRCASECMP(v, "staticgray"))       vclass = StaticGray;
  58.   else if (!XP_STRCASECMP(v, "staticcolor"))      vclass = StaticColor;
  59.   else if (!XP_STRCASECMP(v, "truecolor"))      vclass = TrueColor;
  60.   else if (!XP_STRCASECMP(v, "grayscale"))      vclass = GrayScale;
  61.   else if (!XP_STRCASECMP(v, "pseudocolor"))      vclass = PseudoColor;
  62.   else if (!XP_STRCASECMP(v, "directcolor"))      vclass = DirectColor;
  63.   else if (1 == sscanf(v, " %ld %c", &id, &c))      vclass = SPECIFIC_VISUAL;
  64.   else if (1 == sscanf(v, " 0x%lx %c", &id, &c))  vclass = SPECIFIC_VISUAL;
  65.   else
  66.     {
  67.       fprintf (stderr, XP_GetString( XFE_UNRECOGNISED_VISUAL ), fe_progname, v);
  68.       vclass = DEFAULT_VISUAL;
  69.     }
  70.  
  71.   if (vclass == DEFAULT_VISUAL)
  72.     return DefaultVisualOfScreen (screen);
  73.   else if (vclass == BEST_VISUAL)
  74.     return fe_pick_best_visual (screen);
  75.   else if (vclass == SPECIFIC_VISUAL)
  76.     {
  77.       Visual *visual = fe_id_to_visual (screen, id);
  78.       if (visual) return visual;
  79.       fprintf (stderr, XP_GetString( XFE_NO_VISUAL_WITH_ID ), fe_progname,
  80.            (unsigned int) id);
  81.       return DefaultVisualOfScreen (screen);
  82.     }
  83.   else
  84.     {
  85.       Visual *visual = fe_pick_best_visual_of_class (screen, vclass);
  86.       if (visual) return visual;
  87.       fprintf (stderr, XP_GetString( XFE_NO_VISUAL_OF_CLASS ), fe_progname, v);
  88.       return DefaultVisualOfScreen (screen);
  89.     }
  90. }
  91.  
  92. static Visual *
  93. fe_pick_best_visual (Screen *screen)
  94. {
  95.   /* The "best" visual is the one on which we can allocate the largest
  96.      range and number of colors.
  97.  
  98.      Therefore, a TrueColor visual which is at least 16 bits deep is best.
  99.      (The assumption here being that a TrueColor of less than 16 bits is
  100.      really just a PseudoColor visual with a pre-allocated color cube.)
  101.  
  102.      The next best thing is a PseudoColor visual of any type.  After that
  103.      come the non-colormappable visuals, and non-color visuals.
  104.    */
  105.   Display *dpy = DisplayOfScreen (screen);
  106.   Visual *visual;
  107.   if ((visual = fe_pick_best_visual_of_class (screen, TrueColor)) &&
  108.       fe_VisualDepth (dpy, visual) >= 16)
  109.     return visual;
  110.   if ((visual = fe_pick_best_visual_of_class (screen, PseudoColor)))
  111.     return visual;
  112.   if ((visual = fe_pick_best_visual_of_class (screen, TrueColor)))
  113.     return visual;
  114. #ifdef DIRECTCOLOR_WORKS
  115.   if ((visual = fe_pick_best_visual_of_class (screen, DirectColor)))
  116.     return visual;
  117. #endif
  118.  
  119.   /* If this screen has only StaticGray or GrayScale visuals then just
  120.      choose the default visual if it is deep enough.  This will keep
  121.      us from unnecessarily installing a private colormap and causing
  122.      colormap flashing.  Unfortunately, it also means that if we can't
  123.      install a gray ramp in the GrayScale visual's default colormap,
  124.      we will look bad.  Realistically, I don't expect this to ever
  125.      happen and, if it does, the user can force the use of a
  126.      private colormap with the -install command-line option or a
  127.      resource setting. */
  128.  
  129.   visual = DefaultVisualOfScreen (screen);
  130.   if (fe_VisualDepth (dpy, visual) >= 8)
  131.       return visual;
  132.   
  133.   if ((visual = fe_pick_best_visual_of_class (screen, StaticGray)))
  134.     return visual;
  135.   if ((visual = fe_pick_best_visual_of_class (screen, GrayScale)))
  136.     return visual;
  137.   return DefaultVisualOfScreen (screen);
  138. }
  139.  
  140. #define XXX_IMAGE_LIBRARY_IS_SOMEWHAT_BROKEN
  141.  
  142. static Visual *
  143. fe_pick_best_visual_of_class (Screen *screen, int visual_class)
  144. {
  145.   /* The best visual of a class is the one which on which we can allocate
  146.      the largest range and number of colors, which means the one with the
  147.      greatest depth and number of cells.
  148.    */
  149.   Display *dpy = DisplayOfScreen (screen);
  150.   XVisualInfo vi_in, *vi_out;
  151.   int out_count;
  152.  
  153.   vi_in.class = visual_class;
  154.   vi_in.screen = fe_ScreenNumber (screen);
  155.   vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
  156.                &vi_in, &out_count);
  157.   if (vi_out)
  158.     {
  159.       /* choose the 'best' one, if multiple */
  160.       int i, best;
  161.       Visual *visual;
  162.       for (i = 0, best = 0; i < out_count; i++)
  163.     /* It's better if it's deeper, or if it's the same depth with
  164.        more cells (does that ever happen?  Well, it could...)
  165.        NOTE: don't allow pseudo color to get larger than 8! */
  166.     if (((vi_out [i].depth > vi_out [best].depth) ||
  167.          ((vi_out [i].depth == vi_out [best].depth) &&
  168.           (vi_out [i].colormap_size > vi_out [best].colormap_size)))
  169. #ifdef XXX_IMAGE_LIBRARY_IS_SOMEWHAT_BROKEN
  170.         /* For now, the image library doesn't like PseudoColor visuals
  171.            of depths other than 1 or 8.  Depths greater than 8 only occur
  172.            on machines which have TrueColor anyway, so probably we'll end
  173.            up using that (it is the one that `Best' would pick) but if a
  174.            PseudoColor visual is explicitly specified, pick the 8 bit one.
  175.          */
  176.         && (visual_class != PseudoColor ||
  177.         vi_out [i].depth == 1 ||
  178.         vi_out [i].depth == 8)
  179. #endif
  180.             
  181.             /* SGI has 30-bit deep visuals.  Ignore them. 
  182.                (We only have 24-bit data anyway.)
  183.              */
  184.             && (vi_out [i].depth <= 24)
  185.         )
  186.       best = i;
  187.       visual = vi_out [best].visual;
  188.       XFree ((char *) vi_out);
  189.       return visual;
  190.     }
  191.   else
  192.     return 0;
  193. }
  194.  
  195. static Visual *
  196. fe_id_to_visual (Screen *screen, int id)
  197. {
  198.   Display *dpy = DisplayOfScreen (screen);
  199.   XVisualInfo vi_in, *vi_out;
  200.   int out_count;
  201.   vi_in.screen = fe_ScreenNumber (screen);
  202.   vi_in.visualid = id;
  203.   vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
  204.                &vi_in, &out_count);
  205.   if (vi_out)
  206.     {
  207.       Visual *v = vi_out[0].visual;
  208.       XFree ((char *) vi_out);
  209.       return v;
  210.     }
  211.   return 0;
  212. }
  213.  
  214. char *
  215. fe_VisualDescription (Screen *screen, Visual *visual)
  216. {
  217.   Display *dpy = DisplayOfScreen (screen);
  218.   XVisualInfo vi_in, *vi_out;
  219.   int out_count;
  220.   char buf [255];
  221.   vi_in.screen = fe_ScreenNumber (screen);
  222.   vi_in.visualid = XVisualIDFromVisual (visual);
  223.   vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
  224.                &vi_in, &out_count);
  225.   if (! vi_out) abort ();
  226.   PR_snprintf (buf, sizeof (buf),
  227.        "0x%02x (%s depth: %2d, cmap: %3d)",
  228.        (unsigned int) vi_out->visualid,
  229.        (vi_out->class == StaticGray  ? "StaticGray, " :
  230.         vi_out->class == StaticColor ? "StaticColor," :
  231.         vi_out->class == TrueColor   ? "TrueColor,  " :
  232.         vi_out->class == GrayScale   ? "GrayScale,  " :
  233.         vi_out->class == PseudoColor ? "PseudoColor," :
  234.         vi_out->class == DirectColor ? "DirectColor," :
  235.                        "UNKNOWN:    "),
  236.        vi_out->depth, vi_out->colormap_size /*, vi_out->bits_per_rgb*/);
  237.   XFree ((char *) vi_out);
  238.   return strdup (buf);
  239. }
  240.  
  241. int
  242. fe_ScreenNumber (Screen *screen)
  243. {
  244.   Display *dpy = DisplayOfScreen (screen);
  245.   int i;
  246.   for (i = 0; i < ScreenCount (dpy); i++)
  247.     if (ScreenOfDisplay (dpy, i) == screen)
  248.       return i;
  249.   abort ();
  250. }
  251.  
  252.  
  253. /* Changing visuals
  254.  */
  255.  
  256. #if 0 /* This doesn't work real well - Motif bugs apparently. */
  257. void
  258. fe_ChangeVisualCallback (Widget widget, XtPointer closure, XtPointer call_data)
  259. {
  260.   MWContext *context = (MWContext *) closure;
  261.   Visual *v = fe_ReadVisual (context);
  262.   if (v && v != fe_globalData.default_visual)
  263.     {
  264.       Display *dpy = XtDisplay (CONTEXT_WIDGET (context));
  265.       Screen *screen = XtScreen (CONTEXT_WIDGET (context));
  266.       if (v == DefaultVisualOfScreen (screen))
  267.     fe_globalData.default_cmap = DefaultColormapOfScreen (screen);
  268.       else
  269.     fe_globalData.default_cmap =
  270.       XCreateColormap (dpy, XtWindow (CONTEXT_WIDGET (context)),
  271.                v, AllocNone);
  272.     }
  273. }
  274. #endif
  275.  
  276. int
  277. fe_VisualDepth (Display *dpy, Visual *visual)
  278. {
  279.   XVisualInfo vi_in, *vi_out;
  280.   int out_count, d;
  281. /*  vi_in.screen = DefaultScreen (dpy);*/
  282.   vi_in.visualid = XVisualIDFromVisual (visual);
  283.   vi_out = XGetVisualInfo (dpy, /*VisualScreenMask|*/VisualIDMask,
  284.                &vi_in, &out_count);
  285.   if (! vi_out) abort ();
  286.   d = vi_out [0].depth;
  287.   XFree ((char *) vi_out);
  288.   return d;
  289. }
  290.  
  291. int
  292. fe_VisualPixmapDepth (Display *dpy, Visual *visual)
  293. {
  294.   int visual_depth = fe_VisualDepth (dpy, visual);
  295.   int pixmap_depth = visual_depth;
  296.   int i, pfvc = 0;
  297.   XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
  298.   /* Return the first matching depth in the pixmap formats.
  299.      If there are no matching pixmap formats (which shouldn't
  300.      be able to happen) return the visual depth instead. */
  301.   for (i = 0; i < pfvc; i++)
  302.     if (pfv[i].depth == visual_depth)
  303.       {
  304.     pixmap_depth = pfv[i].bits_per_pixel;
  305.     break;
  306.       }
  307.   if (pfv)
  308.     XFree (pfv);
  309.   return pixmap_depth;
  310. }
  311.  
  312.  
  313. int
  314. fe_VisualCells (Display *dpy, Visual *visual)
  315. {
  316.   XVisualInfo vi_in, *vi_out;
  317.   int out_count, c;
  318. /*  vi_in.screen = DefaultScreen (dpy);*/
  319.   vi_in.visualid = XVisualIDFromVisual (visual);
  320.   vi_out = XGetVisualInfo (dpy, /*VisualScreenMask|*/VisualIDMask,
  321.                &vi_in, &out_count);
  322.   if (! vi_out) abort ();
  323.   c = vi_out [0].colormap_size;
  324.   XFree ((char *) vi_out);
  325.   return c;
  326. }
  327.