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>
26 #include <X11/keysymdef.h>
29 #include "scrnintstr.h"
31 #include "regionstr.h"
33 #include "windowstr.h"
36 #include "colormapst.h"
37 #include "cursorstr.h"
38 #include "dixstruct.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
54 ISOLatin1ToLower(unsigned char source
)
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
);
70 CompareISOLatin1Lowered(const unsigned char *s1
, int s1len
,
71 const unsigned char *s2
, int s2len
)
76 /* note -- compare against zero so that -1 ignores len */
77 c1
= s1len
-- ? *s1
++ : '\0';
78 c2
= s2len
-- ? *s2
++ : '\0';
81 (c1
= ISOLatin1ToLower(c1
)) != (c2
= ISOLatin1ToLower(c2
))))
84 return (int) c1
- (int) c2
;
88 * standard but not required filters don't have constant indices
92 PictureGetFilterId(const char *filter
, int len
, Bool makeit
)
100 for (i
= 0; i
< nfilterNames
; i
++)
101 if (!CompareISOLatin1Lowered((const unsigned char *) filterNames
[i
], -1,
102 (const unsigned char *) filter
, len
))
106 name
= malloc(len
+ 1);
109 memcpy(name
, filter
, len
);
112 names
= reallocarray(filterNames
, nfilterNames
+ 1, sizeof(char *));
114 names
= malloc(sizeof(char *));
121 filterNames
[i
] = name
;
126 PictureSetDefaultIds(void)
128 /* careful here -- this list must match the #define values */
130 if (PictureGetFilterId(FilterNearest
, -1, TRUE
) != PictFilterNearest
)
132 if (PictureGetFilterId(FilterBilinear
, -1, TRUE
) != PictFilterBilinear
)
135 if (PictureGetFilterId(FilterFast
, -1, TRUE
) != PictFilterFast
)
137 if (PictureGetFilterId(FilterGood
, -1, TRUE
) != PictFilterGood
)
139 if (PictureGetFilterId(FilterBest
, -1, TRUE
) != PictFilterBest
)
142 if (PictureGetFilterId(FilterConvolution
, -1, TRUE
) !=
143 PictFilterConvolution
)
149 PictureGetFilterName(int id
)
151 if (0 <= id
&& id
< nfilterNames
)
152 return filterNames
[id
];
158 PictureFreeFilterIds(void)
162 for (i
= 0; i
< nfilterNames
; i
++)
163 free(filterNames
[i
]);
170 PictureAddFilter(ScreenPtr pScreen
,
172 PictFilterValidateParamsProcPtr ValidateParams
,
173 int width
, int height
)
175 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
176 int id
= PictureGetFilterId(filter
, -1, TRUE
);
178 PictFilterPtr filters
;
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
)
190 reallocarray(ps
->filters
, ps
->nfilters
+ 1, sizeof(PictFilterRec
));
192 filters
= malloc(sizeof(PictFilterRec
));
195 ps
->filters
= filters
;
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
;
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
);
213 if (filter_id
< 0 || alias_id
< 0)
215 for (i
= 0; i
< ps
->nfilterAliases
; i
++)
216 if (ps
->filterAliases
[i
].alias_id
== alias_id
)
218 if (i
== ps
->nfilterAliases
) {
219 PictFilterAliasPtr aliases
;
221 if (ps
->filterAliases
)
222 aliases
= reallocarray(ps
->filterAliases
,
223 ps
->nfilterAliases
+ 1,
224 sizeof(PictFilterAliasRec
));
226 aliases
= malloc(sizeof(PictFilterAliasRec
));
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
;
239 PictureFindFilter(ScreenPtr pScreen
, char *name
, int len
)
241 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
242 int id
= PictureGetFilterId(name
, len
, FALSE
);
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
;
253 /* find the filter */
254 for (i
= 0; i
< ps
->nfilters
; i
++)
255 if (ps
->filters
[i
].id
== id
)
256 return &ps
->filters
[i
];
261 convolutionFilterValidateParams(ScreenPtr pScreen
,
264 int nparams
, int *width
, int *height
)
271 if (xFixedFrac(params
[0]) || xFixedFrac(params
[1]))
274 w
= xFixedToInt(params
[0]);
275 h
= xFixedToInt(params
[1]);
287 PictureSetDefaultFilters(ScreenPtr pScreen
)
290 if (!PictureSetDefaultIds())
292 if (PictureAddFilter(pScreen
, FilterNearest
, 0, 1, 1) < 0)
294 if (PictureAddFilter(pScreen
, FilterBilinear
, 0, 2, 2) < 0)
297 if (!PictureSetFilterAlias(pScreen
, FilterNearest
, FilterFast
))
299 if (!PictureSetFilterAlias(pScreen
, FilterBilinear
, FilterGood
))
301 if (!PictureSetFilterAlias(pScreen
, FilterBilinear
, FilterBest
))
305 (pScreen
, FilterConvolution
, convolutionFilterValidateParams
, 0, 0) < 0)
312 PictureResetFilters(ScreenPtr pScreen
)
314 PictureScreenPtr ps
= GetPictureScreen(pScreen
);
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
,
328 PictFilterPtr pFilter
;
331 if (pPicture
->pDrawable
!= NULL
)
332 pScreen
= pPicture
->pDrawable
->pScreen
;
334 pScreen
= screenInfo
.screens
[0];
336 pFilter
= PictureFindFilter(pScreen
, name
, len
);
341 if (pPicture
->pDrawable
== NULL
) {
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
)
355 return SetPicturePictFilter(pPicture
, pFilter
, params
, nparams
);
359 SetPicturePictFilter(PicturePtr pPicture
, PictFilterPtr pFilter
,
360 xFixed
* params
, int nparams
)
365 if (pPicture
->pDrawable
)
366 pScreen
= pPicture
->pDrawable
->pScreen
;
368 pScreen
= screenInfo
.screens
[0];
370 if (pFilter
->ValidateParams
) {
373 if (!(*pFilter
->ValidateParams
)
374 (pScreen
, pFilter
->id
, params
, nparams
, &width
, &height
))
380 if (nparams
!= pPicture
->filter_nparams
) {
381 xFixed
*new_params
= xallocarray(nparams
, sizeof(xFixed
));
383 if (!new_params
&& nparams
)
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
);
397 result
= (*ps
->ChangePictureFilter
) (pPicture
, pPicture
->filter
,