… | |
… | |
32 | |
32 | |
33 | #ifndef FilterConvolution |
33 | #ifndef FilterConvolution |
34 | #define FilterConvolution "convolution" |
34 | #define FilterConvolution "convolution" |
35 | #endif |
35 | #endif |
36 | |
36 | |
|
|
37 | #ifndef RepeatPad |
|
|
38 | #define RepeatPad True |
|
|
39 | #endif |
|
|
40 | |
37 | #ifdef HAVE_BG_PIXMAP |
41 | #ifdef HAVE_BG_PIXMAP |
38 | # if XRENDER |
42 | # if XRENDER |
39 | static Picture |
43 | static Picture |
40 | create_xrender_mask (Display *dpy, Drawable drawable, Bool argb, Bool component_alpha) |
44 | create_xrender_mask (Display *dpy, Drawable drawable, Bool argb, Bool component_alpha) |
41 | { |
45 | { |
… | |
… | |
125 | |
129 | |
126 | return false; |
130 | return false; |
127 | } |
131 | } |
128 | |
132 | |
129 | # ifdef BG_IMAGE_FROM_FILE |
133 | # ifdef BG_IMAGE_FROM_FILE |
130 | static inline bool |
|
|
131 | check_set_scale_value (int geom_flags, int flag, unsigned int &scale, unsigned int new_value) |
|
|
132 | { |
|
|
133 | if (geom_flags & flag) |
|
|
134 | { |
|
|
135 | if (new_value > 1000) |
|
|
136 | new_value = 1000; |
|
|
137 | if (new_value != scale) |
|
|
138 | { |
|
|
139 | scale = new_value; |
|
|
140 | return true; |
|
|
141 | } |
|
|
142 | } |
|
|
143 | return false; |
|
|
144 | } |
|
|
145 | |
|
|
146 | static inline bool |
|
|
147 | check_set_align_value (int geom_flags, int flag, int &align, int new_value) |
|
|
148 | { |
|
|
149 | if (geom_flags & flag) |
|
|
150 | { |
|
|
151 | if (new_value < -100) |
|
|
152 | new_value = -100; |
|
|
153 | else if (new_value > 200) |
|
|
154 | new_value = 200; |
|
|
155 | if (new_value != align) |
|
|
156 | { |
|
|
157 | align = new_value; |
|
|
158 | return true; |
|
|
159 | } |
|
|
160 | } |
|
|
161 | return false; |
|
|
162 | } |
|
|
163 | |
|
|
164 | static inline int |
134 | static inline int |
165 | make_align_position (int align, int window_size, int image_size) |
135 | make_align_position (int align, int window_size, int image_size) |
166 | { |
136 | { |
167 | int diff = window_size - image_size; |
137 | int diff = window_size - image_size; |
168 | int smaller = min (image_size, window_size); |
138 | int smaller = min (image_size, window_size); |
… | |
… | |
187 | src_pos = -pos; |
157 | src_pos = -pos; |
188 | dst_pos = 0; |
158 | dst_pos = 0; |
189 | dst_size += pos; |
159 | dst_size += pos; |
190 | } |
160 | } |
191 | |
161 | |
192 | if (dst_pos + dst_size > target_size) |
|
|
193 | dst_size = target_size - dst_pos; |
162 | min_it (dst_size, target_size - dst_pos); |
194 | return src_pos; |
163 | return src_pos; |
195 | } |
164 | } |
196 | |
165 | |
197 | bool |
166 | bool |
198 | rxvt_term::bg_set_geometry (const char *geom, bool update) |
167 | rxvt_term::bg_set_geometry (const char *geom, bool update) |
199 | { |
168 | { |
200 | bool changed = false; |
169 | bool changed = false; |
201 | int geom_flags = 0; |
170 | int geom_flags = 0; |
202 | int x = 0, y = 0; |
171 | int x = h_align; |
|
|
172 | int y = v_align; |
203 | unsigned int w = 0, h = 0; |
173 | unsigned int w = h_scale; |
|
|
174 | unsigned int h = v_scale; |
204 | unsigned long new_flags = 0; |
175 | unsigned long new_flags = 0; |
205 | |
176 | |
206 | if (geom == NULL) |
177 | if (geom == NULL) |
207 | return false; |
178 | return false; |
208 | |
179 | |
… | |
… | |
317 | w = h = defaultScale; |
288 | w = h = defaultScale; |
318 | else if (!(geom_flags & HeightValue)) |
289 | else if (!(geom_flags & HeightValue)) |
319 | h = w; |
290 | h = w; |
320 | else if (!(geom_flags & WidthValue)) |
291 | else if (!(geom_flags & WidthValue)) |
321 | w = h; |
292 | w = h; |
322 | |
|
|
323 | geom_flags |= WidthValue|HeightValue|XValue|YValue; |
|
|
324 | } |
293 | } |
325 | |
294 | |
326 | if (check_set_scale_value (geom_flags, WidthValue, h_scale, w)) changed = true; |
295 | min_it (w, 1000); |
327 | if (check_set_scale_value (geom_flags, HeightValue, v_scale, h)) changed = true; |
296 | min_it (h, 1000); |
328 | if (check_set_align_value (geom_flags, XValue, h_align, x)) changed = true; |
297 | clamp_it (x, -100, 200); |
329 | if (check_set_align_value (geom_flags, YValue, v_align, y)) changed = true; |
298 | clamp_it (y, -100, 200); |
330 | |
299 | |
331 | if (new_flags != bg_flags) |
300 | if (bg_flags != new_flags |
|
|
301 | || h_scale != w |
|
|
302 | || v_scale != h |
|
|
303 | || h_align != x |
|
|
304 | || v_align != y) |
332 | { |
305 | { |
333 | bg_flags = new_flags; |
306 | bg_flags = new_flags; |
|
|
307 | h_scale = w; |
|
|
308 | v_scale = h; |
|
|
309 | h_align = x; |
|
|
310 | v_align = y; |
334 | changed = true; |
311 | changed = true; |
335 | } |
312 | } |
336 | |
313 | |
337 | return changed; |
314 | return changed; |
338 | } |
315 | } |
… | |
… | |
392 | if (tr_flags & BG_NEEDS_TINT) |
369 | if (tr_flags & BG_NEEDS_TINT) |
393 | { |
370 | { |
394 | ShadingInfo as_shade; |
371 | ShadingInfo as_shade; |
395 | as_shade.shading = shade; |
372 | as_shade.shading = shade; |
396 | |
373 | |
397 | rgba c; |
374 | rgba c (rgba::MAX_CC,rgba::MAX_CC,rgba::MAX_CC); |
|
|
375 | if (bg_flags & BG_TINT_SET) |
398 | tint.get (c); |
376 | tint.get (c); |
399 | as_shade.tintColor.red = c.r; |
377 | as_shade.tintColor.red = c.r; |
400 | as_shade.tintColor.green = c.g; |
378 | as_shade.tintColor.green = c.g; |
401 | as_shade.tintColor.blue = c.b; |
379 | as_shade.tintColor.blue = c.b; |
402 | |
380 | |
403 | background_tint = shading2tint32 (&as_shade); |
381 | background_tint = shading2tint32 (&as_shade); |
… | |
… | |
830 | Picture mask = create_xrender_mask (dpy, vt, False, False); |
808 | Picture mask = create_xrender_mask (dpy, vt, False, False); |
831 | |
809 | |
832 | XRenderColor mask_c; |
810 | XRenderColor mask_c; |
833 | |
811 | |
834 | mask_c.alpha = 0x8000; |
812 | mask_c.alpha = 0x8000; |
835 | mask_c.red = 0; |
813 | mask_c.red = |
836 | mask_c.green = 0; |
814 | mask_c.green = |
837 | mask_c.blue = 0; |
815 | mask_c.blue = 0; |
838 | XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); |
816 | XRenderFillRectangle (dpy, PictOpSrc, mask, &mask_c, 0, 0, 1, 1); |
|
|
817 | |
839 | XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, target_width, target_height); |
818 | XRenderComposite (dpy, PictOpOver, src, mask, dst, 0, 0, 0, 0, 0, 0, target_width, target_height); |
840 | |
819 | |
841 | XRenderFreePicture (dpy, src); |
820 | XRenderFreePicture (dpy, src); |
842 | XRenderFreePicture (dpy, dst); |
821 | XRenderFreePicture (dpy, dst); |
843 | XRenderFreePicture (dpy, mask); |
822 | XRenderFreePicture (dpy, mask); |
… | |
… | |
955 | { |
934 | { |
956 | changed = true; |
935 | changed = true; |
957 | v_blurRadius = vr; |
936 | v_blurRadius = vr; |
958 | } |
937 | } |
959 | |
938 | |
960 | if (v_blurRadius == 0 && h_blurRadius == 0) |
939 | if (h_blurRadius == 0 || v_blurRadius == 0) |
961 | bg_flags &= ~BG_NEEDS_BLUR; |
940 | bg_flags &= ~BG_NEEDS_BLUR; |
962 | else |
941 | else |
963 | bg_flags |= BG_NEEDS_BLUR; |
942 | bg_flags |= BG_NEEDS_BLUR; |
964 | |
943 | |
965 | return changed; |
944 | return changed; |
… | |
… | |
971 | rgba c; |
950 | rgba c; |
972 | bool has_shade = shade != 100; |
951 | bool has_shade = shade != 100; |
973 | |
952 | |
974 | bg_flags &= ~BG_TINT_FLAGS; |
953 | bg_flags &= ~BG_TINT_FLAGS; |
975 | |
954 | |
|
|
955 | if (bg_flags & BG_TINT_SET) |
|
|
956 | { |
976 | tint.get (c); |
957 | tint.get (c); |
977 | |
|
|
978 | if (!has_shade |
958 | if (!has_shade |
979 | && (c.r <= 0x00ff || c.r >= 0xff00) |
959 | && (c.r <= 0x00ff || c.r >= 0xff00) |
980 | && (c.g <= 0x00ff || c.g >= 0xff00) |
960 | && (c.g <= 0x00ff || c.g >= 0xff00) |
981 | && (c.b <= 0x00ff || c.b >= 0xff00)) |
961 | && (c.b <= 0x00ff || c.b >= 0xff00)) |
982 | bg_flags |= BG_TINT_BITAND; |
962 | bg_flags |= BG_TINT_BITAND; |
|
|
963 | } |
983 | |
964 | |
984 | if (has_shade |
965 | if (has_shade || (bg_flags & BG_TINT_SET)) |
985 | || c.r < 0xff00 |
|
|
986 | || c.g < 0xff00 |
|
|
987 | || c.b < 0xff00) |
|
|
988 | bg_flags |= BG_NEEDS_TINT; |
966 | bg_flags |= BG_NEEDS_TINT; |
989 | } |
967 | } |
990 | |
968 | |
991 | bool |
969 | bool |
992 | rxvt_term::bg_set_tint (rxvt_color &new_tint) |
970 | rxvt_term::bg_set_tint (rxvt_color &new_tint) |
993 | { |
971 | { |
994 | if (tint != new_tint) |
972 | if (!(bg_flags & BG_TINT_SET) || tint != new_tint) |
995 | { |
973 | { |
996 | tint = new_tint; |
974 | tint = new_tint; |
|
|
975 | bg_flags |= BG_TINT_SET; |
997 | set_tint_shade_flags (); |
976 | set_tint_shade_flags (); |
998 | return true; |
977 | return true; |
999 | } |
978 | } |
1000 | |
979 | |
1001 | return false; |
980 | return false; |
… | |
… | |
1042 | params[i+2] = XDoubleToFixed (kernel[i] / sum); |
1021 | params[i+2] = XDoubleToFixed (kernel[i] / sum); |
1043 | } |
1022 | } |
1044 | #endif |
1023 | #endif |
1045 | |
1024 | |
1046 | bool |
1025 | bool |
1047 | rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height) |
1026 | rxvt_term::blur_pixmap (Pixmap pixmap, Visual *visual, int width, int height, int depth) |
1048 | { |
1027 | { |
1049 | bool ret = false; |
1028 | bool ret = false; |
1050 | #if XRENDER |
1029 | #if XRENDER |
1051 | if (!(bg_flags & BG_HAS_RENDER_CONV)) |
1030 | if (!(bg_flags & BG_HAS_RENDER_CONV)) |
1052 | return false; |
1031 | return false; |
1053 | |
1032 | |
1054 | int size = max (h_blurRadius, v_blurRadius) * 2 + 1; |
1033 | int size = max (h_blurRadius, v_blurRadius) * 2 + 1; |
1055 | double *kernel = (double *)malloc (size * sizeof (double)); |
1034 | double *kernel = (double *)malloc (size * sizeof (double)); |
1056 | XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); |
1035 | XFixed *params = (XFixed *)malloc ((size + 2) * sizeof (XFixed)); |
1057 | |
1036 | |
|
|
1037 | XRenderPictureAttributes pa; |
1058 | XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); |
1038 | XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); |
1059 | |
1039 | |
|
|
1040 | pa.repeat = RepeatPad; |
1060 | Picture src = XRenderCreatePicture (dpy, pixmap, format, 0, 0); |
1041 | Picture src = XRenderCreatePicture (dpy, pixmap, format, CPRepeat, &pa); |
|
|
1042 | Pixmap tmp = XCreatePixmap (dpy, pixmap, width, height, depth); |
1061 | Picture dst = XRenderCreatePicture (dpy, pixmap, format, 0, 0); |
1043 | Picture dst = XRenderCreatePicture (dpy, tmp, format, CPRepeat, &pa); |
|
|
1044 | XFreePixmap (dpy, tmp); |
1062 | |
1045 | |
1063 | if (kernel && params) |
1046 | if (kernel && params) |
1064 | { |
1047 | { |
1065 | if (h_blurRadius) |
|
|
1066 | { |
|
|
1067 | size = h_blurRadius * 2 + 1; |
1048 | size = h_blurRadius * 2 + 1; |
1068 | get_gaussian_kernel (h_blurRadius, size, kernel, params); |
1049 | get_gaussian_kernel (h_blurRadius, size, kernel, params); |
1069 | |
1050 | |
1070 | XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); |
1051 | XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); |
1071 | XRenderComposite (dpy, |
1052 | XRenderComposite (dpy, |
1072 | PictOpSrc, |
1053 | PictOpSrc, |
1073 | src, |
1054 | src, |
1074 | None, |
1055 | None, |
1075 | dst, |
1056 | dst, |
1076 | 0, 0, |
1057 | 0, 0, |
1077 | 0, 0, |
1058 | 0, 0, |
1078 | 0, 0, |
1059 | 0, 0, |
1079 | width, height); |
1060 | width, height); |
1080 | } |
|
|
1081 | |
1061 | |
1082 | if (v_blurRadius) |
1062 | ::swap (src, dst); |
1083 | { |
1063 | |
1084 | size = v_blurRadius * 2 + 1; |
1064 | size = v_blurRadius * 2 + 1; |
1085 | get_gaussian_kernel (v_blurRadius, size, kernel, params); |
1065 | get_gaussian_kernel (v_blurRadius, size, kernel, params); |
1086 | ::swap (params[0], params[1]); |
1066 | ::swap (params[0], params[1]); |
1087 | |
1067 | |
1088 | XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); |
1068 | XRenderSetPictureFilter (dpy, src, FilterConvolution, params, size+2); |
1089 | XRenderComposite (dpy, |
1069 | XRenderComposite (dpy, |
1090 | PictOpSrc, |
1070 | PictOpSrc, |
1091 | src, |
1071 | src, |
1092 | None, |
1072 | None, |
1093 | dst, |
1073 | dst, |
1094 | 0, 0, |
1074 | 0, 0, |
1095 | 0, 0, |
1075 | 0, 0, |
1096 | 0, 0, |
1076 | 0, 0, |
1097 | width, height); |
1077 | width, height); |
1098 | } |
|
|
1099 | |
1078 | |
1100 | ret = true; |
1079 | ret = true; |
1101 | } |
1080 | } |
1102 | |
1081 | |
1103 | free (kernel); |
1082 | free (kernel); |
… | |
… | |
1133 | } |
1112 | } |
1134 | } |
1113 | } |
1135 | # if XRENDER |
1114 | # if XRENDER |
1136 | else if (bg_flags & BG_HAS_RENDER) |
1115 | else if (bg_flags & BG_HAS_RENDER) |
1137 | { |
1116 | { |
1138 | rgba c; |
1117 | rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); |
1139 | |
1118 | |
|
|
1119 | if (bg_flags & BG_TINT_SET) |
1140 | tint.get (c); |
1120 | tint.get (c); |
1141 | |
1121 | |
1142 | if (shade <= 100) |
1122 | if (shade <= 100) |
1143 | { |
1123 | { |
1144 | c.r = c.r * shade / 100; |
1124 | c.r = c.r * shade / 100; |
1145 | c.g = c.g * shade / 100; |
1125 | c.g = c.g * shade / 100; |
… | |
… | |
1171 | mask_c.alpha = 0; |
1151 | mask_c.alpha = 0; |
1172 | mask_c.red = 0xffff - c.r; |
1152 | mask_c.red = 0xffff - c.r; |
1173 | mask_c.green = 0xffff - c.g; |
1153 | mask_c.green = 0xffff - c.g; |
1174 | mask_c.blue = 0xffff - c.b; |
1154 | mask_c.blue = 0xffff - c.b; |
1175 | XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); |
1155 | XRenderFillRectangle (dpy, PictOpSrc, mask_pic, &mask_c, 0, 0, 1, 1); |
|
|
1156 | |
1176 | XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height); |
1157 | XRenderComposite (dpy, PictOpOver, overlay_pic, mask_pic, back_pic, 0, 0, 0, 0, 0, 0, width, height); |
1177 | |
1158 | |
1178 | if (shade > 100) |
1159 | if (shade > 100) |
1179 | { |
1160 | { |
1180 | mask_c.red = mask_c.green = mask_c.blue = 0xffff * (shade - 100) / 100; |
|
|
1181 | mask_c.alpha = 0; |
1161 | mask_c.alpha = 0; |
|
|
1162 | mask_c.red = |
|
|
1163 | mask_c.green = |
|
|
1164 | mask_c.blue = 0xffff * (shade - 100) / 100; |
1182 | XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); |
1165 | XRenderFillRectangle (dpy, PictOpSrc, overlay_pic, &mask_c, 0, 0, 1, 1); |
1183 | |
1166 | |
1184 | XRenderComposite (dpy, PictOpOver, overlay_pic, None, back_pic, 0, 0, 0, 0, 0, 0, width, height); |
1167 | XRenderComposite (dpy, PictOpOver, overlay_pic, None, back_pic, 0, 0, 0, 0, 0, 0, width, height); |
1185 | } |
1168 | } |
1186 | |
1169 | |
… | |
… | |
1298 | |
1281 | |
1299 | if (!(bg_flags & BG_CLIENT_RENDER)) |
1282 | if (!(bg_flags & BG_CLIENT_RENDER)) |
1300 | { |
1283 | { |
1301 | if (bg_flags & BG_NEEDS_BLUR) |
1284 | if (bg_flags & BG_NEEDS_BLUR) |
1302 | { |
1285 | { |
1303 | if (blur_pixmap (bg_pixmap, visual, window_width, window_height)) |
1286 | if (blur_pixmap (bg_pixmap, visual, window_width, window_height, depth)) |
1304 | result &= ~BG_NEEDS_BLUR; |
1287 | result &= ~BG_NEEDS_BLUR; |
1305 | } |
1288 | } |
1306 | if (bg_flags & BG_NEEDS_TINT) |
1289 | if (bg_flags & BG_NEEDS_TINT) |
1307 | { |
1290 | { |
1308 | if (tint_pixmap (bg_pixmap, visual, window_width, window_height)) |
1291 | if (tint_pixmap (bg_pixmap, visual, window_width, window_height)) |
… | |
… | |
1353 | # ifdef ENABLE_TRANSPARENCY |
1336 | # ifdef ENABLE_TRANSPARENCY |
1354 | if (bg_flags & BG_IS_TRANSPARENT) |
1337 | if (bg_flags & BG_IS_TRANSPARENT) |
1355 | { |
1338 | { |
1356 | /* we need to re-generate transparency pixmap in that case ! */ |
1339 | /* we need to re-generate transparency pixmap in that case ! */ |
1357 | tr_flags = make_transparency_pixmap (); |
1340 | tr_flags = make_transparency_pixmap (); |
1358 | if (tr_flags == 0) |
1341 | if (tr_flags) |
1359 | return false; |
|
|
1360 | bg_flags |= BG_IS_VALID; |
1342 | bg_flags |= BG_IS_VALID; |
1361 | } |
1343 | } |
1362 | # endif |
1344 | # endif |
1363 | |
1345 | |
1364 | # ifdef BG_IMAGE_FROM_FILE |
1346 | # ifdef BG_IMAGE_FROM_FILE |
1365 | if ((bg_flags & BG_IS_FROM_FILE) |
1347 | if ((bg_flags & BG_IS_FROM_FILE) |
… | |
… | |
1389 | |
1371 | |
1390 | void |
1372 | void |
1391 | rxvt_term::bg_init () |
1373 | rxvt_term::bg_init () |
1392 | { |
1374 | { |
1393 | #ifdef ENABLE_TRANSPARENCY |
1375 | #ifdef ENABLE_TRANSPARENCY |
1394 | rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); |
|
|
1395 | tint.set (this, c); |
|
|
1396 | shade = 100; |
1376 | shade = 100; |
1397 | #endif |
1377 | #endif |
1398 | |
1378 | |
1399 | bg_flags &= ~(BG_HAS_RENDER | BG_HAS_RENDER_CONV); |
1379 | bg_flags &= ~(BG_HAS_RENDER | BG_HAS_RENDER_CONV); |
1400 | #if XRENDER |
1380 | #if XRENDER |
… | |
… | |
1503 | break; |
1483 | break; |
1504 | default: |
1484 | default: |
1505 | return; /* we do not support this color depth */ |
1485 | return; /* we do not support this color depth */ |
1506 | } |
1486 | } |
1507 | |
1487 | |
1508 | rgba c; |
1488 | rgba c (rgba::MAX_CC, rgba::MAX_CC, rgba::MAX_CC); |
1509 | |
1489 | |
|
|
1490 | if (bg_flags & BG_TINT_SET) |
1510 | tint.get (c); |
1491 | tint.get (c); |
1511 | |
1492 | |
1512 | /* prepare limits for color transformation (each channel is handled separately) */ |
1493 | /* prepare limits for color transformation (each channel is handled separately) */ |
1513 | if (shade > 100) |
1494 | if (shade > 100) |
1514 | { |
1495 | { |
1515 | c.r = c.r * (200 - shade) / 100; |
1496 | c.r = c.r * (200 - shade) / 100; |