pjs/cmd/xfe/visual.c

327 строки
10 KiB
C
Исходник Ответственный История

Этот файл содержит невидимые символы Юникода!

Этот файл содержит невидимые символы Юникода, которые могут быть отображены не так, как показано ниже. Если это намеренно, можете спокойно проигнорировать это предупреждение. Используйте кнопку Экранировать, чтобы показать скрытые символы.

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
visual.c --- hackery involving X visuals
Created: Jamie Zawinski <jwz@netscape.com>, 7-Jul-94.
This file is based on code I wrote for xscreensaver, which I previously
released under the standard X copyright (that is, not CopyLeft.)
*/
#include "mozilla.h"
#include "xfe.h"
static Visual *fe_pick_best_visual (Screen *screen);
static Visual *fe_pick_best_visual_of_class (Screen *screen, int visual_class);
static Visual *fe_id_to_visual (Screen *screen, int id);
int fe_VisualDepth (Display *dpy, Visual *visual);
#define DEFAULT_VISUAL -1
#define BEST_VISUAL -2
#define SPECIFIC_VISUAL -3
/* for XP_GetString() */
#include <xpgetstr.h>
extern int XFE_UNRECOGNISED_VISUAL;
extern int XFE_NO_VISUAL_WITH_ID;
extern int XFE_NO_VISUAL_OF_CLASS;
Visual *
fe_ParseVisual (Screen *screen, const char *v)
{
int vclass;
unsigned long id;
char c;
if (!v) vclass = BEST_VISUAL;
else if (!XP_STRCASECMP(v, "default")) vclass = DEFAULT_VISUAL;
else if (!XP_STRCASECMP(v, "best")) vclass = BEST_VISUAL;
else if (!XP_STRCASECMP(v, "staticgray")) vclass = StaticGray;
else if (!XP_STRCASECMP(v, "staticcolor")) vclass = StaticColor;
else if (!XP_STRCASECMP(v, "truecolor")) vclass = TrueColor;
else if (!XP_STRCASECMP(v, "grayscale")) vclass = GrayScale;
else if (!XP_STRCASECMP(v, "pseudocolor")) vclass = PseudoColor;
else if (!XP_STRCASECMP(v, "directcolor")) vclass = DirectColor;
else if (1 == sscanf(v, " %ld %c", &id, &c)) vclass = SPECIFIC_VISUAL;
else if (1 == sscanf(v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL;
else
{
fprintf (stderr, XP_GetString( XFE_UNRECOGNISED_VISUAL ), fe_progname, v);
vclass = DEFAULT_VISUAL;
}
if (vclass == DEFAULT_VISUAL)
return DefaultVisualOfScreen (screen);
else if (vclass == BEST_VISUAL)
return fe_pick_best_visual (screen);
else if (vclass == SPECIFIC_VISUAL)
{
Visual *visual = fe_id_to_visual (screen, id);
if (visual) return visual;
fprintf (stderr, XP_GetString( XFE_NO_VISUAL_WITH_ID ), fe_progname,
(unsigned int) id);
return DefaultVisualOfScreen (screen);
}
else
{
Visual *visual = fe_pick_best_visual_of_class (screen, vclass);
if (visual) return visual;
fprintf (stderr, XP_GetString( XFE_NO_VISUAL_OF_CLASS ), fe_progname, v);
return DefaultVisualOfScreen (screen);
}
}
static Visual *
fe_pick_best_visual (Screen *screen)
{
/* The "best" visual is the one on which we can allocate the largest
range and number of colors.
Therefore, a TrueColor visual which is at least 16 bits deep is best.
(The assumption here being that a TrueColor of less than 16 bits is
really just a PseudoColor visual with a pre-allocated color cube.)
The next best thing is a PseudoColor visual of any type. After that
come the non-colormappable visuals, and non-color visuals.
*/
Display *dpy = DisplayOfScreen (screen);
Visual *visual;
if ((visual = fe_pick_best_visual_of_class (screen, TrueColor)) &&
fe_VisualDepth (dpy, visual) >= 16)
return visual;
if ((visual = fe_pick_best_visual_of_class (screen, PseudoColor)))
return visual;
if ((visual = fe_pick_best_visual_of_class (screen, TrueColor)))
return visual;
#ifdef DIRECTCOLOR_WORKS
if ((visual = fe_pick_best_visual_of_class (screen, DirectColor)))
return visual;
#endif
/* If this screen has only StaticGray or GrayScale visuals then just
choose the default visual if it is deep enough. This will keep
us from unnecessarily installing a private colormap and causing
colormap flashing. Unfortunately, it also means that if we can't
install a gray ramp in the GrayScale visual's default colormap,
we will look bad. Realistically, I don't expect this to ever
happen and, if it does, the user can force the use of a
private colormap with the -install command-line option or a
resource setting. */
visual = DefaultVisualOfScreen (screen);
if (fe_VisualDepth (dpy, visual) >= 8)
return visual;
if ((visual = fe_pick_best_visual_of_class (screen, StaticGray)))
return visual;
if ((visual = fe_pick_best_visual_of_class (screen, GrayScale)))
return visual;
return DefaultVisualOfScreen (screen);
}
#define XXX_IMAGE_LIBRARY_IS_SOMEWHAT_BROKEN
static Visual *
fe_pick_best_visual_of_class (Screen *screen, int visual_class)
{
/* The best visual of a class is the one which on which we can allocate
the largest range and number of colors, which means the one with the
greatest depth and number of cells.
*/
Display *dpy = DisplayOfScreen (screen);
XVisualInfo vi_in, *vi_out;
int out_count;
vi_in.class = visual_class;
vi_in.screen = fe_ScreenNumber (screen);
vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
&vi_in, &out_count);
if (vi_out)
{
/* choose the 'best' one, if multiple */
int i, best;
Visual *visual;
for (i = 0, best = 0; i < out_count; i++)
/* It's better if it's deeper, or if it's the same depth with
more cells (does that ever happen? Well, it could...)
NOTE: don't allow pseudo color to get larger than 8! */
if (((vi_out [i].depth > vi_out [best].depth) ||
((vi_out [i].depth == vi_out [best].depth) &&
(vi_out [i].colormap_size > vi_out [best].colormap_size)))
#ifdef XXX_IMAGE_LIBRARY_IS_SOMEWHAT_BROKEN
/* For now, the image library doesn't like PseudoColor visuals
of depths other than 1 or 8. Depths greater than 8 only occur
on machines which have TrueColor anyway, so probably we'll end
up using that (it is the one that `Best' would pick) but if a
PseudoColor visual is explicitly specified, pick the 8 bit one.
*/
&& (visual_class != PseudoColor ||
vi_out [i].depth == 1 ||
vi_out [i].depth == 8)
#endif
/* SGI has 30-bit deep visuals. Ignore them.
(We only have 24-bit data anyway.)
*/
&& (vi_out [i].depth <= 24)
)
best = i;
visual = vi_out [best].visual;
XFree ((char *) vi_out);
return visual;
}
else
return 0;
}
static Visual *
fe_id_to_visual (Screen *screen, int id)
{
Display *dpy = DisplayOfScreen (screen);
XVisualInfo vi_in, *vi_out;
int out_count;
vi_in.screen = fe_ScreenNumber (screen);
vi_in.visualid = id;
vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
&vi_in, &out_count);
if (vi_out)
{
Visual *v = vi_out[0].visual;
XFree ((char *) vi_out);
return v;
}
return 0;
}
char *
fe_VisualDescription (Screen *screen, Visual *visual)
{
Display *dpy = DisplayOfScreen (screen);
XVisualInfo vi_in, *vi_out;
int out_count;
char buf [255];
vi_in.screen = fe_ScreenNumber (screen);
vi_in.visualid = XVisualIDFromVisual (visual);
vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
&vi_in, &out_count);
if (! vi_out) abort ();
PR_snprintf (buf, sizeof (buf),
"0x%02x (%s depth: %2d, cmap: %3d)",
(unsigned int) vi_out->visualid,
(vi_out->class == StaticGray ? "StaticGray, " :
vi_out->class == StaticColor ? "StaticColor," :
vi_out->class == TrueColor ? "TrueColor, " :
vi_out->class == GrayScale ? "GrayScale, " :
vi_out->class == PseudoColor ? "PseudoColor," :
vi_out->class == DirectColor ? "DirectColor," :
"UNKNOWN: "),
vi_out->depth, vi_out->colormap_size /*, vi_out->bits_per_rgb*/);
XFree ((char *) vi_out);
return strdup (buf);
}
int
fe_ScreenNumber (Screen *screen)
{
Display *dpy = DisplayOfScreen (screen);
int i;
for (i = 0; i < ScreenCount (dpy); i++)
if (ScreenOfDisplay (dpy, i) == screen)
return i;
abort ();
}
/* Changing visuals
*/
#if 0 /* This doesn't work real well - Motif bugs apparently. */
void
fe_ChangeVisualCallback (Widget widget, XtPointer closure, XtPointer call_data)
{
MWContext *context = (MWContext *) closure;
Visual *v = fe_ReadVisual (context);
if (v && v != fe_globalData.default_visual)
{
Display *dpy = XtDisplay (CONTEXT_WIDGET (context));
Screen *screen = XtScreen (CONTEXT_WIDGET (context));
if (v == DefaultVisualOfScreen (screen))
fe_globalData.default_cmap = DefaultColormapOfScreen (screen);
else
fe_globalData.default_cmap =
XCreateColormap (dpy, XtWindow (CONTEXT_WIDGET (context)),
v, AllocNone);
}
}
#endif
int
fe_VisualDepth (Display *dpy, Visual *visual)
{
XVisualInfo vi_in, *vi_out;
int out_count, d;
/* vi_in.screen = DefaultScreen (dpy);*/
vi_in.visualid = XVisualIDFromVisual (visual);
vi_out = XGetVisualInfo (dpy, /*VisualScreenMask|*/VisualIDMask,
&vi_in, &out_count);
if (! vi_out) abort ();
d = vi_out [0].depth;
XFree ((char *) vi_out);
return d;
}
int
fe_VisualPixmapDepth (Display *dpy, Visual *visual)
{
int visual_depth = fe_VisualDepth (dpy, visual);
int pixmap_depth = visual_depth;
int i, pfvc = 0;
XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
/* Return the first matching depth in the pixmap formats.
If there are no matching pixmap formats (which shouldn't
be able to happen) return the visual depth instead. */
for (i = 0; i < pfvc; i++)
if (pfv[i].depth == visual_depth)
{
pixmap_depth = pfv[i].bits_per_pixel;
break;
}
if (pfv)
XFree (pfv);
return pixmap_depth;
}
int
fe_VisualCells (Display *dpy, Visual *visual)
{
XVisualInfo vi_in, *vi_out;
int out_count, c;
/* vi_in.screen = DefaultScreen (dpy);*/
vi_in.visualid = XVisualIDFromVisual (visual);
vi_out = XGetVisualInfo (dpy, /*VisualScreenMask|*/VisualIDMask,
&vi_in, &out_count);
if (! vi_out) abort ();
c = vi_out [0].colormap_size;
XFree ((char *) vi_out);
return c;
}