xwayland: Add xdg-system-bell support
[xserver.git] / render / filter.c
blob546998a92c8d031b7cf99cc9c6ce1b4a05f10e25
1 /*
2 * Copyright © 2002 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #include <dix-config.h>
25 #define XK_LATIN1
26 #include <X11/keysymdef.h>
28 #include "misc.h"
29 #include "scrnintstr.h"
30 #include "os.h"
31 #include "regionstr.h"
32 #include "validate.h"
33 #include "windowstr.h"
34 #include "input.h"
35 #include "resource.h"
36 #include "colormapst.h"
37 #include "cursorstr.h"
38 #include "dixstruct.h"
39 #include "gcstruct.h"
40 #include "servermd.h"
41 #include "picturestr.h"
43 static char **filterNames;
44 static int nfilterNames;
47 * ISO Latin-1 case conversion routine
49 * this routine always null-terminates the result, so
50 * beware of too-small buffers
53 static unsigned char
54 ISOLatin1ToLower(unsigned char source)
56 unsigned char dest;
58 if ((source >= XK_A) && (source <= XK_Z))
59 dest = source + (XK_a - XK_A);
60 else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis))
61 dest = source + (XK_agrave - XK_Agrave);
62 else if ((source >= XK_Ooblique) && (source <= XK_Thorn))
63 dest = source + (XK_oslash - XK_Ooblique);
64 else
65 dest = source;
66 return dest;
69 static int
70 CompareISOLatin1Lowered(const unsigned char *s1, int s1len,
71 const unsigned char *s2, int s2len)
73 unsigned char c1, c2;
75 for (;;) {
76 /* note -- compare against zero so that -1 ignores len */
77 c1 = s1len-- ? *s1++ : '\0';
78 c2 = s2len-- ? *s2++ : '\0';
79 if (!c1 ||
80 (c1 != c2 &&
81 (c1 = ISOLatin1ToLower(c1)) != (c2 = ISOLatin1ToLower(c2))))
82 break;
84 return (int) c1 - (int) c2;
88 * standard but not required filters don't have constant indices
91 int
92 PictureGetFilterId(const char *filter, int len, Bool makeit)
94 int i;
95 char *name;
96 char **names;
98 if (len < 0)
99 len = strlen(filter);
100 for (i = 0; i < nfilterNames; i++)
101 if (!CompareISOLatin1Lowered((const unsigned char *) filterNames[i], -1,
102 (const unsigned char *) filter, len))
103 return i;
104 if (!makeit)
105 return -1;
106 name = malloc(len + 1);
107 if (!name)
108 return -1;
109 memcpy(name, filter, len);
110 name[len] = '\0';
111 if (filterNames)
112 names = reallocarray(filterNames, nfilterNames + 1, sizeof(char *));
113 else
114 names = malloc(sizeof(char *));
115 if (!names) {
116 free(name);
117 return -1;
119 filterNames = names;
120 i = nfilterNames++;
121 filterNames[i] = name;
122 return i;
125 static Bool
126 PictureSetDefaultIds(void)
128 /* careful here -- this list must match the #define values */
130 if (PictureGetFilterId(FilterNearest, -1, TRUE) != PictFilterNearest)
131 return FALSE;
132 if (PictureGetFilterId(FilterBilinear, -1, TRUE) != PictFilterBilinear)
133 return FALSE;
135 if (PictureGetFilterId(FilterFast, -1, TRUE) != PictFilterFast)
136 return FALSE;
137 if (PictureGetFilterId(FilterGood, -1, TRUE) != PictFilterGood)
138 return FALSE;
139 if (PictureGetFilterId(FilterBest, -1, TRUE) != PictFilterBest)
140 return FALSE;
142 if (PictureGetFilterId(FilterConvolution, -1, TRUE) !=
143 PictFilterConvolution)
144 return FALSE;
145 return TRUE;
148 char *
149 PictureGetFilterName(int id)
151 if (0 <= id && id < nfilterNames)
152 return filterNames[id];
153 else
154 return 0;
157 static void
158 PictureFreeFilterIds(void)
160 int i;
162 for (i = 0; i < nfilterNames; i++)
163 free(filterNames[i]);
164 free(filterNames);
165 nfilterNames = 0;
166 filterNames = 0;
170 PictureAddFilter(ScreenPtr pScreen,
171 const char *filter,
172 PictFilterValidateParamsProcPtr ValidateParams,
173 int width, int height)
175 PictureScreenPtr ps = GetPictureScreen(pScreen);
176 int id = PictureGetFilterId(filter, -1, TRUE);
177 int i;
178 PictFilterPtr filters;
180 if (id < 0)
181 return -1;
183 * It's an error to attempt to reregister a filter
185 for (i = 0; i < ps->nfilters; i++)
186 if (ps->filters[i].id == id)
187 return -1;
188 if (ps->filters)
189 filters =
190 reallocarray(ps->filters, ps->nfilters + 1, sizeof(PictFilterRec));
191 else
192 filters = malloc(sizeof(PictFilterRec));
193 if (!filters)
194 return -1;
195 ps->filters = filters;
196 i = ps->nfilters++;
197 ps->filters[i].name = PictureGetFilterName(id);
198 ps->filters[i].id = id;
199 ps->filters[i].ValidateParams = ValidateParams;
200 ps->filters[i].width = width;
201 ps->filters[i].height = height;
202 return id;
205 Bool
206 PictureSetFilterAlias(ScreenPtr pScreen, const char *filter, const char *alias)
208 PictureScreenPtr ps = GetPictureScreen(pScreen);
209 int filter_id = PictureGetFilterId(filter, -1, FALSE);
210 int alias_id = PictureGetFilterId(alias, -1, TRUE);
211 int i;
213 if (filter_id < 0 || alias_id < 0)
214 return FALSE;
215 for (i = 0; i < ps->nfilterAliases; i++)
216 if (ps->filterAliases[i].alias_id == alias_id)
217 break;
218 if (i == ps->nfilterAliases) {
219 PictFilterAliasPtr aliases;
221 if (ps->filterAliases)
222 aliases = reallocarray(ps->filterAliases,
223 ps->nfilterAliases + 1,
224 sizeof(PictFilterAliasRec));
225 else
226 aliases = malloc(sizeof(PictFilterAliasRec));
227 if (!aliases)
228 return FALSE;
229 ps->filterAliases = aliases;
230 ps->filterAliases[i].alias = PictureGetFilterName(alias_id);
231 ps->filterAliases[i].alias_id = alias_id;
232 ps->nfilterAliases++;
234 ps->filterAliases[i].filter_id = filter_id;
235 return TRUE;
238 PictFilterPtr
239 PictureFindFilter(ScreenPtr pScreen, char *name, int len)
241 PictureScreenPtr ps = GetPictureScreen(pScreen);
242 int id = PictureGetFilterId(name, len, FALSE);
243 int i;
245 if (id < 0)
246 return 0;
247 /* Check for an alias, allow them to recurse */
248 for (i = 0; i < ps->nfilterAliases; i++)
249 if (ps->filterAliases[i].alias_id == id) {
250 id = ps->filterAliases[i].filter_id;
251 i = 0;
253 /* find the filter */
254 for (i = 0; i < ps->nfilters; i++)
255 if (ps->filters[i].id == id)
256 return &ps->filters[i];
257 return 0;
260 static Bool
261 convolutionFilterValidateParams(ScreenPtr pScreen,
262 int filter,
263 xFixed * params,
264 int nparams, int *width, int *height)
266 int w, h;
268 if (nparams < 3)
269 return FALSE;
271 if (xFixedFrac(params[0]) || xFixedFrac(params[1]))
272 return FALSE;
274 w = xFixedToInt(params[0]);
275 h = xFixedToInt(params[1]);
277 nparams -= 2;
278 if (w * h > nparams)
279 return FALSE;
281 *width = w;
282 *height = h;
283 return TRUE;
286 Bool
287 PictureSetDefaultFilters(ScreenPtr pScreen)
289 if (!filterNames)
290 if (!PictureSetDefaultIds())
291 return FALSE;
292 if (PictureAddFilter(pScreen, FilterNearest, 0, 1, 1) < 0)
293 return FALSE;
294 if (PictureAddFilter(pScreen, FilterBilinear, 0, 2, 2) < 0)
295 return FALSE;
297 if (!PictureSetFilterAlias(pScreen, FilterNearest, FilterFast))
298 return FALSE;
299 if (!PictureSetFilterAlias(pScreen, FilterBilinear, FilterGood))
300 return FALSE;
301 if (!PictureSetFilterAlias(pScreen, FilterBilinear, FilterBest))
302 return FALSE;
304 if (PictureAddFilter
305 (pScreen, FilterConvolution, convolutionFilterValidateParams, 0, 0) < 0)
306 return FALSE;
308 return TRUE;
311 void
312 PictureResetFilters(ScreenPtr pScreen)
314 PictureScreenPtr ps = GetPictureScreen(pScreen);
316 free(ps->filters);
317 free(ps->filterAliases);
319 /* Free the filters when the last screen is closed */
320 if (pScreen->myNum == 0)
321 PictureFreeFilterIds();
325 SetPictureFilter(PicturePtr pPicture, char *name, int len, xFixed * params,
326 int nparams)
328 PictFilterPtr pFilter;
329 ScreenPtr pScreen;
331 if (pPicture->pDrawable != NULL)
332 pScreen = pPicture->pDrawable->pScreen;
333 else
334 pScreen = screenInfo.screens[0];
336 pFilter = PictureFindFilter(pScreen, name, len);
338 if (!pFilter)
339 return BadName;
341 if (pPicture->pDrawable == NULL) {
342 int s;
344 /* For source pictures, the picture isn't tied to a screen. So, ensure
345 * that all screens can handle a filter we set for the picture.
347 for (s = 1; s < screenInfo.numScreens; s++) {
348 PictFilterPtr pScreenFilter;
350 pScreenFilter = PictureFindFilter(screenInfo.screens[s], name, len);
351 if (!pScreenFilter || pScreenFilter->id != pFilter->id)
352 return BadMatch;
355 return SetPicturePictFilter(pPicture, pFilter, params, nparams);
359 SetPicturePictFilter(PicturePtr pPicture, PictFilterPtr pFilter,
360 xFixed * params, int nparams)
362 ScreenPtr pScreen;
363 int i;
365 if (pPicture->pDrawable)
366 pScreen = pPicture->pDrawable->pScreen;
367 else
368 pScreen = screenInfo.screens[0];
370 if (pFilter->ValidateParams) {
371 int width, height;
373 if (!(*pFilter->ValidateParams)
374 (pScreen, pFilter->id, params, nparams, &width, &height))
375 return BadMatch;
377 else if (nparams)
378 return BadMatch;
380 if (nparams != pPicture->filter_nparams) {
381 xFixed *new_params = xallocarray(nparams, sizeof(xFixed));
383 if (!new_params && nparams)
384 return BadAlloc;
385 free(pPicture->filter_params);
386 pPicture->filter_params = new_params;
387 pPicture->filter_nparams = nparams;
389 for (i = 0; i < nparams; i++)
390 pPicture->filter_params[i] = params[i];
391 pPicture->filter = pFilter->id;
393 if (pPicture->pDrawable) {
394 PictureScreenPtr ps = GetPictureScreen(pScreen);
395 int result;
397 result = (*ps->ChangePictureFilter) (pPicture, pPicture->filter,
398 params, nparams);
399 return result;
401 return Success;