comparison src/xterm.c @ 55030:44eb66585062

(x_draw_relief_rect): Add top_p and bot_p args. (x_draw_glyph_string_box): Fix call to x_draw_relief_rect. (x_draw_image_foreground, x_draw_image_relief) (x_draw_image_foreground_1, x_draw_image_glyph_string): Draw sliced images.
author Kim F. Storm <storm@cua.dk>
date Tue, 20 Apr 2004 22:19:23 +0000
parents edff9ce01ed0
children 535ccf62b57f 30dd490f06f2
comparison
equal deleted inserted replaced
55029:01ecdd56871c 55030:44eb66585062
979 static void x_draw_image_foreground P_ ((struct glyph_string *)); 979 static void x_draw_image_foreground P_ ((struct glyph_string *));
980 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap)); 980 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
981 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int, 981 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
982 int, int, int)); 982 int, int, int));
983 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int, 983 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
984 int, int, int, int, XRectangle *)); 984 int, int, int, int, int, int,
985 XRectangle *));
985 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, 986 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
986 int, int, int, XRectangle *)); 987 int, int, int, XRectangle *));
987 988
988 #if GLYPH_DEBUG 989 #if GLYPH_DEBUG
989 static void x_check_font P_ ((struct frame *, XFontStruct *)); 990 static void x_check_font P_ ((struct frame *, XFontStruct *));
2017 side of the rectangle. CLIP_RECT is the clipping rectangle to use 2018 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2018 when drawing. */ 2019 when drawing. */
2019 2020
2020 static void 2021 static void
2021 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, 2022 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2022 raised_p, left_p, right_p, clip_rect) 2023 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2023 struct frame *f; 2024 struct frame *f;
2024 int left_x, top_y, right_x, bottom_y, width, left_p, right_p, raised_p; 2025 int left_x, top_y, right_x, bottom_y, width;
2026 int top_p, bot_p, left_p, right_p, raised_p;
2025 XRectangle *clip_rect; 2027 XRectangle *clip_rect;
2026 { 2028 {
2027 Display *dpy = FRAME_X_DISPLAY (f); 2029 Display *dpy = FRAME_X_DISPLAY (f);
2028 Window window = FRAME_X_WINDOW (f); 2030 Window window = FRAME_X_WINDOW (f);
2029 int i; 2031 int i;
2034 else 2036 else
2035 gc = f->output_data.x->black_relief.gc; 2037 gc = f->output_data.x->black_relief.gc;
2036 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted); 2038 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2037 2039
2038 /* Top. */ 2040 /* Top. */
2039 for (i = 0; i < width; ++i) 2041 if (top_p)
2040 XDrawLine (dpy, window, gc, 2042 for (i = 0; i < width; ++i)
2041 left_x + i * left_p, top_y + i, 2043 XDrawLine (dpy, window, gc,
2042 right_x + 1 - i * right_p, top_y + i); 2044 left_x + i * left_p, top_y + i,
2045 right_x + 1 - i * right_p, top_y + i);
2043 2046
2044 /* Left. */ 2047 /* Left. */
2045 if (left_p) 2048 if (left_p)
2046 for (i = 0; i < width; ++i) 2049 for (i = 0; i < width; ++i)
2047 XDrawLine (dpy, window, gc, 2050 XDrawLine (dpy, window, gc,
2053 else 2056 else
2054 gc = f->output_data.x->white_relief.gc; 2057 gc = f->output_data.x->white_relief.gc;
2055 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted); 2058 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
2056 2059
2057 /* Bottom. */ 2060 /* Bottom. */
2058 for (i = 0; i < width; ++i) 2061 if (bot_p)
2059 XDrawLine (dpy, window, gc, 2062 for (i = 0; i < width; ++i)
2060 left_x + i * left_p, bottom_y - i, 2063 XDrawLine (dpy, window, gc,
2061 right_x + 1 - i * right_p, bottom_y - i); 2064 left_x + i * left_p, bottom_y - i,
2065 right_x + 1 - i * right_p, bottom_y - i);
2062 2066
2063 /* Right. */ 2067 /* Right. */
2064 if (right_p) 2068 if (right_p)
2065 for (i = 0; i < width; ++i) 2069 for (i = 0; i < width; ++i)
2066 XDrawLine (dpy, window, gc, 2070 XDrawLine (dpy, window, gc,
2164 left_p, right_p, &clip_rect); 2168 left_p, right_p, &clip_rect);
2165 else 2169 else
2166 { 2170 {
2167 x_setup_relief_colors (s); 2171 x_setup_relief_colors (s);
2168 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, 2172 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2169 width, raised_p, left_p, right_p, &clip_rect); 2173 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2170 } 2174 }
2171 } 2175 }
2172 2176
2173 2177
2174 /* Draw foreground of image glyph string S. */ 2178 /* Draw foreground of image glyph string S. */
2175 2179
2176 static void 2180 static void
2177 x_draw_image_foreground (s) 2181 x_draw_image_foreground (s)
2178 struct glyph_string *s; 2182 struct glyph_string *s;
2179 { 2183 {
2180 int x; 2184 int x = s->x;
2181 int y = s->ybase - image_ascent (s->img, s->face); 2185 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2182 2186
2183 /* If first glyph of S has a left box line, start drawing it to the 2187 /* If first glyph of S has a left box line, start drawing it to the
2184 right of that line. */ 2188 right of that line. */
2185 if (s->face->box != FACE_NO_BOX 2189 if (s->face->box != FACE_NO_BOX
2186 && s->first_glyph->left_box_line_p) 2190 && s->first_glyph->left_box_line_p
2187 x = s->x + abs (s->face->box_line_width); 2191 && s->slice.x == 0)
2188 else 2192 x += abs (s->face->box_line_width);
2189 x = s->x;
2190 2193
2191 /* If there is a margin around the image, adjust x- and y-position 2194 /* If there is a margin around the image, adjust x- and y-position
2192 by that margin. */ 2195 by that margin. */
2193 x += s->img->hmargin; 2196 if (s->slice.x == 0)
2194 y += s->img->vmargin; 2197 x += s->img->hmargin;
2198 if (s->slice.y == 0)
2199 y += s->img->vmargin;
2195 2200
2196 if (s->img->pixmap) 2201 if (s->img->pixmap)
2197 { 2202 {
2198 if (s->img->mask) 2203 if (s->img->mask)
2199 { 2204 {
2214 XChangeGC (s->display, s->gc, mask, &xgcv); 2219 XChangeGC (s->display, s->gc, mask, &xgcv);
2215 2220
2216 get_glyph_string_clip_rect (s, &clip_rect); 2221 get_glyph_string_clip_rect (s, &clip_rect);
2217 image_rect.x = x; 2222 image_rect.x = x;
2218 image_rect.y = y; 2223 image_rect.y = y;
2219 image_rect.width = s->img->width; 2224 image_rect.width = s->slice.width;
2220 image_rect.height = s->img->height; 2225 image_rect.height = s->slice.height;
2221 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) 2226 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2222 XCopyArea (s->display, s->img->pixmap, s->window, s->gc, 2227 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2223 r.x - x, r.y - y, r.width, r.height, r.x, r.y); 2228 s->slice.x + r.x - x, s->slice.y + r.y - y,
2229 r.width, r.height, r.x, r.y);
2224 } 2230 }
2225 else 2231 else
2226 { 2232 {
2227 XRectangle clip_rect, image_rect, r; 2233 XRectangle clip_rect, image_rect, r;
2228 2234
2229 get_glyph_string_clip_rect (s, &clip_rect); 2235 get_glyph_string_clip_rect (s, &clip_rect);
2230 image_rect.x = x; 2236 image_rect.x = x;
2231 image_rect.y = y; 2237 image_rect.y = y;
2232 image_rect.width = s->img->width; 2238 image_rect.width = s->slice.width;
2233 image_rect.height = s->img->height; 2239 image_rect.height = s->slice.height;
2234 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) 2240 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2235 XCopyArea (s->display, s->img->pixmap, s->window, s->gc, 2241 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2236 r.x - x, r.y - y, r.width, r.height, r.x, r.y); 2242 s->slice.x + r.x - x, s->slice.y + r.y - y,
2243 r.width, r.height, r.x, r.y);
2244
2245 /* When the image has a mask, we can expect that at
2246 least part of a mouse highlight or a block cursor will
2247 be visible. If the image doesn't have a mask, make
2248 a block cursor visible by drawing a rectangle around
2249 the image. I believe it's looking better if we do
2250 nothing here for mouse-face. */
2251 if (s->hl == DRAW_CURSOR)
2252 {
2253 int r = s->img->relief;
2254 if (r < 0) r = -r;
2255 XDrawRectangle (s->display, s->window, s->gc,
2256 x - r, y - r,
2257 s->slice.width + r*2 - 1,
2258 s->slice.height + r*2 - 1);
2259 }
2260 }
2261 }
2262 else
2263 /* Draw a rectangle if image could not be loaded. */
2264 XDrawRectangle (s->display, s->window, s->gc, x, y,
2265 s->slice.width - 1, s->slice.height - 1);
2266 }
2267
2268
2269 /* Draw a relief around the image glyph string S. */
2270
2271 static void
2272 x_draw_image_relief (s)
2273 struct glyph_string *s;
2274 {
2275 int x0, y0, x1, y1, thick, raised_p;
2276 XRectangle r;
2277 int x = s->x;
2278 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2279
2280 /* If first glyph of S has a left box line, start drawing it to the
2281 right of that line. */
2282 if (s->face->box != FACE_NO_BOX
2283 && s->first_glyph->left_box_line_p
2284 && s->slice.x == 0)
2285 x += abs (s->face->box_line_width);
2286
2287 /* If there is a margin around the image, adjust x- and y-position
2288 by that margin. */
2289 if (s->slice.x == 0)
2290 x += s->img->hmargin;
2291 if (s->slice.y == 0)
2292 y += s->img->vmargin;
2293
2294 if (s->hl == DRAW_IMAGE_SUNKEN
2295 || s->hl == DRAW_IMAGE_RAISED)
2296 {
2297 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2298 raised_p = s->hl == DRAW_IMAGE_RAISED;
2299 }
2300 else
2301 {
2302 thick = abs (s->img->relief);
2303 raised_p = s->img->relief > 0;
2304 }
2305
2306 x0 = x - thick;
2307 y0 = y - thick;
2308 x1 = x + s->slice.width + thick - 1;
2309 y1 = y + s->slice.height + thick - 1;
2310
2311 x_setup_relief_colors (s);
2312 get_glyph_string_clip_rect (s, &r);
2313 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2314 s->slice.y == 0,
2315 s->slice.y + s->slice.height == s->img->height,
2316 s->slice.x == 0,
2317 s->slice.x + s->slice.width == s->img->width,
2318 &r);
2319 }
2320
2321
2322 /* Draw the foreground of image glyph string S to PIXMAP. */
2323
2324 static void
2325 x_draw_image_foreground_1 (s, pixmap)
2326 struct glyph_string *s;
2327 Pixmap pixmap;
2328 {
2329 int x = 0;
2330 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2331
2332 /* If first glyph of S has a left box line, start drawing it to the
2333 right of that line. */
2334 if (s->face->box != FACE_NO_BOX
2335 && s->first_glyph->left_box_line_p
2336 && s->slice.x == 0)
2337 x += abs (s->face->box_line_width);
2338
2339 /* If there is a margin around the image, adjust x- and y-position
2340 by that margin. */
2341 if (s->slice.x == 0)
2342 x += s->img->hmargin;
2343 if (s->slice.y == 0)
2344 y += s->img->vmargin;
2345
2346 if (s->img->pixmap)
2347 {
2348 if (s->img->mask)
2349 {
2350 /* We can't set both a clip mask and use XSetClipRectangles
2351 because the latter also sets a clip mask. We also can't
2352 trust on the shape extension to be available
2353 (XShapeCombineRegion). So, compute the rectangle to draw
2354 manually. */
2355 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2356 | GCFunction);
2357 XGCValues xgcv;
2358
2359 xgcv.clip_mask = s->img->mask;
2360 xgcv.clip_x_origin = x;
2361 xgcv.clip_y_origin = y;
2362 xgcv.function = GXcopy;
2363 XChangeGC (s->display, s->gc, mask, &xgcv);
2364
2365 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2366 s->slice.x, s->slice.y,
2367 s->slice.width, s->slice.height, x, y);
2368 XSetClipMask (s->display, s->gc, None);
2369 }
2370 else
2371 {
2372 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2373 s->slice.x, s->slice.y,
2374 s->slice.width, s->slice.height, x, y);
2237 2375
2238 /* When the image has a mask, we can expect that at 2376 /* When the image has a mask, we can expect that at
2239 least part of a mouse highlight or a block cursor will 2377 least part of a mouse highlight or a block cursor will
2240 be visible. If the image doesn't have a mask, make 2378 be visible. If the image doesn't have a mask, make
2241 a block cursor visible by drawing a rectangle around 2379 a block cursor visible by drawing a rectangle around
2244 if (s->hl == DRAW_CURSOR) 2382 if (s->hl == DRAW_CURSOR)
2245 { 2383 {
2246 int r = s->img->relief; 2384 int r = s->img->relief;
2247 if (r < 0) r = -r; 2385 if (r < 0) r = -r;
2248 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r, 2386 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
2249 s->img->width + r*2 - 1, s->img->height + r*2 - 1); 2387 s->slice.width + r*2 - 1,
2250 } 2388 s->slice.height + r*2 - 1);
2251 }
2252 }
2253 else
2254 /* Draw a rectangle if image could not be loaded. */
2255 XDrawRectangle (s->display, s->window, s->gc, x, y,
2256 s->img->width - 1, s->img->height - 1);
2257 }
2258
2259
2260 /* Draw a relief around the image glyph string S. */
2261
2262 static void
2263 x_draw_image_relief (s)
2264 struct glyph_string *s;
2265 {
2266 int x0, y0, x1, y1, thick, raised_p;
2267 XRectangle r;
2268 int x;
2269 int y = s->ybase - image_ascent (s->img, s->face);
2270
2271 /* If first glyph of S has a left box line, start drawing it to the
2272 right of that line. */
2273 if (s->face->box != FACE_NO_BOX
2274 && s->first_glyph->left_box_line_p)
2275 x = s->x + abs (s->face->box_line_width);
2276 else
2277 x = s->x;
2278
2279 /* If there is a margin around the image, adjust x- and y-position
2280 by that margin. */
2281 x += s->img->hmargin;
2282 y += s->img->vmargin;
2283
2284 if (s->hl == DRAW_IMAGE_SUNKEN
2285 || s->hl == DRAW_IMAGE_RAISED)
2286 {
2287 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2288 raised_p = s->hl == DRAW_IMAGE_RAISED;
2289 }
2290 else
2291 {
2292 thick = abs (s->img->relief);
2293 raised_p = s->img->relief > 0;
2294 }
2295
2296 x0 = x - thick;
2297 y0 = y - thick;
2298 x1 = x + s->img->width + thick - 1;
2299 y1 = y + s->img->height + thick - 1;
2300
2301 x_setup_relief_colors (s);
2302 get_glyph_string_clip_rect (s, &r);
2303 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
2304 }
2305
2306
2307 /* Draw the foreground of image glyph string S to PIXMAP. */
2308
2309 static void
2310 x_draw_image_foreground_1 (s, pixmap)
2311 struct glyph_string *s;
2312 Pixmap pixmap;
2313 {
2314 int x;
2315 int y = s->ybase - s->y - image_ascent (s->img, s->face);
2316
2317 /* If first glyph of S has a left box line, start drawing it to the
2318 right of that line. */
2319 if (s->face->box != FACE_NO_BOX
2320 && s->first_glyph->left_box_line_p)
2321 x = abs (s->face->box_line_width);
2322 else
2323 x = 0;
2324
2325 /* If there is a margin around the image, adjust x- and y-position
2326 by that margin. */
2327 x += s->img->hmargin;
2328 y += s->img->vmargin;
2329
2330 if (s->img->pixmap)
2331 {
2332 if (s->img->mask)
2333 {
2334 /* We can't set both a clip mask and use XSetClipRectangles
2335 because the latter also sets a clip mask. We also can't
2336 trust on the shape extension to be available
2337 (XShapeCombineRegion). So, compute the rectangle to draw
2338 manually. */
2339 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2340 | GCFunction);
2341 XGCValues xgcv;
2342
2343 xgcv.clip_mask = s->img->mask;
2344 xgcv.clip_x_origin = x;
2345 xgcv.clip_y_origin = y;
2346 xgcv.function = GXcopy;
2347 XChangeGC (s->display, s->gc, mask, &xgcv);
2348
2349 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2350 0, 0, s->img->width, s->img->height, x, y);
2351 XSetClipMask (s->display, s->gc, None);
2352 }
2353 else
2354 {
2355 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2356 0, 0, s->img->width, s->img->height, x, y);
2357
2358 /* When the image has a mask, we can expect that at
2359 least part of a mouse highlight or a block cursor will
2360 be visible. If the image doesn't have a mask, make
2361 a block cursor visible by drawing a rectangle around
2362 the image. I believe it's looking better if we do
2363 nothing here for mouse-face. */
2364 if (s->hl == DRAW_CURSOR)
2365 {
2366 int r = s->img->relief;
2367 if (r < 0) r = -r;
2368 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r,
2369 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2370 } 2389 }
2371 } 2390 }
2372 } 2391 }
2373 else 2392 else
2374 /* Draw a rectangle if image could not be loaded. */ 2393 /* Draw a rectangle if image could not be loaded. */
2375 XDrawRectangle (s->display, pixmap, s->gc, x, y, 2394 XDrawRectangle (s->display, pixmap, s->gc, x, y,
2376 s->img->width - 1, s->img->height - 1); 2395 s->slice.width - 1, s->slice.height - 1);
2377 } 2396 }
2378 2397
2379 2398
2380 /* Draw part of the background of glyph string S. X, Y, W, and H 2399 /* Draw part of the background of glyph string S. X, Y, W, and H
2381 give the rectangle to draw. */ 2400 give the rectangle to draw. */
2413 2432
2414 static void 2433 static void
2415 x_draw_image_glyph_string (s) 2434 x_draw_image_glyph_string (s)
2416 struct glyph_string *s; 2435 struct glyph_string *s;
2417 { 2436 {
2418 int x, y;
2419 int box_line_hwidth = abs (s->face->box_line_width); 2437 int box_line_hwidth = abs (s->face->box_line_width);
2420 int box_line_vwidth = max (s->face->box_line_width, 0); 2438 int box_line_vwidth = max (s->face->box_line_width, 0);
2421 int height; 2439 int height;
2422 Pixmap pixmap = None; 2440 Pixmap pixmap = None;
2423 2441
2424 height = s->height - 2 * box_line_vwidth; 2442 height = s->height;
2425 2443 if (s->slice.y == 0)
2444 height -= box_line_vwidth;
2445 if (s->slice.y + s->slice.height >= s->img->height)
2446 height -= box_line_vwidth;
2426 2447
2427 /* Fill background with face under the image. Do it only if row is 2448 /* Fill background with face under the image. Do it only if row is
2428 taller than image or if image has a clip mask to reduce 2449 taller than image or if image has a clip mask to reduce
2429 flickering. */ 2450 flickering. */
2430 s->stippled_p = s->face->stipple != 0; 2451 s->stippled_p = s->face->stipple != 0;
2431 if (height > s->img->height 2452 if (height > s->slice.height
2432 || s->img->hmargin 2453 || s->img->hmargin
2433 || s->img->vmargin 2454 || s->img->vmargin
2434 || s->img->mask 2455 || s->img->mask
2435 || s->img->pixmap == 0 2456 || s->img->pixmap == 0
2436 || s->width != s->background_width) 2457 || s->width != s->background_width)
2437 { 2458 {
2438 if (box_line_hwidth && s->first_glyph->left_box_line_p)
2439 x = s->x + box_line_hwidth;
2440 else
2441 x = s->x;
2442
2443 y = s->y + box_line_vwidth;
2444
2445 if (s->img->mask) 2459 if (s->img->mask)
2446 { 2460 {
2447 /* Create a pixmap as large as the glyph string. Fill it 2461 /* Create a pixmap as large as the glyph string. Fill it
2448 with the background color. Copy the image to it, using 2462 with the background color. Copy the image to it, using
2449 its mask. Copy the temporary pixmap to the display. */ 2463 its mask. Copy the temporary pixmap to the display. */
2478 0, 0, s->background_width, s->height); 2492 0, 0, s->background_width, s->height);
2479 XSetForeground (s->display, s->gc, xgcv.foreground); 2493 XSetForeground (s->display, s->gc, xgcv.foreground);
2480 } 2494 }
2481 } 2495 }
2482 else 2496 else
2483 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height); 2497 {
2498 int x = s->x;
2499 int y = s->y;
2500
2501 if (s->first_glyph->left_box_line_p
2502 && s->slice.x == 0)
2503 x += box_line_hwidth;
2504
2505 if (s->slice.y == 0)
2506 y += box_line_vwidth;
2507
2508 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2509 }
2484 2510
2485 s->background_filled_p = 1; 2511 s->background_filled_p = 1;
2486 } 2512 }
2487 2513
2488 /* Draw the foreground. */ 2514 /* Draw the foreground. */