1/* 2 * Copyright © 2003 Keith Packard 3 * 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. 13 * 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. 21 */ 22 23#ifdef HAVE_DIX_CONFIG_H 24#include <dix-config.h> 25#endif 26 27#include <stdlib.h> 28#include "uxa-priv.h" 29 30#include <dixfontstr.h> 31#include <gcstruct.h> 32#include <picturestr.h> 33#include <scrnintstr.h> 34#include <windowstr.h> 35#include <X11/X.h> 36#include <X11/fonts/font.h> 37#include <X11/fonts/fontstruct.h> 38#ifdef HAVE_XFONT2 39#include <X11/fonts/libxfont2.h> 40#else 41#include <X11/fonts/fontutil.h> 42#endif 43 44#include "uxa-damage.h" 45 46typedef struct _damageGCPriv { 47 GCOps *ops; 48 GCFuncs *funcs; 49} DamageGCPrivRec, *DamageGCPrivPtr; 50 51#define DAMAGE_VALIDATE_ENABLE 0 52#define DAMAGE_DEBUG_ENABLE 0 53#if DAMAGE_DEBUG_ENABLE 54#define DAMAGE_DEBUG(x) ErrorF x 55#else 56#define DAMAGE_DEBUG(x) 57#endif 58 59#define TRIM_BOX(box, pGC) if (pGC->pCompositeClip) { \ 60 BoxPtr extents = &pGC->pCompositeClip->extents; \ 61 if(box.x1 < extents->x1) box.x1 = extents->x1; \ 62 if(box.x2 > extents->x2) box.x2 = extents->x2; \ 63 if(box.y1 < extents->y1) box.y1 = extents->y1; \ 64 if(box.y2 > extents->y2) box.y2 = extents->y2; \ 65 } 66 67#define TRANSLATE_BOX(box, pDrawable) { \ 68 box.x1 += pDrawable->x; \ 69 box.x2 += pDrawable->x; \ 70 box.y1 += pDrawable->y; \ 71 box.y2 += pDrawable->y; \ 72 } 73 74#define TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC) { \ 75 TRANSLATE_BOX(box, pDrawable); \ 76 TRIM_BOX(box, pGC); \ 77 } 78 79#define BOX_NOT_EMPTY(box) \ 80 (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0)) 81 82#define checkGCDamage(g) ((!g->pCompositeClip || \ 83 REGION_NOTEMPTY(d->pScreen, \ 84 g->pCompositeClip))) 85 86#define TRIM_PICTURE_BOX(box, pDst) { \ 87 BoxPtr extents = &pDst->pCompositeClip->extents; \ 88 if(box.x1 < extents->x1) box.x1 = extents->x1; \ 89 if(box.x2 > extents->x2) box.x2 = extents->x2; \ 90 if(box.y1 < extents->y1) box.y1 = extents->y1; \ 91 if(box.y2 > extents->y2) box.y2 = extents->y2; \ 92 } 93 94#define checkPictureDamage(p) (REGION_NOTEMPTY(pScreen, p->pCompositeClip)) 95 96static void 97trim_region (RegionPtr pRegion, 98 DrawablePtr pDrawable, 99 int subWindowMode) 100{ 101 RegionRec pixClip; 102 int draw_x = 0; 103 int draw_y = 0; 104#ifdef COMPOSITE 105 int screen_x = 0, screen_y = 0; 106#endif 107 108 /* short circuit for empty regions */ 109 if (!REGION_NOTEMPTY(pScreen, pRegion)) 110 return; 111 112#ifdef COMPOSITE 113 /* 114 * When drawing to a pixmap which is storing window contents, 115 * the region presented is in pixmap relative coordinates which 116 * need to be converted to screen relative coordinates 117 */ 118 if (pDrawable->type != DRAWABLE_WINDOW) 119 { 120 screen_x = ((PixmapPtr) pDrawable)->screen_x - pDrawable->x; 121 screen_y = ((PixmapPtr) pDrawable)->screen_y - pDrawable->y; 122 } 123 if (screen_x || screen_y) 124 REGION_TRANSLATE (pScreen, pRegion, screen_x, screen_y); 125#endif 126 127 /* Clip against any children */ 128 if (pDrawable->type == DRAWABLE_WINDOW && 129 ((WindowPtr)(pDrawable))->backingStore == NotUseful) 130 { 131 if (subWindowMode == ClipByChildren) 132 { 133 REGION_INTERSECT(pScreen, pRegion, pRegion, 134 &((WindowPtr)(pDrawable))->clipList); 135 } 136 else if (subWindowMode == IncludeInferiors) 137 { 138 RegionPtr pTempRegion = 139 NotClippedByChildren((WindowPtr)(pDrawable)); 140 REGION_INTERSECT(pScreen, pRegion, pRegion, pTempRegion); 141 REGION_DESTROY(pScreen, pTempRegion); 142 } 143 /* If subWindowMode is set to an invalid value, don't perform 144 * any drawable-based clipping. */ 145 } 146 147 /* Clip against border or pixmap bounds */ 148 if (pDrawable->type == DRAWABLE_WINDOW) 149 { 150 REGION_INTERSECT (pScreen, pRegion, pRegion, 151 &((WindowPtr)(pDrawable))->borderClip); 152 } 153 else 154 { 155 BoxRec box; 156 157 draw_x = pDrawable->x; 158 draw_y = pDrawable->y; 159#ifdef COMPOSITE 160 /* 161 * Need to move everyone to screen coordinates 162 * XXX what about off-screen pixmaps with non-zero x/y? 163 */ 164 if (!WindowDrawable(pDrawable->type)) 165 { 166 draw_x += ((PixmapPtr) pDrawable)->screen_x; 167 draw_y += ((PixmapPtr) pDrawable)->screen_y; 168 } 169#endif 170 171 box.x1 = draw_x; 172 box.y1 = draw_y; 173 box.x2 = draw_x + pDrawable->width; 174 box.y2 = draw_y + pDrawable->height; 175 176 REGION_INIT(pScreen, &pixClip, &box, 1); 177 REGION_INTERSECT (pScreen, pRegion, pRegion, &pixClip); 178 REGION_UNINIT(pScreen, &pixClip); 179 } 180 181 /* 182 * Move region to target coordinate space 183 */ 184 if (draw_x || draw_y) 185 REGION_TRANSLATE (pScreen, pRegion, -draw_x, -draw_y); 186 187 /* Now do something with the damage */ 188} 189 190static void 191add_region (RegionPtr existing, 192 RegionPtr new, 193 DrawablePtr pDrawable, 194 int subWindowMode) 195{ 196 trim_region (new, pDrawable, subWindowMode); 197 198 REGION_UNION (pDrawable->pScreen, existing, existing, new); 199} 200 201static void 202add_box (RegionPtr existing, 203 BoxPtr box, 204 DrawablePtr drawable, 205 int subwindow_mode) 206{ 207 RegionRec region; 208 209 REGION_INIT (pDrawable->pScreen, ®ion, box, 1); 210 211 add_region (existing, ®ion, drawable, subwindow_mode); 212 213 REGION_UNINIT (pDrawable->pScreen, ®ion); 214} 215 216 217void 218uxa_damage_composite (RegionPtr region, 219 CARD8 op, 220 PicturePtr pSrc, 221 PicturePtr pMask, 222 PicturePtr pDst, 223 INT16 xSrc, 224 INT16 ySrc, 225 INT16 xMask, 226 INT16 yMask, 227 INT16 xDst, 228 INT16 yDst, 229 CARD16 width, 230 CARD16 height) 231{ 232 if (checkPictureDamage (pDst)) 233 { 234 BoxRec box; 235 236 box.x1 = xDst + pDst->pDrawable->x; 237 box.y1 = yDst + pDst->pDrawable->y; 238 box.x2 = box.x1 + width; 239 box.y2 = box.y1 + height; 240 241 TRIM_PICTURE_BOX(box, pDst); 242 243 if (BOX_NOT_EMPTY(box)) 244 add_box (region, &box, pDst->pDrawable, pDst->subWindowMode); 245 } 246} 247 248void 249uxa_damage_glyphs (RegionPtr region, 250 CARD8 op, 251 PicturePtr pSrc, 252 PicturePtr pDst, 253 PictFormatPtr maskFormat, 254 INT16 xSrc, 255 INT16 ySrc, 256 int nlist, 257 GlyphListPtr list, 258 GlyphPtr *glyphs) 259{ 260 if (checkPictureDamage (pDst)) 261 { 262 int nlistTmp = nlist; 263 GlyphListPtr listTmp = list; 264 GlyphPtr *glyphsTmp = glyphs; 265 int x, y; 266 int n; 267 GlyphPtr glyph; 268 BoxRec box; 269 int x1, y1, x2, y2; 270 271 box.x1 = 32767; 272 box.y1 = 32767; 273 box.x2 = -32767; 274 box.y2 = -32767; 275 x = pDst->pDrawable->x; 276 y = pDst->pDrawable->y; 277 while (nlistTmp--) 278 { 279 x += listTmp->xOff; 280 y += listTmp->yOff; 281 n = listTmp->len; 282 while (n--) 283 { 284 glyph = *glyphsTmp++; 285 x1 = x - glyph->info.x; 286 y1 = y - glyph->info.y; 287 x2 = x1 + glyph->info.width; 288 y2 = y1 + glyph->info.height; 289 if (x1 < box.x1) 290 box.x1 = x1; 291 if (y1 < box.y1) 292 box.y1 = y1; 293 if (x2 > box.x2) 294 box.x2 = x2; 295 if (y2 > box.y2) 296 box.y2 = y2; 297 x += glyph->info.xOff; 298 y += glyph->info.yOff; 299 } 300 listTmp++; 301 } 302 TRIM_PICTURE_BOX (box, pDst); 303 if (BOX_NOT_EMPTY(box)) 304 add_box (region, &box, pDst->pDrawable, pDst->subWindowMode); 305 } 306} 307 308void 309uxa_damage_add_traps (RegionPtr region, 310 PicturePtr pPicture, 311 INT16 x_off, 312 INT16 y_off, 313 int ntrap, 314 xTrap *traps) 315{ 316 if (checkPictureDamage (pPicture)) 317 { 318 BoxRec box; 319 int i; 320 int x, y; 321 xTrap *t = traps; 322 323 box.x1 = 32767; 324 box.y1 = 32767; 325 box.x2 = -32767; 326 box.y2 = -32767; 327 x = pPicture->pDrawable->x + x_off; 328 y = pPicture->pDrawable->y + y_off; 329 for (i = 0; i < ntrap; i++) 330 { 331 pixman_fixed_t l = min (t->top.l, t->bot.l); 332 pixman_fixed_t r = max (t->top.r, t->bot.r); 333 int x1 = x + pixman_fixed_to_int (l); 334 int x2 = x + pixman_fixed_to_int (pixman_fixed_ceil (r)); 335 int y1 = y + pixman_fixed_to_int (t->top.y); 336 int y2 = y + pixman_fixed_to_int (pixman_fixed_ceil (t->bot.y)); 337 338 if (x1 < box.x1) 339 box.x1 = x1; 340 if (x2 > box.x2) 341 box.x2 = x2; 342 if (y1 < box.y1) 343 box.y1 = y1; 344 if (y2 > box.y2) 345 box.y2 = y2; 346 } 347 TRIM_PICTURE_BOX (box, pPicture); 348 if (BOX_NOT_EMPTY(box)) 349 add_box (region, &box, pPicture->pDrawable, pPicture->subWindowMode); 350 } 351} 352 353/**********************************************************/ 354 355 356void 357uxa_damage_fill_spans (RegionPtr region, 358 DrawablePtr pDrawable, 359 GC *pGC, 360 int npt, 361 DDXPointPtr ppt, 362 int *pwidth, 363 int fSorted) 364{ 365 if (npt && checkGCDamage (pGC)) 366 { 367 int nptTmp = npt; 368 DDXPointPtr pptTmp = ppt; 369 int *pwidthTmp = pwidth; 370 BoxRec box; 371 372 box.x1 = pptTmp->x; 373 box.x2 = box.x1 + *pwidthTmp; 374 box.y2 = box.y1 = pptTmp->y; 375 376 while(--nptTmp) 377 { 378 pptTmp++; 379 pwidthTmp++; 380 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 381 if(box.x2 < (pptTmp->x + *pwidthTmp)) 382 box.x2 = pptTmp->x + *pwidthTmp; 383 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 384 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 385 } 386 387 box.y2++; 388 389 if(!pGC->miTranslate) { 390 TRANSLATE_BOX(box, pDrawable); 391 } 392 TRIM_BOX(box, pGC); 393 394 if(BOX_NOT_EMPTY(box)) 395 add_box (region, &box, pDrawable, pGC->subWindowMode); 396 } 397} 398 399void 400uxa_damage_set_spans (RegionPtr region, 401 DrawablePtr pDrawable, 402 GCPtr pGC, 403 char *pcharsrc, 404 DDXPointPtr ppt, 405 int *pwidth, 406 int npt, 407 int fSorted) 408{ 409 if (npt && checkGCDamage (pGC)) 410 { 411 DDXPointPtr pptTmp = ppt; 412 int *pwidthTmp = pwidth; 413 int nptTmp = npt; 414 BoxRec box; 415 416 box.x1 = pptTmp->x; 417 box.x2 = box.x1 + *pwidthTmp; 418 box.y2 = box.y1 = pptTmp->y; 419 420 while(--nptTmp) 421 { 422 pptTmp++; 423 pwidthTmp++; 424 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 425 if(box.x2 < (pptTmp->x + *pwidthTmp)) 426 box.x2 = pptTmp->x + *pwidthTmp; 427 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 428 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 429 } 430 431 box.y2++; 432 433 if(!pGC->miTranslate) { 434 TRANSLATE_BOX(box, pDrawable); 435 } 436 TRIM_BOX(box, pGC); 437 438 if(BOX_NOT_EMPTY(box)) 439 add_box (region, &box, pDrawable, pGC->subWindowMode); 440 } 441} 442 443void 444uxa_damage_put_image (RegionPtr region, 445 DrawablePtr pDrawable, 446 GCPtr pGC, 447 int depth, 448 int x, 449 int y, 450 int w, 451 int h, 452 int leftPad, 453 int format, 454 char *pImage) 455{ 456 if (checkGCDamage (pGC)) 457 { 458 BoxRec box; 459 460 box.x1 = x + pDrawable->x; 461 box.x2 = box.x1 + w; 462 box.y1 = y + pDrawable->y; 463 box.y2 = box.y1 + h; 464 465 TRIM_BOX(box, pGC); 466 if(BOX_NOT_EMPTY(box)) 467 add_box (region, &box, pDrawable, pGC->subWindowMode); 468 } 469} 470 471void 472uxa_damage_copy_area(RegionPtr region, 473 DrawablePtr pSrc, 474 DrawablePtr pDst, 475 GC *pGC, 476 int srcx, 477 int srcy, 478 int width, 479 int height, 480 int dstx, 481 int dsty) 482{ 483 if (checkGCDamage (pGC)) 484 { 485 BoxRec box; 486 487 box.x1 = dstx + pDst->x; 488 box.x2 = box.x1 + width; 489 box.y1 = dsty + pDst->y; 490 box.y2 = box.y1 + height; 491 492 TRIM_BOX(box, pGC); 493 if(BOX_NOT_EMPTY(box)) 494 add_box (region, &box, pDst, pGC->subWindowMode); 495 } 496} 497 498void 499uxa_damage_copy_plane (RegionPtr region, 500 DrawablePtr pSrc, 501 DrawablePtr pDst, 502 GCPtr pGC, 503 int srcx, 504 int srcy, 505 int width, 506 int height, 507 int dstx, 508 int dsty, 509 unsigned long bitPlane) 510{ 511 if (checkGCDamage (pGC)) 512 { 513 BoxRec box; 514 515 box.x1 = dstx + pDst->x; 516 box.x2 = box.x1 + width; 517 box.y1 = dsty + pDst->y; 518 box.y2 = box.y1 + height; 519 520 TRIM_BOX(box, pGC); 521 if(BOX_NOT_EMPTY(box)) 522 add_box (region, &box, pDst, pGC->subWindowMode); 523 } 524} 525 526void 527uxa_damage_poly_point (RegionPtr region, 528 DrawablePtr pDrawable, 529 GCPtr pGC, 530 int mode, 531 int npt, 532 xPoint *ppt) 533{ 534 if (npt && checkGCDamage (pGC)) 535 { 536 BoxRec box; 537 int nptTmp = npt; 538 xPoint *pptTmp = ppt; 539 540 box.x2 = box.x1 = pptTmp->x; 541 box.y2 = box.y1 = pptTmp->y; 542 543 /* this could be slow if the points were spread out */ 544 545 while(--nptTmp) 546 { 547 pptTmp++; 548 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 549 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; 550 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 551 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 552 } 553 554 box.x2++; 555 box.y2++; 556 557 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 558 if(BOX_NOT_EMPTY(box)) 559 add_box (region, &box, pDrawable, pGC->subWindowMode); 560 } 561} 562 563void 564uxa_damage_poly_lines (RegionPtr region, 565 DrawablePtr pDrawable, 566 GCPtr pGC, 567 int mode, 568 int npt, 569 DDXPointPtr ppt) 570{ 571 if (npt && checkGCDamage (pGC)) 572 { 573 int nptTmp = npt; 574 DDXPointPtr pptTmp = ppt; 575 BoxRec box; 576 int extra = pGC->lineWidth >> 1; 577 578 box.x2 = box.x1 = pptTmp->x; 579 box.y2 = box.y1 = pptTmp->y; 580 581 if(nptTmp > 1) 582 { 583 if(pGC->joinStyle == JoinMiter) 584 extra = 6 * pGC->lineWidth; 585 else if(pGC->capStyle == CapProjecting) 586 extra = pGC->lineWidth; 587 } 588 589 if(mode == CoordModePrevious) 590 { 591 int x = box.x1; 592 int y = box.y1; 593 while(--nptTmp) 594 { 595 pptTmp++; 596 x += pptTmp->x; 597 y += pptTmp->y; 598 if(box.x1 > x) box.x1 = x; 599 else if(box.x2 < x) box.x2 = x; 600 if(box.y1 > y) box.y1 = y; 601 else if(box.y2 < y) box.y2 = y; 602 } 603 } 604 else 605 { 606 while(--nptTmp) 607 { 608 pptTmp++; 609 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 610 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; 611 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 612 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 613 } 614 } 615 616 box.x2++; 617 box.y2++; 618 619 if(extra) 620 { 621 box.x1 -= extra; 622 box.x2 += extra; 623 box.y1 -= extra; 624 box.y2 += extra; 625 } 626 627 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 628 if(BOX_NOT_EMPTY(box)) 629 add_box (region, &box, pDrawable, pGC->subWindowMode); 630 } 631} 632 633void 634uxa_damage_poly_segment (RegionPtr region, 635 DrawablePtr pDrawable, 636 GCPtr pGC, 637 int nSeg, 638 xSegment *pSeg) 639{ 640 if (nSeg && checkGCDamage (pGC)) 641 { 642 BoxRec box; 643 int extra = pGC->lineWidth; 644 int nsegTmp = nSeg; 645 xSegment *pSegTmp = pSeg; 646 647 if(pGC->capStyle != CapProjecting) 648 extra >>= 1; 649 650 if(pSegTmp->x2 > pSegTmp->x1) { 651 box.x1 = pSegTmp->x1; 652 box.x2 = pSegTmp->x2; 653 } else { 654 box.x2 = pSegTmp->x1; 655 box.x1 = pSegTmp->x2; 656 } 657 658 if(pSegTmp->y2 > pSegTmp->y1) { 659 box.y1 = pSegTmp->y1; 660 box.y2 = pSegTmp->y2; 661 } else { 662 box.y2 = pSegTmp->y1; 663 box.y1 = pSegTmp->y2; 664 } 665 666 while(--nsegTmp) 667 { 668 pSegTmp++; 669 if(pSegTmp->x2 > pSegTmp->x1) 670 { 671 if(pSegTmp->x1 < box.x1) box.x1 = pSegTmp->x1; 672 if(pSegTmp->x2 > box.x2) box.x2 = pSegTmp->x2; 673 } 674 else 675 { 676 if(pSegTmp->x2 < box.x1) box.x1 = pSegTmp->x2; 677 if(pSegTmp->x1 > box.x2) box.x2 = pSegTmp->x1; 678 } 679 if(pSegTmp->y2 > pSegTmp->y1) 680 { 681 if(pSegTmp->y1 < box.y1) box.y1 = pSegTmp->y1; 682 if(pSegTmp->y2 > box.y2) box.y2 = pSegTmp->y2; 683 } 684 else 685 { 686 if(pSegTmp->y2 < box.y1) box.y1 = pSegTmp->y2; 687 if(pSegTmp->y1 > box.y2) box.y2 = pSegTmp->y1; 688 } 689 } 690 691 box.x2++; 692 box.y2++; 693 694 if(extra) 695 { 696 box.x1 -= extra; 697 box.x2 += extra; 698 box.y1 -= extra; 699 box.y2 += extra; 700 } 701 702 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 703 if(BOX_NOT_EMPTY(box)) 704 add_box (region, &box, pDrawable, pGC->subWindowMode); 705 } 706} 707 708void 709uxa_damage_poly_rectangle (RegionPtr region, 710 DrawablePtr pDrawable, 711 GCPtr pGC, 712 int nRects, 713 xRectangle *pRects) 714{ 715 if (nRects && checkGCDamage (pGC)) 716 { 717 BoxRec box; 718 int offset1, offset2, offset3; 719 int nRectsTmp = nRects; 720 xRectangle *pRectsTmp = pRects; 721 722 offset2 = pGC->lineWidth; 723 if(!offset2) offset2 = 1; 724 offset1 = offset2 >> 1; 725 offset3 = offset2 - offset1; 726 727 while(nRectsTmp--) 728 { 729 box.x1 = pRectsTmp->x - offset1; 730 box.y1 = pRectsTmp->y - offset1; 731 box.x2 = box.x1 + pRectsTmp->width + offset2; 732 box.y2 = box.y1 + offset2; 733 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 734 if(BOX_NOT_EMPTY(box)) 735 add_box (region, &box, pDrawable, pGC->subWindowMode); 736 737 box.x1 = pRectsTmp->x - offset1; 738 box.y1 = pRectsTmp->y + offset3; 739 box.x2 = box.x1 + offset2; 740 box.y2 = box.y1 + pRectsTmp->height - offset2; 741 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 742 if(BOX_NOT_EMPTY(box)) 743 add_box (region, &box, pDrawable, pGC->subWindowMode); 744 745 box.x1 = pRectsTmp->x + pRectsTmp->width - offset1; 746 box.y1 = pRectsTmp->y + offset3; 747 box.x2 = box.x1 + offset2; 748 box.y2 = box.y1 + pRectsTmp->height - offset2; 749 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 750 if(BOX_NOT_EMPTY(box)) 751 add_box (region, &box, pDrawable, pGC->subWindowMode); 752 753 box.x1 = pRectsTmp->x - offset1; 754 box.y1 = pRectsTmp->y + pRectsTmp->height - offset1; 755 box.x2 = box.x1 + pRectsTmp->width + offset2; 756 box.y2 = box.y1 + offset2; 757 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 758 if(BOX_NOT_EMPTY(box)) 759 add_box (region, &box, pDrawable, pGC->subWindowMode); 760 761 pRectsTmp++; 762 } 763 } 764} 765 766void 767uxa_damage_poly_arc (RegionPtr region, 768 DrawablePtr pDrawable, 769 GCPtr pGC, 770 int nArcs, 771 xArc *pArcs) 772{ 773 if (nArcs && checkGCDamage (pGC)) 774 { 775 int extra = pGC->lineWidth >> 1; 776 BoxRec box; 777 int nArcsTmp = nArcs; 778 xArc *pArcsTmp = pArcs; 779 780 box.x1 = pArcsTmp->x; 781 box.x2 = box.x1 + pArcsTmp->width; 782 box.y1 = pArcsTmp->y; 783 box.y2 = box.y1 + pArcsTmp->height; 784 785 while(--nArcsTmp) 786 { 787 pArcsTmp++; 788 if(box.x1 > pArcsTmp->x) 789 box.x1 = pArcsTmp->x; 790 if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) 791 box.x2 = pArcsTmp->x + pArcsTmp->width; 792 if(box.y1 > pArcsTmp->y) 793 box.y1 = pArcsTmp->y; 794 if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) 795 box.y2 = pArcsTmp->y + pArcsTmp->height; 796 } 797 798 if(extra) 799 { 800 box.x1 -= extra; 801 box.x2 += extra; 802 box.y1 -= extra; 803 box.y2 += extra; 804 } 805 806 box.x2++; 807 box.y2++; 808 809 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 810 if(BOX_NOT_EMPTY(box)) 811 add_box (region, &box, pDrawable, pGC->subWindowMode); 812 } 813} 814 815void 816uxa_damage_fill_polygon (RegionPtr region, 817 DrawablePtr pDrawable, 818 GCPtr pGC, 819 int shape, 820 int mode, 821 int npt, 822 DDXPointPtr ppt) 823{ 824 if (npt > 2 && checkGCDamage (pGC)) 825 { 826 DDXPointPtr pptTmp = ppt; 827 int nptTmp = npt; 828 BoxRec box; 829 830 box.x2 = box.x1 = pptTmp->x; 831 box.y2 = box.y1 = pptTmp->y; 832 833 if(mode != CoordModeOrigin) 834 { 835 int x = box.x1; 836 int y = box.y1; 837 while(--nptTmp) 838 { 839 pptTmp++; 840 x += pptTmp->x; 841 y += pptTmp->y; 842 if(box.x1 > x) box.x1 = x; 843 else if(box.x2 < x) box.x2 = x; 844 if(box.y1 > y) box.y1 = y; 845 else if(box.y2 < y) box.y2 = y; 846 } 847 } 848 else 849 { 850 while(--nptTmp) 851 { 852 pptTmp++; 853 if(box.x1 > pptTmp->x) box.x1 = pptTmp->x; 854 else if(box.x2 < pptTmp->x) box.x2 = pptTmp->x; 855 if(box.y1 > pptTmp->y) box.y1 = pptTmp->y; 856 else if(box.y2 < pptTmp->y) box.y2 = pptTmp->y; 857 } 858 } 859 860 box.x2++; 861 box.y2++; 862 863 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 864 if(BOX_NOT_EMPTY(box)) 865 add_box (region, &box, pDrawable, pGC->subWindowMode); 866 } 867} 868 869 870void 871uxa_damage_poly_fill_rect (RegionPtr region, 872 DrawablePtr pDrawable, 873 GCPtr pGC, 874 int nRects, 875 xRectangle *pRects) 876{ 877 if (nRects && checkGCDamage (pGC)) 878 { 879 int i; 880 881 for (i = 0; i < nRects; ++i) 882 { 883 xRectangle *rect = &(pRects[i]); 884 BoxRec box; 885 886 box.x1 = rect->x; 887 box.x2 = rect->x + rect->width; 888 box.y1 = rect->y; 889 box.y2 = rect->y + rect->height; 890 891 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 892 if(BOX_NOT_EMPTY(box)) 893 add_box (region, &box, pDrawable, pGC->subWindowMode); 894 } 895 } 896} 897 898 899void 900uxa_damage_poly_fill_arc (RegionPtr region, 901 DrawablePtr pDrawable, 902 GCPtr pGC, 903 int nArcs, 904 xArc *pArcs) 905{ 906 if (nArcs && checkGCDamage (pGC)) 907 { 908 BoxRec box; 909 int nArcsTmp = nArcs; 910 xArc *pArcsTmp = pArcs; 911 912 box.x1 = pArcsTmp->x; 913 box.x2 = box.x1 + pArcsTmp->width; 914 box.y1 = pArcsTmp->y; 915 box.y2 = box.y1 + pArcsTmp->height; 916 917 while(--nArcsTmp) 918 { 919 pArcsTmp++; 920 if(box.x1 > pArcsTmp->x) 921 box.x1 = pArcsTmp->x; 922 if(box.x2 < (pArcsTmp->x + pArcsTmp->width)) 923 box.x2 = pArcsTmp->x + pArcsTmp->width; 924 if(box.y1 > pArcsTmp->y) 925 box.y1 = pArcsTmp->y; 926 if(box.y2 < (pArcsTmp->y + pArcsTmp->height)) 927 box.y2 = pArcsTmp->y + pArcsTmp->height; 928 } 929 930 TRIM_AND_TRANSLATE_BOX(box, pDrawable, pGC); 931 if(BOX_NOT_EMPTY(box)) 932 add_box (region, &box, pDrawable, pGC->subWindowMode); 933 } 934} 935 936/* 937 * general Poly/Image text function. Extract glyph information, 938 * compute bounding box and remove cursor if it is overlapped. 939 */ 940 941void 942uxa_damage_chars (RegionPtr region, 943 DrawablePtr pDrawable, 944 FontPtr font, 945 int x, 946 int y, 947 unsigned int n, 948 CharInfoPtr *charinfo, 949 Bool imageblt, 950 int subWindowMode) 951{ 952 ExtentInfoRec extents; 953 BoxRec box; 954 955#ifdef HAVE_XFONT2 956 xfont2_query_glyph_extents(font, charinfo, n, &extents); 957#else 958 QueryGlyphExtents(font, charinfo, n, &extents); 959#endif 960 if (imageblt) 961 { 962 if (extents.overallWidth > extents.overallRight) 963 extents.overallRight = extents.overallWidth; 964 if (extents.overallWidth < extents.overallLeft) 965 extents.overallLeft = extents.overallWidth; 966 if (extents.overallLeft > 0) 967 extents.overallLeft = 0; 968 if (extents.fontAscent > extents.overallAscent) 969 extents.overallAscent = extents.fontAscent; 970 if (extents.fontDescent > extents.overallDescent) 971 extents.overallDescent = extents.fontDescent; 972 } 973 box.x1 = x + extents.overallLeft; 974 box.y1 = y - extents.overallAscent; 975 box.x2 = x + extents.overallRight; 976 box.y2 = y + extents.overallDescent; 977 add_box (region, &box, pDrawable, subWindowMode); 978} 979 980/* 981 * values for textType: 982 */ 983#define TT_POLY8 0 984#define TT_IMAGE8 1 985#define TT_POLY16 2 986#define TT_IMAGE16 3 987 988int 989uxa_damage_text (RegionPtr region, 990 DrawablePtr pDrawable, 991 GCPtr pGC, 992 int x, 993 int y, 994 unsigned long count, 995 char *chars, 996 FontEncoding fontEncoding, 997 Bool textType) 998{ 999 CharInfoPtr *charinfo; 1000 CharInfoPtr *info; 1001 unsigned long i; 1002 unsigned int n; 1003 int w; 1004 Bool imageblt; 1005 1006 imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16); 1007 1008 charinfo = malloc(count * sizeof(CharInfoPtr)); 1009 if (!charinfo) 1010 return x; 1011 1012 GetGlyphs(pGC->font, count, (unsigned char *)chars, 1013 fontEncoding, &i, charinfo); 1014 n = (unsigned int)i; 1015 w = 0; 1016 if (!imageblt) 1017 for (info = charinfo; i--; info++) 1018 w += (*info)->metrics.characterWidth; 1019 1020 if (n != 0) { 1021 uxa_damage_chars (region, 1022 pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n, 1023 charinfo, imageblt, pGC->subWindowMode); 1024 } 1025 free(charinfo); 1026 return x + w; 1027} 1028 1029int 1030uxa_damage_poly_text_8(RegionPtr region, 1031 DrawablePtr pDrawable, 1032 GCPtr pGC, 1033 int x, 1034 int y, 1035 int count, 1036 char *chars) 1037{ 1038 if (checkGCDamage (pGC)) 1039 x = uxa_damage_text (region, 1040 pDrawable, pGC, x, y, (unsigned long) count, chars, 1041 Linear8Bit, TT_POLY8); 1042 return x; 1043} 1044 1045int 1046uxa_damage_poly_text_16 (RegionPtr region, 1047 DrawablePtr pDrawable, 1048 GCPtr pGC, 1049 int x, 1050 int y, 1051 int count, 1052 unsigned short *chars) 1053{ 1054 if (checkGCDamage (pGC)) 1055 x = uxa_damage_text (region, 1056 pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, 1057 FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, 1058 TT_POLY16); 1059 1060 return x; 1061} 1062 1063void 1064uxa_damage_image_text_8(RegionPtr region, 1065 DrawablePtr pDrawable, 1066 GCPtr pGC, 1067 int x, 1068 int y, 1069 int count, 1070 char *chars) 1071{ 1072 if (checkGCDamage (pGC)) 1073 uxa_damage_text (region, 1074 pDrawable, pGC, x, y, (unsigned long) count, chars, 1075 Linear8Bit, TT_IMAGE8); 1076} 1077 1078void 1079uxa_damage_image_text_16 (RegionPtr region, 1080 DrawablePtr pDrawable, 1081 GCPtr pGC, 1082 int x, 1083 int y, 1084 int count, 1085 unsigned short *chars) 1086{ 1087 if (checkGCDamage (pGC)) 1088 uxa_damage_text (region, 1089 pDrawable, pGC, x, y, (unsigned long) count, (char *) chars, 1090 FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit, 1091 TT_IMAGE16); 1092} 1093 1094 1095void 1096uxa_damage_image_glyph_blt(RegionPtr region, 1097 DrawablePtr pDrawable, 1098 GCPtr pGC, 1099 int x, 1100 int y, 1101 unsigned int nglyph, 1102 CharInfoPtr *ppci, 1103 pointer pglyphBase) 1104{ 1105 uxa_damage_chars (region, 1106 pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, 1107 nglyph, ppci, TRUE, pGC->subWindowMode); 1108} 1109 1110void 1111uxa_damage_poly_glyph_blt(RegionPtr region, 1112 DrawablePtr pDrawable, 1113 GCPtr pGC, 1114 int x, 1115 int y, 1116 unsigned int nglyph, 1117 CharInfoPtr *ppci, 1118 pointer pglyphBase) 1119{ 1120 uxa_damage_chars (region, 1121 pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, 1122 nglyph, ppci, FALSE, pGC->subWindowMode); 1123} 1124 1125void 1126uxa_damage_push_pixels (RegionPtr region, 1127 GCPtr pGC, 1128 PixmapPtr pBitMap, 1129 DrawablePtr pDrawable, 1130 int dx, 1131 int dy, 1132 int xOrg, 1133 int yOrg) 1134{ 1135 if(checkGCDamage (pGC)) 1136 { 1137 BoxRec box; 1138 1139 box.x1 = xOrg; 1140 box.y1 = yOrg; 1141 1142 if(!pGC->miTranslate) { 1143 box.x1 += pDrawable->x; 1144 box.y1 += pDrawable->y; 1145 } 1146 1147 box.x2 = box.x1 + dx; 1148 box.y2 = box.y1 + dy; 1149 1150 TRIM_BOX(box, pGC); 1151 if(BOX_NOT_EMPTY(box)) 1152 add_box (region, &box, pDrawable, pGC->subWindowMode); 1153 } 1154} 1155 1156void 1157uxa_damage_copy_window(RegionPtr region, 1158 WindowPtr pWindow, 1159 DDXPointRec ptOldOrg, 1160 RegionPtr prgnSrc) 1161{ 1162#if 0 1163 ScreenPtr pScreen = pWindow->drawable.pScreen; 1164 damageScrPriv(pScreen); 1165 int dx = pWindow->drawable.x - ptOldOrg.x; 1166 int dy = pWindow->drawable.y - ptOldOrg.y; 1167 1168 /* 1169 * The region comes in source relative, but the damage occurs 1170 * at the destination location. Translate back and forth. 1171 */ 1172 REGION_TRANSLATE (pScreen, prgnSrc, dx, dy); 1173 damageRegionAppend (&pWindow->drawable, prgnSrc, FALSE, -1); 1174 REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy); 1175#endif 1176 1177 /* FIXME */ 1178} 1179