1/* 2 * tkMacOSXDraw.c -- 3 * 4 * This file contains functions that perform drawing to 5 * Xlib windows. Most of the functions simple emulate 6 * Xlib functions. 7 * 8 * Copyright (c) 1995-1997 Sun Microsystems, Inc. 9 * Copyright 2001, Apple Computer, Inc. 10 * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net> 11 * 12 * See the file "license.terms" for information on usage and redistribution 13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 14 * 15 * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.2.2.31 2008/02/27 00:12:59 das Exp $ 16 */ 17 18#include "tkMacOSXPrivate.h" 19#include "tkMacOSXDebug.h" 20#include "xbytes.h" 21 22#include "tclInt.h" /* for Tcl_CreateNamespace() */ 23 24/* 25#ifdef TK_MAC_DEBUG 26#define TK_MAC_DEBUG_DRAWING 27#endif 28*/ 29 30#define radians(d) ((d) * (M_PI/180.0)) 31 32/* 33 * Non-antialiased CG drawing looks better and more like X11 drawing when using 34 * very fine lines, so decrease all linewidths by the following constant. 35 */ 36#define NON_AA_CG_OFFSET .999 37 38/* 39 * Temporary region that can be reused. 40 */ 41 42RgnHandle tkMacOSXtmpQdRgn = NULL; 43 44int tkMacOSXUseCGDrawing = 1; 45 46int tkPictureIsOpen; 47 48static PixPatHandle penPat = NULL, tmpPixPat = NULL; 49 50static int cgAntiAliasLimit = 0; 51#define notAA(w) ((w) < cgAntiAliasLimit) 52 53static int useThemedToplevel = 0; 54static int useThemedFrame = 0; 55 56/* 57 * Prototypes for functions used only in this file. 58 */ 59 60static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr); 61static void NoQDClip(CGrafPtr port); 62 63 64/* 65 *---------------------------------------------------------------------- 66 * 67 * TkMacOSXInitCGDrawing -- 68 * 69 * Initializes link vars that control CG drawing. 70 * 71 * Results: 72 * None. 73 * 74 * Side effects: 75 * None. 76 * 77 *---------------------------------------------------------------------- 78 */ 79 80MODULE_SCOPE int 81TkMacOSXInitCGDrawing( 82 Tcl_Interp *interp, 83 int enable, 84 int limit) 85{ 86 static Boolean initialized = FALSE; 87 88 if (!initialized) { 89 initialized = TRUE; 90 91 if (Tcl_CreateNamespace(interp, "::tk::mac", NULL, NULL) == NULL) { 92 Tcl_ResetResult(interp); 93 } 94 if (Tcl_LinkVar(interp, "::tk::mac::useCGDrawing", 95 (char *) &tkMacOSXUseCGDrawing, TCL_LINK_BOOLEAN) != TCL_OK) { 96 Tcl_ResetResult(interp); 97 } 98 tkMacOSXUseCGDrawing = enable; 99 100 if (Tcl_LinkVar(interp, "::tk::mac::CGAntialiasLimit", 101 (char *) &cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) { 102 Tcl_ResetResult(interp); 103 } 104 cgAntiAliasLimit = limit; 105 106 /* 107 * Piggy-back the themed drawing var init here. 108 */ 109 110 if (Tcl_LinkVar(interp, "::tk::mac::useThemedToplevel", 111 (char *) &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) { 112 Tcl_ResetResult(interp); 113 } 114 if (Tcl_LinkVar(interp, "::tk::mac::useThemedFrame", 115 (char *) &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) { 116 Tcl_ResetResult(interp); 117 } 118 119 if (tkMacOSXtmpQdRgn == NULL) { 120 tkMacOSXtmpQdRgn = NewRgn(); 121 } 122 } 123#ifdef TK_MAC_DEBUG_DRAWING 124 TkMacOSXInitNamedDebugSymbol(QD, void, QD_DebugPrint, char*); 125 if (QD_DebugPrint) { 126 ; /* gdb: b *QD_DebugPrint */ 127 } 128#endif /* TK_MAC_DEBUG_WINDOWS */ 129 return TCL_OK; 130} 131 132/* 133 *---------------------------------------------------------------------- 134 * 135 * XCopyArea -- 136 * 137 * Copies data from one drawable to another using block transfer 138 * routines. 139 * 140 * Results: 141 * None. 142 * 143 * Side effects: 144 * Data is moved from a window or bitmap to a second window or 145 * bitmap. 146 * 147 *---------------------------------------------------------------------- 148 */ 149 150void 151XCopyArea( 152 Display *display, /* Display. */ 153 Drawable src, /* Source drawable. */ 154 Drawable dst, /* Destination drawable. */ 155 GC gc, /* GC to use. */ 156 int src_x, /* X & Y, width & height */ 157 int src_y, /* define the source rectangle */ 158 unsigned int width, /* that will be copied. */ 159 unsigned int height, 160 int dest_x, /* Dest X & Y on dest rect. */ 161 int dest_y) 162{ 163 TkMacOSXDrawingContext dc; 164 MacDrawable *srcDraw = (MacDrawable *) src, *dstDraw = (MacDrawable *) dst; 165 166 display->request++; 167 if (!width || !height) { 168 /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */ 169 return; 170 } 171 { 172 CGrafPtr srcPort; 173 174 srcPort = TkMacOSXGetDrawablePort(src); 175 if (srcPort) { 176 Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; 177 const BitMap *srcBit, *dstBit; 178 RGBColor black = {0, 0, 0}, white = {0xffff, 0xffff, 0xffff}; 179 180 if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) { 181 return; 182 } 183 if (dc.context) { 184 TkMacOSXDbgMsg("Ignored CG drawing of QD drawable"); 185 goto end; 186 } 187 if (!dc.port) { 188 TkMacOSXDbgMsg("Invalid destination drawable"); 189 goto end; 190 } 191 srcBit = GetPortBitMapForCopyBits(srcPort); 192 dstBit = GetPortBitMapForCopyBits(dc.port); 193 SetRect(srcPtr, srcDraw->xOff + src_x, srcDraw->yOff + src_y, 194 srcDraw->xOff + src_x + width, 195 srcDraw->yOff + src_y + height); 196 if (tkPictureIsOpen) { 197 dstPtr = srcPtr; 198 } else { 199 SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, 200 dstDraw->xOff + dest_x + width, 201 dstDraw->yOff + dest_y + height); 202 } 203 RGBForeColor(&black); 204 RGBBackColor(&white); 205 CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL); 206end: 207 TkMacOSXRestoreDrawingContext(&dc); 208 } else { 209 TkMacOSXDbgMsg("Invalid source drawable"); 210 } 211 } 212} 213 214/* 215 *---------------------------------------------------------------------- 216 * 217 * XCopyPlane -- 218 * 219 * Copies a bitmap from a source drawable to a destination 220 * drawable. The plane argument specifies which bit plane of 221 * the source contains the bitmap. Note that this implementation 222 * ignores the gc->function. 223 * 224 * Results: 225 * None. 226 * 227 * Side effects: 228 * Changes the destination drawable. 229 * 230 *---------------------------------------------------------------------- 231 */ 232 233void 234XCopyPlane( 235 Display *display, /* Display. */ 236 Drawable src, /* Source drawable. */ 237 Drawable dst, /* Destination drawable. */ 238 GC gc, /* GC to use. */ 239 int src_x, /* X & Y, width & height */ 240 int src_y, /* define the source rectangle */ 241 unsigned int width, /* that will be copied. */ 242 unsigned int height, 243 int dest_x, /* Dest X & Y on dest rect. */ 244 int dest_y, 245 unsigned long plane) /* Which plane to copy. */ 246{ 247 TkMacOSXDrawingContext dc; 248 MacDrawable *srcDraw = (MacDrawable *) src, *dstDraw = (MacDrawable *) dst; 249 250 display->request++; 251 if (!width || !height) { 252 /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */ 253 return; 254 } 255 if (plane != 1) { 256 Tcl_Panic("Unexpected plane specified for XCopyPlane"); 257 } 258 { 259 CGrafPtr srcPort; 260 261 srcPort = TkMacOSXGetDrawablePort(src); 262 if (srcPort) { 263 Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; 264 const BitMap *srcBit, *dstBit; 265 TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; 266 267 if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) { 268 return; 269 } 270 if (dc.context) { 271 TkMacOSXDbgMsg("Ignored CG drawing of QD drawable"); 272 goto end; 273 } 274 if (!dc.port) { 275 TkMacOSXDbgMsg("Invalid destination drawable"); 276 goto end; 277 } 278 srcBit = GetPortBitMapForCopyBits(srcPort); 279 dstBit = GetPortBitMapForCopyBits(dc.port); 280 SetRect(srcPtr, srcDraw->xOff + src_x, srcDraw->yOff + src_y, 281 srcDraw->xOff + src_x + width, 282 srcDraw->yOff + src_y + height); 283 if (tkPictureIsOpen) { 284 dstPtr = srcPtr; 285 } else { 286 SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, 287 dstDraw->xOff + dest_x + width, 288 dstDraw->yOff + dest_y + height); 289 } 290 TkMacOSXSetColorInPort(gc->foreground, 1, NULL, dc.port); 291 if (!clipPtr || clipPtr->type == TKP_CLIP_REGION) { 292 /* 293 * Opaque bitmaps. 294 */ 295 296 TkMacOSXSetColorInPort(gc->background, 0, NULL, dc.port); 297 CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL); 298 } else if (clipPtr->type == TKP_CLIP_PIXMAP) { 299 if (clipPtr->value.pixmap == src) { 300 /* 301 * Transparent bitmaps. If it's color ignore the forecolor. 302 */ 303 short tmode = GetPixDepth(GetPortPixMap(srcPort)) == 1 ? 304 srcOr : transparent; 305 306 CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); 307 } else { 308 /* 309 * Two arbitrary bitmaps. 310 */ 311 312 CGrafPtr mskPort = TkMacOSXGetDrawablePort( 313 clipPtr->value.pixmap); 314 const BitMap *mskBit = GetPortBitMapForCopyBits(mskPort); 315 316 CopyDeepMask(srcBit, mskBit, dstBit, srcPtr, srcPtr, 317 dstPtr, srcCopy, NULL); 318 } 319 } 320end: 321 TkMacOSXRestoreDrawingContext(&dc); 322 } else { 323 TkMacOSXDbgMsg("Invalid source drawable"); 324 } 325 } 326} 327 328/* 329 *---------------------------------------------------------------------- 330 * 331 * TkPutImage -- 332 * 333 * Copies a subimage from an in-memory image to a rectangle of 334 * of the specified drawable. 335 * 336 * Results: 337 * None. 338 * 339 * Side effects: 340 * Draws the image on the specified drawable. 341 * 342 *---------------------------------------------------------------------- 343 */ 344 345void 346TkPutImage( 347 unsigned long *colors, /* Unused on Macintosh. */ 348 int ncolors, /* Unused on Macintosh. */ 349 Display* display, /* Display. */ 350 Drawable d, /* Drawable to place image on. */ 351 GC gc, /* GC to use. */ 352 XImage* image, /* Image to place. */ 353 int src_x, /* Source X & Y. */ 354 int src_y, 355 int dest_x, /* Destination X & Y. */ 356 int dest_y, 357 unsigned int width, /* Same width & height for both */ 358 unsigned int height) /* distination and source. */ 359{ 360 TkMacOSXDrawingContext dc; 361 MacDrawable *dstDraw = (MacDrawable *) d; 362 363 display->request++; 364 if (!TkMacOSXSetupDrawingContext(d, gc, 0, &dc)) { 365 return; 366 } 367 if (dc.context) { 368 TkMacOSXDbgMsg("Ignored CG drawing of XImage"); 369 } else { 370 Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; 371 const BitMap *dstBit; 372 RGBColor black = {0, 0, 0}, white = {0xffff, 0xffff, 0xffff}; 373 int i, j; 374 char *newData = NULL; 375 char *dataPtr, *newPtr, *oldPtr; 376 int rowBytes = image->bytes_per_line, sliceRowBytes, lastSliceRowBytes; 377 int slices, sliceWidth, lastSliceWidth; 378 379 dstBit = GetPortBitMapForCopyBits(dc.port); 380 SetRect(srcPtr, src_x, src_y, src_x + width, src_y + height); 381 if (tkPictureIsOpen) { 382 dstPtr = srcPtr; 383 } else { 384 SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, 385 dstDraw->xOff + dest_x + width, 386 dstDraw->yOff + dest_y + height); 387 } 388 RGBForeColor(&black); 389 RGBBackColor(&white); 390 if (image->obdata) { 391 /* 392 * Image from XGetImage, copy from containing GWorld directly. 393 */ 394 395 CopyBits(GetPortBitMapForCopyBits(TkMacOSXGetDrawablePort( 396 (Drawable)image->obdata)), dstBit, 397 srcPtr, dstPtr, srcCopy, NULL); 398 } else if (image->depth == 1) { 399 /* 400 * BW image 401 */ 402 403 const int maxRowBytes = 0x3ffe; 404 BitMap bitmap; 405 int odd; 406 407 if (rowBytes > maxRowBytes) { 408 slices = rowBytes / maxRowBytes; 409 sliceRowBytes = maxRowBytes; 410 lastSliceRowBytes = rowBytes - (slices * maxRowBytes); 411 if (!lastSliceRowBytes) { 412 slices--; 413 lastSliceRowBytes = maxRowBytes; 414 } 415 sliceWidth = (long) image->width * maxRowBytes / rowBytes; 416 lastSliceWidth = image->width - (sliceWidth * slices); 417 } else { 418 slices = 0; 419 sliceRowBytes = lastSliceRowBytes = rowBytes; 420 sliceWidth = lastSliceWidth = image->width; 421 } 422 bitmap.bounds.top = bitmap.bounds.left = 0; 423 bitmap.bounds.bottom = (short) image->height; 424 dataPtr = image->data + image->xoffset; 425 do { 426 if (slices) { 427 bitmap.bounds.right = bitmap.bounds.left + sliceWidth; 428 } else { 429 sliceRowBytes = lastSliceRowBytes; 430 bitmap.bounds.right = bitmap.bounds.left + lastSliceWidth; 431 } 432 oldPtr = dataPtr; 433 odd = sliceRowBytes % 2; 434 if (!newData) { 435 newData = ckalloc(image->height * (sliceRowBytes+odd)); 436 } 437 newPtr = newData; 438 if (image->bitmap_bit_order != MSBFirst) { 439 for (i = 0; i < image->height; i++) { 440 for (j = 0; j < sliceRowBytes; j++) { 441 *newPtr = xBitReverseTable[(unsigned char)*oldPtr]; 442 newPtr++; oldPtr++; 443 } 444 if (odd) { 445 *newPtr++ = 0; 446 } 447 oldPtr += rowBytes - sliceRowBytes; 448 } 449 } else { 450 for (i = 0; i < image->height; i++) { 451 memcpy(newPtr, oldPtr, sliceRowBytes); 452 newPtr += sliceRowBytes; 453 if (odd) { 454 *newPtr++ = 0; 455 } 456 oldPtr += rowBytes; 457 } 458 } 459 bitmap.baseAddr = newData; 460 bitmap.rowBytes = sliceRowBytes + odd; 461 CopyBits(&bitmap, dstBit, srcPtr, dstPtr, srcCopy, NULL); 462 if (slices) { 463 bitmap.bounds.left = bitmap.bounds.right; 464 dataPtr += sliceRowBytes; 465 } 466 } while (slices--); 467 ckfree(newData); 468 } else { 469 /* 470 * Color image 471 */ 472 473 const int maxRowBytes = 0x3ffc; 474 PixMap pixmap; 475 476 pixmap.bounds.left = 0; 477 pixmap.bounds.top = 0; 478 pixmap.bounds.bottom = (short) image->height; 479 pixmap.pixelType = RGBDirect; 480 pixmap.pmVersion = baseAddr32; /* 32bit clean */ 481 pixmap.packType = 0; 482 pixmap.packSize = 0; 483 pixmap.hRes = 0x00480000; 484 pixmap.vRes = 0x00480000; 485 pixmap.pixelSize = 32; 486 pixmap.cmpCount = 3; 487 pixmap.cmpSize = 8; 488 pixmap.pixelFormat = image->byte_order == MSBFirst ? 489 k32ARGBPixelFormat : k32BGRAPixelFormat; 490 pixmap.pmTable = NULL; 491 pixmap.pmExt = 0; 492 if (rowBytes > maxRowBytes) { 493 slices = rowBytes / maxRowBytes; 494 sliceRowBytes = maxRowBytes; 495 lastSliceRowBytes = rowBytes - (slices * maxRowBytes); 496 if (!lastSliceRowBytes) { 497 slices--; 498 lastSliceRowBytes = maxRowBytes; 499 } 500 sliceWidth = (long) image->width * maxRowBytes / rowBytes; 501 lastSliceWidth = image->width - (sliceWidth * slices); 502 dataPtr = image->data + image->xoffset; 503 newData = (char *) ckalloc(image->height * sliceRowBytes); 504 do { 505 if (slices) { 506 pixmap.bounds.right = pixmap.bounds.left + sliceWidth; 507 } else { 508 sliceRowBytes = lastSliceRowBytes; 509 pixmap.bounds.right = pixmap.bounds.left + lastSliceWidth; 510 } 511 oldPtr = dataPtr; 512 newPtr = newData; 513 for (i = 0; i < image->height; i++) { 514 memcpy(newPtr, oldPtr, sliceRowBytes); 515 oldPtr += rowBytes; 516 newPtr += sliceRowBytes; 517 } 518 pixmap.baseAddr = newData; 519 pixmap.rowBytes = sliceRowBytes | 0x8000; 520 CopyBits((BitMap*) &pixmap, dstBit, srcPtr, dstPtr, srcCopy, 521 NULL); 522 if (slices) { 523 pixmap.bounds.left = pixmap.bounds.right; 524 dataPtr += sliceRowBytes; 525 } 526 } while (slices--); 527 ckfree(newData); 528 } else { 529 pixmap.bounds.right = (short) image->width; 530 pixmap.baseAddr = image->data + image->xoffset; 531 pixmap.rowBytes = rowBytes | 0x8000; 532 CopyBits((BitMap*) &pixmap, dstBit, srcPtr, dstPtr, srcCopy, NULL); 533 } 534 } 535 } 536 TkMacOSXRestoreDrawingContext(&dc); 537} 538 539/* 540 *---------------------------------------------------------------------- 541 * 542 * XDrawLines -- 543 * 544 * Draw connected lines. 545 * 546 * Results: 547 * None. 548 * 549 * Side effects: 550 * Renders a series of connected lines. 551 * 552 *---------------------------------------------------------------------- 553 */ 554 555void 556XDrawLines( 557 Display *display, /* Display. */ 558 Drawable d, /* Draw on this. */ 559 GC gc, /* Use this GC. */ 560 XPoint *points, /* Array of points. */ 561 int npoints, /* Number of points. */ 562 int mode) /* Line drawing mode. */ 563{ 564 MacDrawable *macWin = (MacDrawable *) d; 565 TkMacOSXDrawingContext dc; 566 int i, lw = gc->line_width; 567 568 if (npoints < 2) { 569 /* 570 * TODO: generate BadValue error. 571 */ 572 573 return; 574 } 575 576 display->request++; 577 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 578 return; 579 } 580 if (dc.context) { 581 double prevx, prevy; 582 double o = (lw % 2) ? .5 : 0; 583 584 CGContextBeginPath(dc.context); 585 prevx = macWin->xOff + points[0].x + o; 586 prevy = macWin->yOff + points[0].y + o; 587 CGContextMoveToPoint(dc.context, prevx, prevy); 588 for (i = 1; i < npoints; i++) { 589 if (mode == CoordModeOrigin) { 590 CGContextAddLineToPoint(dc.context, 591 macWin->xOff + points[i].x + o, 592 macWin->yOff + points[i].y + o); 593 } else { 594 prevx += points[i].x; 595 prevy += points[i].y; 596 CGContextAddLineToPoint(dc.context, prevx, prevy); 597 } 598 } 599 CGContextStrokePath(dc.context); 600 } else { 601 int o = -lw/2; 602 603 /* This is broken for fat lines, it is not possible to correctly 604 * imitate X11 drawing of oblique fat lines with QD line drawing, 605 * we should draw a filled polygon instead. */ 606 607 MoveTo((short) (macWin->xOff + points[0].x + o), 608 (short) (macWin->yOff + points[0].y + o)); 609 for (i = 1; i < npoints; i++) { 610 if (mode == CoordModeOrigin) { 611 LineTo((short) (macWin->xOff + points[i].x + o), 612 (short) (macWin->yOff + points[i].y + o)); 613 } else { 614 Line((short) points[i].x, (short) points[i].y); 615 } 616 } 617 } 618 TkMacOSXRestoreDrawingContext(&dc); 619} 620 621/* 622 *---------------------------------------------------------------------- 623 * 624 * XDrawSegments -- 625 * 626 * Draw unconnected lines. 627 * 628 * Results: 629 * None. 630 * 631 * Side effects: 632 * Renders a series of unconnected lines. 633 * 634 *---------------------------------------------------------------------- 635 */ 636 637void 638XDrawSegments( 639 Display *display, 640 Drawable d, 641 GC gc, 642 XSegment *segments, 643 int nsegments) 644{ 645 MacDrawable *macWin = (MacDrawable *) d; 646 TkMacOSXDrawingContext dc; 647 int i, lw = gc->line_width; 648 649 display->request++; 650 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 651 return; 652 } 653 if (dc.context) { 654 double o = (lw % 2) ? .5 : 0; 655 656 for (i = 0; i < nsegments; i++) { 657 CGContextBeginPath(dc.context); 658 CGContextMoveToPoint(dc.context, 659 macWin->xOff + segments[i].x1 + o, 660 macWin->yOff + segments[i].y1 + o); 661 CGContextAddLineToPoint(dc.context, 662 macWin->xOff + segments[i].x2 + o, 663 macWin->yOff + segments[i].y2 + o); 664 CGContextStrokePath(dc.context); 665 } 666 } else { 667 int o = -lw/2; 668 669 /* This is broken for fat lines, it is not possible to correctly 670 * imitate X11 drawing of oblique fat lines with QD line drawing, 671 * we should draw a filled polygon instead. */ 672 673 for (i = 0; i < nsegments; i++) { 674 MoveTo((short) (macWin->xOff + segments[i].x1 + o), 675 (short) (macWin->yOff + segments[i].y1 + o)); 676 LineTo((short) (macWin->xOff + segments[i].x2 + o), 677 (short) (macWin->yOff + segments[i].y2 + o)); 678 } 679 } 680 TkMacOSXRestoreDrawingContext(&dc); 681} 682 683/* 684 *---------------------------------------------------------------------- 685 * 686 * XFillPolygon -- 687 * 688 * Draws a filled polygon. 689 * 690 * Results: 691 * None. 692 * 693 * Side effects: 694 * Draws a filled polygon on the specified drawable. 695 * 696 *---------------------------------------------------------------------- 697 */ 698 699void 700XFillPolygon( 701 Display* display, /* Display. */ 702 Drawable d, /* Draw on this. */ 703 GC gc, /* Use this GC. */ 704 XPoint* points, /* Array of points. */ 705 int npoints, /* Number of points. */ 706 int shape, /* Shape to draw. */ 707 int mode) /* Drawing mode. */ 708{ 709 MacDrawable *macWin = (MacDrawable *) d; 710 TkMacOSXDrawingContext dc; 711 int i; 712 713 display->request++; 714 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 715 return; 716 } 717 if (dc.context) { 718 double prevx, prevy; 719 double o = (gc->line_width % 2) ? .5 : 0; 720 721 CGContextBeginPath(dc.context); 722 prevx = macWin->xOff + points[0].x + o; 723 prevy = macWin->yOff + points[0].y + o; 724 CGContextMoveToPoint(dc.context, prevx, prevy); 725 for (i = 1; i < npoints; i++) { 726 if (mode == CoordModeOrigin) { 727 CGContextAddLineToPoint(dc.context, 728 macWin->xOff + points[i].x + o, 729 macWin->yOff + points[i].y + o); 730 } else { 731 prevx += points[i].x; 732 prevy += points[i].y; 733 CGContextAddLineToPoint(dc.context, prevx, prevy); 734 } 735 } 736 CGContextEOFillPath(dc.context); 737 } else { 738 PolyHandle polygon; 739 740 polygon = OpenPoly(); 741 MoveTo((short) (macWin->xOff + points[0].x), 742 (short) (macWin->yOff + points[0].y)); 743 for (i = 1; i < npoints; i++) { 744 if (mode == CoordModeOrigin) { 745 LineTo((short) (macWin->xOff + points[i].x), 746 (short) (macWin->yOff + points[i].y)); 747 } else { 748 Line((short) points[i].x, (short) points[i].y); 749 } 750 } 751 ClosePoly(); 752 FillCPoly(polygon, dc.penPat); 753 KillPoly(polygon); 754 } 755 TkMacOSXRestoreDrawingContext(&dc); 756} 757 758/* 759 *---------------------------------------------------------------------- 760 * 761 * XDrawRectangle -- 762 * 763 * Draws a rectangle. 764 * 765 * Results: 766 * None. 767 * 768 * Side effects: 769 * Draws a rectangle on the specified drawable. 770 * 771 *---------------------------------------------------------------------- 772 */ 773 774void 775XDrawRectangle( 776 Display *display, /* Display. */ 777 Drawable d, /* Draw on this. */ 778 GC gc, /* Use this GC. */ 779 int x, int y, /* Upper left corner. */ 780 unsigned int width, /* Width & height of rect. */ 781 unsigned int height) 782{ 783 MacDrawable *macWin = (MacDrawable *) d; 784 TkMacOSXDrawingContext dc; 785 int lw = gc->line_width; 786 787 if (width == 0 || height == 0) { 788 return; 789 } 790 791 display->request++; 792 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 793 return; 794 } 795 if (dc.context) { 796 CGRect rect; 797 double o = (lw % 2) ? .5 : 0; 798 799 rect = CGRectMake( 800 macWin->xOff + x + o, 801 macWin->yOff + y + o, 802 width, height); 803 CGContextStrokeRect(dc.context, rect); 804 } else { 805 Rect theRect; 806 int o = -lw/2; 807 808 theRect.left = (short) (macWin->xOff + x + o); 809 theRect.top = (short) (macWin->yOff + y + o); 810 theRect.right = (short) (theRect.left + width + lw); 811 theRect.bottom = (short) (theRect.top + height + lw); 812 FrameRect(&theRect); 813 } 814 TkMacOSXRestoreDrawingContext(&dc); 815} 816 817#ifdef TK_MACOSXDRAW_UNUSED 818/* 819 *---------------------------------------------------------------------- 820 * 821 * XDrawRectangles -- 822 * 823 * Draws the outlines of the specified rectangles as if a 824 * five-point PolyLine protocol request were specified for each 825 * rectangle: 826 * 827 * [x,y] [x+width,y] [x+width,y+height] [x,y+height] [x,y] 828 * 829 * For the specified rectangles, these functions do not draw a 830 * pixel more than once. XDrawRectangles draws the rectangles in 831 * the order listed in the array. If rectangles intersect, the 832 * intersecting pixels are drawn multiple times. Draws a 833 * rectangle. 834 * 835 * Results: 836 * None. 837 * 838 * Side effects: 839 * Draws rectangles on the specified drawable. 840 * 841 *---------------------------------------------------------------------- 842 */ 843 844void 845XDrawRectangles( 846 Display *display, 847 Drawable drawable, 848 GC gc, 849 XRectangle *rectArr, 850 int nRects) 851{ 852 MacDrawable *macWin = (MacDrawable *) drawable; 853 TkMacOSXDrawingContext dc; 854 XRectangle * rectPtr; 855 int i, lw = gc->line_width; 856 857 display->request++; 858 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 859 return; 860 } 861 if (dc.context) { 862 CGRect rect; 863 double o = (lw % 2) ? .5 : 0; 864 865 for (i = 0, rectPtr = rectArr; i < nRects; i++, rectPtr++) { 866 if (rectPtr->width == 0 || rectPtr->height == 0) { 867 continue; 868 } 869 rect = CGRectMake( 870 macWin->xOff + rectPtr->x + o, 871 macWin->yOff + rectPtr->y + o, 872 rectPtr->width, rectPtr->height); 873 CGContextStrokeRect(dc.context, rect); 874 } 875 } else { 876 Rect theRect; 877 int o = -lw/2; 878 879 for (i = 0, rectPtr = rectArr; i < nRects;i++, rectPtr++) { 880 theRect.left = (short) (macWin->xOff + rectPtr->x + o); 881 theRect.top = (short) (macWin->yOff + rectPtr->y + o); 882 theRect.right = (short) (theRect.left + rectPtr->width + lw); 883 theRect.bottom = (short) (theRect.top + rectPtr->height + lw); 884 FrameRect(&theRect); 885 } 886 } 887 TkMacOSXRestoreDrawingContext(&dc); 888} 889#endif 890 891/* 892 *---------------------------------------------------------------------- 893 * 894 * XFillRectangles -- 895 * 896 * Fill multiple rectangular areas in the given drawable. 897 * 898 * Results: 899 * None. 900 * 901 * Side effects: 902 * Draws onto the specified drawable. 903 * 904 *---------------------------------------------------------------------- 905 */ 906 907void 908XFillRectangles( 909 Display* display, /* Display. */ 910 Drawable d, /* Draw on this. */ 911 GC gc, /* Use this GC. */ 912 XRectangle *rectangles, /* Rectangle array. */ 913 int n_rectangles) /* Number of rectangles. */ 914{ 915 MacDrawable *macWin = (MacDrawable *) d; 916 TkMacOSXDrawingContext dc; 917 XRectangle * rectPtr; 918 int i; 919 920 display->request++; 921 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 922 return; 923 } 924 if (dc.context) { 925 CGRect rect; 926 927 for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) { 928 if (rectPtr->width == 0 || rectPtr->height == 0) { 929 continue; 930 } 931 rect = CGRectMake( 932 macWin->xOff + rectPtr->x, 933 macWin->yOff + rectPtr->y, 934 rectPtr->width, rectPtr->height); 935 CGContextFillRect(dc.context, rect); 936 } 937 } else { 938 Rect theRect; 939 940 for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) { 941 theRect.left = (short) (macWin->xOff + rectPtr->x); 942 theRect.top = (short) (macWin->yOff + rectPtr->y); 943 theRect.right = (short) (theRect.left + rectPtr->width); 944 theRect.bottom = (short) (theRect.top + rectPtr->height); 945 FillCRect(&theRect, dc.penPat); 946 } 947 } 948 TkMacOSXRestoreDrawingContext(&dc); 949} 950 951/* 952 *---------------------------------------------------------------------- 953 * 954 * XDrawArc -- 955 * 956 * Draw an arc. 957 * 958 * Results: 959 * None. 960 * 961 * Side effects: 962 * Draws an arc on the specified drawable. 963 * 964 *---------------------------------------------------------------------- 965 */ 966 967void 968XDrawArc( 969 Display* display, /* Display. */ 970 Drawable d, /* Draw on this. */ 971 GC gc, /* Use this GC. */ 972 int x, int y, /* Upper left of bounding rect. */ 973 unsigned int width, /* Width & height. */ 974 unsigned int height, 975 int angle1, /* Staring angle of arc. */ 976 int angle2) /* Extent of arc. */ 977{ 978 MacDrawable *macWin = (MacDrawable *) d; 979 TkMacOSXDrawingContext dc; 980 int lw = gc->line_width; 981 982 if (width == 0 || height == 0 || angle2 == 0) { 983 return; 984 } 985 986 display->request++; 987 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 988 return; 989 } 990 if (dc.context) { 991 CGRect rect; 992 double o = (lw % 2) ? .5 : 0; 993 994 rect = CGRectMake( 995 macWin->xOff + x + o, 996 macWin->yOff + y + o, 997 width, height); 998 TK_IF_MAC_OS_X_API_COND (4, CGContextStrokeEllipseInRect, 999 angle1 == 0 && angle2 == 23040, 1000 CGContextStrokeEllipseInRect(dc.context, rect); 1001 ) TK_ELSE ( 1002 CGMutablePathRef p = CGPathCreateMutable(); 1003 CGAffineTransform t = CGAffineTransformIdentity; 1004 CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); 1005 double w = CGRectGetWidth(rect); 1006 1007 if (width != height) { 1008 t = CGAffineTransformMakeScale(1.0, CGRectGetHeight(rect)/w); 1009 c = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t)); 1010 } 1011 CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0), 1012 radians(-(angle1 + angle2)/64.0), angle2 > 0); 1013 CGContextAddPath(dc.context, p); 1014 CGPathRelease(p); 1015 CGContextStrokePath(dc.context); 1016 ) TK_ENDIF 1017 } else { 1018 Rect theRect; 1019 short start, extent; 1020 int o = -lw/2; 1021 1022 theRect.left = (short) (macWin->xOff + x + o); 1023 theRect.top = (short) (macWin->yOff + y + o); 1024 theRect.right = (short) (theRect.left + width + lw); 1025 theRect.bottom = (short) (theRect.top + height + lw); 1026 start = (short) (90 - (angle1/64)); 1027 extent = (short) (-(angle2/64)); 1028 FrameArc(&theRect, start, extent); 1029 } 1030 TkMacOSXRestoreDrawingContext(&dc); 1031} 1032 1033#ifdef TK_MACOSXDRAW_UNUSED 1034/* 1035 *---------------------------------------------------------------------- 1036 * 1037 * XDrawArcs -- 1038 * 1039 * Draws multiple circular or elliptical arcs. Each arc is 1040 * specified by a rectangle and two angles. The center of the 1041 * circle or ellipse is the center of the rect- angle, and the 1042 * major and minor axes are specified by the width and height. 1043 * Positive angles indicate counterclock- wise motion, and 1044 * negative angles indicate clockwise motion. If the magnitude 1045 * of angle2 is greater than 360 degrees, XDrawArcs truncates it 1046 * to 360 degrees. 1047 * 1048 * Results: 1049 * None. 1050 * 1051 * Side effects: 1052 * Draws an arc for each array element on the specified drawable. 1053 * 1054 *---------------------------------------------------------------------- 1055 */ 1056 1057void 1058XDrawArcs( 1059 Display *display, 1060 Drawable d, 1061 GC gc, 1062 XArc *arcArr, 1063 int nArcs) 1064{ 1065 1066 MacDrawable *macWin = (MacDrawable *) d; 1067 TkMacOSXDrawingContext dc; 1068 XArc *arcPtr; 1069 int i, lw = gc->line_width; 1070 1071 display->request++; 1072 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 1073 return; 1074 } 1075 if (dc.context) { 1076 CGRect rect; 1077 double o = (lw % 2) ? .5 : 0; 1078 1079 for (i=0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) { 1080 if (arcPtr->width == 0 || arcPtr->height == 0 1081 || arcPtr->angle2 == 0) { 1082 continue; 1083 } 1084 rect = CGRectMake( 1085 macWin->xOff + arcPtr->x + o, 1086 macWin->yOff + arcPtr->y + o, 1087 arcPtr->width, arcPtr->height); 1088 1089 TK_IF_MAC_OS_X_API_COND (4, CGContextStrokeEllipseInRect, 1090 arcPtr->angle1 == 0 && arcPtr->angle2 == 23040, 1091 CGContextStrokeEllipseInRect(dc.context, rect); 1092 ) TK_ELSE ( 1093 CGMutablePathRef p = CGPathCreateMutable(); 1094 CGAffineTransform t = CGAffineTransformIdentity; 1095 CGPoint c = CGPointMake(CGRectGetMidX(rect), 1096 CGRectGetMidY(rect)); 1097 double w = CGRectGetWidth(rect); 1098 1099 if (arcPtr->width != arcPtr->height) { 1100 t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w); 1101 c = CGPointApplyAffineTransform(c, 1102 CGAffineTransformInvert(t)); 1103 } 1104 CGPathAddArc(p, &t, c.x, c.y, w/2, 1105 radians(-arcPtr->angle1/64.0), 1106 radians(-(arcPtr->angle1 + arcPtr->angle2)/64.0), 1107 arcPtr->angle2 > 0); 1108 CGContextAddPath(dc.context, p); 1109 CGPathRelease(p); 1110 CGContextStrokePath(dc.context); 1111 ) TK_ENDIF 1112 } 1113 } else { 1114 Rect theRect; 1115 short start, extent; 1116 int o = -lw/2; 1117 1118 for (i = 0, arcPtr = arcArr;i < nArcs;i++, arcPtr++) { 1119 theRect.left = (short) (macWin->xOff + arcPtr->x + o); 1120 theRect.top = (short) (macWin->yOff + arcPtr->y + o); 1121 theRect.right = (short) (theRect.left + arcPtr->width + lw); 1122 theRect.bottom = (short) (theRect.top + arcPtr->height + lw); 1123 start = (short) (90 - (arcPtr->angle1/64)); 1124 extent = (short) (-(arcPtr->angle2/64)); 1125 FrameArc(&theRect, start, extent); 1126 } 1127 } 1128 TkMacOSXRestoreDrawingContext(&dc); 1129} 1130#endif 1131 1132/* 1133 *---------------------------------------------------------------------- 1134 * 1135 * XFillArc -- 1136 * 1137 * Draw a filled arc. 1138 * 1139 * Results: 1140 * None. 1141 * 1142 * Side effects: 1143 * Draws a filled arc on the specified drawable. 1144 * 1145 *---------------------------------------------------------------------- 1146 */ 1147 1148void 1149XFillArc( 1150 Display* display, /* Display. */ 1151 Drawable d, /* Draw on this. */ 1152 GC gc, /* Use this GC. */ 1153 int x, int y, /* Upper left of bounding rect. */ 1154 unsigned int width, /* Width & height. */ 1155 unsigned int height, 1156 int angle1, /* Staring angle of arc. */ 1157 int angle2) /* Extent of arc. */ 1158{ 1159 MacDrawable *macWin = (MacDrawable *) d; 1160 TkMacOSXDrawingContext dc; 1161 int lw = gc->line_width; 1162 1163 if (width == 0 || height == 0 || angle2 == 0) { 1164 return; 1165 } 1166 1167 display->request++; 1168 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 1169 return; 1170 } 1171 if (dc.context) { 1172 CGRect rect; 1173 double o = (lw % 2) ? .5 : 0, u = 0; 1174 1175 if (notAA(lw)) { 1176 o += NON_AA_CG_OFFSET/2; 1177 u += NON_AA_CG_OFFSET; 1178 } 1179 rect = CGRectMake( 1180 macWin->xOff + x + o, 1181 macWin->yOff + y + o, 1182 width - u, height - u); 1183 1184 TK_IF_MAC_OS_X_API_COND (4, CGContextFillEllipseInRect, 1185 angle1 == 0 && angle2 == 23040, 1186 CGContextFillEllipseInRect(dc.context, rect); 1187 ) TK_ELSE ( 1188 CGMutablePathRef p = CGPathCreateMutable(); 1189 CGAffineTransform t = CGAffineTransformIdentity; 1190 CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); 1191 double w = CGRectGetWidth(rect); 1192 1193 if (width != height) { 1194 t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w); 1195 c = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t)); 1196 } 1197 if (gc->arc_mode == ArcPieSlice) { 1198 CGPathMoveToPoint(p, &t, c.x, c.y); 1199 } 1200 CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0), 1201 radians(-(angle1 + angle2)/64.0), angle2 > 0); 1202 CGPathCloseSubpath(p); 1203 CGContextAddPath(dc.context, p); 1204 CGPathRelease(p); 1205 CGContextFillPath(dc.context); 1206 ) TK_ENDIF 1207 } else { 1208 Rect theRect; 1209 short start, extent; 1210 int o = -lw/2; 1211 PolyHandle polygon; 1212 double sin1, cos1, sin2, cos2, angle; 1213 double boxWidth, boxHeight; 1214 double vertex[2], center1[2], center2[2]; 1215 1216 theRect.left = (short) (macWin->xOff + x + o); 1217 theRect.top = (short) (macWin->yOff + y + o); 1218 theRect.right = (short) (theRect.left + width + lw); 1219 theRect.bottom = (short) (theRect.top + height + lw); 1220 start = (short) (90 - (angle1/64)); 1221 extent = (short) (-(angle2/64)); 1222 if (gc->arc_mode == ArcChord) { 1223 boxWidth = theRect.right - theRect.left; 1224 boxHeight = theRect.bottom - theRect.top; 1225 angle = radians(-angle1/64.0); 1226 sin1 = sin(angle); 1227 cos1 = cos(angle); 1228 angle -= radians(angle2/64.0); 1229 sin2 = sin(angle); 1230 cos2 = cos(angle); 1231 vertex[0] = (theRect.left + theRect.right)/2.0; 1232 vertex[1] = (theRect.top + theRect.bottom)/2.0; 1233 center1[0] = vertex[0] + cos1*boxWidth/2.0; 1234 center1[1] = vertex[1] + sin1*boxHeight/2.0; 1235 center2[0] = vertex[0] + cos2*boxWidth/2.0; 1236 center2[1] = vertex[1] + sin2*boxHeight/2.0; 1237 1238 polygon = OpenPoly(); 1239 MoveTo((short) ((theRect.left + theRect.right)/2), 1240 (short) ((theRect.top + theRect.bottom)/2)); 1241 LineTo((short) (center1[0] + .5), (short) (center1[1] + .5)); 1242 LineTo((short) (center2[0] + .5), (short) (center2[1] + .5)); 1243 ClosePoly(); 1244 FillCArc(&theRect, start, extent, dc.penPat); 1245 FillCPoly(polygon, dc.penPat); 1246 KillPoly(polygon); 1247 } else { 1248 FillCArc(&theRect, start, extent, dc.penPat); 1249 } 1250 } 1251 TkMacOSXRestoreDrawingContext(&dc); 1252} 1253 1254#ifdef TK_MACOSXDRAW_UNUSED 1255/* 1256 *---------------------------------------------------------------------- 1257 * 1258 * XFillArcs -- 1259 * 1260 * Draw a filled arc. 1261 * 1262 * Results: 1263 * None. 1264 * 1265 * Side effects: 1266 * Draws a filled arc for each array element on the specified drawable. 1267 * 1268 *---------------------------------------------------------------------- 1269 */ 1270 1271void 1272XFillArcs( 1273 Display *display, 1274 Drawable d, 1275 GC gc, 1276 XArc *arcArr, 1277 int nArcs) 1278{ 1279 MacDrawable *macWin = (MacDrawable *) d; 1280 TkMacOSXDrawingContext dc; 1281 XArc * arcPtr; 1282 int i, lw = gc->line_width; 1283 1284 display->request++; 1285 if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { 1286 return; 1287 } 1288 if (dc.context) { 1289 CGRect rect; 1290 double o = (lw % 2) ? .5 : 0, u = 0; 1291 1292 if (notAA(lw)) { 1293 o += NON_AA_CG_OFFSET/2; 1294 u += NON_AA_CG_OFFSET; 1295 } 1296 for (i = 0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) { 1297 if (arcPtr->width == 0 || arcPtr->height == 0 1298 || arcPtr->angle2 == 0) { 1299 continue; 1300 } 1301 rect = CGRectMake( 1302 macWin->xOff + arcPtr->x + o, 1303 macWin->yOff + arcPtr->y + o, 1304 arcPtr->width - u, arcPtr->height - u); 1305 TK_IF_MAC_OS_X_API_COND (4, CGContextFillEllipseInRect, 1306 arcPtr->angle1 == 0 && arcPtr->angle2 == 23040, 1307 CGContextFillEllipseInRect(dc.context, rect); 1308 ) TK_ELSE ( 1309 CGMutablePathRef p = CGPathCreateMutable(); 1310 CGAffineTransform t = CGAffineTransformIdentity; 1311 CGPoint c = CGPointMake(CGRectGetMidX(rect), 1312 CGRectGetMidY(rect)); 1313 double w = CGRectGetWidth(rect); 1314 1315 if (arcPtr->width != arcPtr->height) { 1316 t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w); 1317 c = CGPointApplyAffineTransform(c, 1318 CGAffineTransformInvert(t)); 1319 } 1320 if (gc->arc_mode == ArcPieSlice) { 1321 CGPathMoveToPoint(p, &t, c.x, c.y); 1322 } 1323 CGPathAddArc(p, &t, c.x, c.y, w/2, 1324 radians(-arcPtr->angle1/64.0), 1325 radians(-(arcPtr->angle1 + arcPtr->angle2)/64.0), 1326 arcPtr->angle2 > 0); 1327 CGPathCloseSubpath(p); 1328 CGContextAddPath(dc.context, p); 1329 CGPathRelease(p); 1330 CGContextFillPath(dc.context); 1331 ) TK_ENDIF 1332 } 1333 } else { 1334 Rect theRect; 1335 short start, extent; 1336 int o = -lw/2; 1337 PolyHandle polygon; 1338 double sin1, cos1, sin2, cos2, angle; 1339 double boxWidth, boxHeight; 1340 double vertex[2], center1[2], center2[2]; 1341 1342 for (i = 0, arcPtr = arcArr;i<nArcs;i++, arcPtr++) { 1343 theRect.left = (short) (macWin->xOff + arcPtr->x + o); 1344 theRect.top = (short) (macWin->yOff + arcPtr->y + o); 1345 theRect.right = (short) (theRect.left + arcPtr->width + lw); 1346 theRect.bottom = (short) (theRect.top + arcPtr->height + lw); 1347 start = (short) (90 - (arcPtr->angle1/64)); 1348 extent = (short) (- (arcPtr->angle2/64)); 1349 1350 if (gc->arc_mode == ArcChord) { 1351 boxWidth = theRect.right - theRect.left; 1352 boxHeight = theRect.bottom - theRect.top; 1353 angle = radians(-arcPtr->angle1/64.0); 1354 sin1 = sin(angle); 1355 cos1 = cos(angle); 1356 angle -= radians(arcPtr->angle2/64.0); 1357 sin2 = sin(angle); 1358 cos2 = cos(angle); 1359 vertex[0] = (theRect.left + theRect.right)/2.0; 1360 vertex[1] = (theRect.top + theRect.bottom)/2.0; 1361 center1[0] = vertex[0] + cos1*boxWidth/2.0; 1362 center1[1] = vertex[1] + sin1*boxHeight/2.0; 1363 center2[0] = vertex[0] + cos2*boxWidth/2.0; 1364 center2[1] = vertex[1] + sin2*boxHeight/2.0; 1365 1366 polygon = OpenPoly(); 1367 MoveTo((short) ((theRect.left + theRect.right)/2), 1368 (short) ((theRect.top + theRect.bottom)/2)); 1369 LineTo((short) (center1[0] + .5), (short) (center1[1] + .5)); 1370 LineTo((short) (center2[0] + .5), (short) (center2[1] + .5)); 1371 ClosePoly(); 1372 FillCArc(&theRect, start, extent, dc.penPat); 1373 FillCPoly(polygon, dc.penPat); 1374 KillPoly(polygon); 1375 } else { 1376 FillCArc(&theRect, start, extent, dc.penPat); 1377 } 1378 } 1379 } 1380 TkMacOSXRestoreDrawingContext(&dc); 1381} 1382#endif 1383 1384#ifdef TK_MACOSXDRAW_UNUSED 1385/* 1386 *---------------------------------------------------------------------- 1387 * 1388 * XMaxRequestSize -- 1389 * 1390 *---------------------------------------------------------------------- 1391 */ 1392 1393long 1394XMaxRequestSize( 1395 Display *display) 1396{ 1397 return (SHRT_MAX / 4); 1398} 1399#endif 1400 1401/* 1402 *---------------------------------------------------------------------- 1403 * 1404 * TkScrollWindow -- 1405 * 1406 * Scroll a rectangle of the specified window and accumulate 1407 * a damage region. 1408 * 1409 * Results: 1410 * Returns 0 if the scroll genereated no additional damage. 1411 * Otherwise, sets the region that needs to be repainted after 1412 * scrolling and returns 1. 1413 * 1414 * Side effects: 1415 * Scrolls the bits in the window. 1416 * 1417 *---------------------------------------------------------------------- 1418 */ 1419 1420int 1421TkScrollWindow( 1422 Tk_Window tkwin, /* The window to be scrolled. */ 1423 GC gc, /* GC for window to be scrolled. */ 1424 int x, int y, /* Position rectangle to be scrolled. */ 1425 int width, int height, 1426 int dx, int dy, /* Distance rectangle should be moved. */ 1427 TkRegion damageRgn) /* Region to accumulate damage in. */ 1428{ 1429 MacDrawable *destDraw = (MacDrawable *) Tk_WindowId(tkwin); 1430 CGrafPtr destPort, savePort; 1431 Boolean portChanged; 1432 Rect scrollRect; 1433 int result; 1434 HIShapeRef dmgRgn; 1435 1436 /* 1437 * Due to the implementation below the behavior may be differnt 1438 * than X in certain cases that should never occur in Tk. The 1439 * scrollRect is the source rect extended by the offset (the union 1440 * of the source rect and the offset rect). Everything 1441 * in the extended scrollRect is scrolled. On X, it's possible 1442 * to "skip" over an area if the offset makes the source and 1443 * destination rects disjoint and non-aligned. 1444 */ 1445 1446 scrollRect.left = destDraw->xOff + x; 1447 scrollRect.top = destDraw->yOff + y; 1448 scrollRect.right = scrollRect.left + width; 1449 scrollRect.bottom = scrollRect.top + height; 1450 if (dx < 0) { 1451 scrollRect.left += dx; 1452 } else { 1453 scrollRect.right += dx; 1454 } 1455 if (dy < 0) { 1456 scrollRect.top += dy; 1457 } else { 1458 scrollRect.bottom += dy; 1459 } 1460 1461 destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); 1462 TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); 1463 TkMacOSXCheckTmpQdRgnEmpty(); 1464 portChanged = QDSwapPort(destPort, &savePort); 1465 ScrollRect(&scrollRect, dx, dy, tkMacOSXtmpQdRgn); 1466 if (portChanged) { 1467 QDSwapPort(savePort, NULL); 1468 } 1469 1470 /* 1471 * Fortunately, the region returned by ScrollRect is semantically 1472 * the same as what we need to return in this function. If the 1473 * region is empty we return zero to denote that no damage was 1474 * created. 1475 */ 1476 1477 dmgRgn = HIShapeCreateWithQDRgn(tkMacOSXtmpQdRgn); 1478 SetEmptyRgn(tkMacOSXtmpQdRgn); 1479 TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn); 1480 result = HIShapeIsEmpty(dmgRgn) ? 0 : 1; 1481 CFRelease(dmgRgn); 1482 1483 return result; 1484} 1485 1486/* 1487 *---------------------------------------------------------------------- 1488 * 1489 * TkMacOSXSetUpGraphicsPort -- 1490 * 1491 * Set up the graphics port from the given GC. 1492 * 1493 * Results: 1494 * None. 1495 * 1496 * Side effects: 1497 * The current port is adjusted. 1498 * 1499 *---------------------------------------------------------------------- 1500 */ 1501 1502void 1503TkMacOSXSetUpGraphicsPort( 1504 GC gc, /* GC to apply to current port. */ 1505 GWorldPtr destPort) 1506{ 1507 CGrafPtr savePort; 1508 Boolean portChanged; 1509 1510 portChanged = QDSwapPort(destPort, &savePort); 1511 PenNormal(); 1512 if (gc) { 1513 if (!penPat) { 1514 if (!tmpPixPat) { 1515 penPat = NewPixPat(); 1516 } else { 1517 penPat = tmpPixPat; 1518 tmpPixPat = NULL; 1519 } 1520 } 1521 TkMacOSXSetColorInPort(gc->foreground, 1, penPat, destPort); 1522 PenPixPat(penPat); 1523 if(gc->function == GXxor) { 1524 PenMode(patXor); 1525 } 1526 if (gc->line_width > 1) { 1527 PenSize(gc->line_width, gc->line_width); 1528 } 1529 if (gc->line_style != LineSolid) { 1530 /* 1531 * FIXME: Here the dash pattern should be set in the drawing 1532 * environment. This is not possible with QuickDraw line drawing. 1533 */ 1534 } 1535 } 1536 if (portChanged) { 1537 QDSwapPort(savePort, NULL); 1538 } 1539} 1540 1541/* 1542 *---------------------------------------------------------------------- 1543 * 1544 * TkMacOSXSetUpDrawingContext -- 1545 * 1546 * Set up a drawing context for the given drawable and GC. 1547 * 1548 * Results: 1549 * Boolean indicating whether it is ok to draw; if false, drawing 1550 * context was not setup, so do not attempt to draw and do not call 1551 * TkMacOSXRestoreDrawingContext(). 1552 * 1553 * Side effects: 1554 * None. 1555 * 1556 *---------------------------------------------------------------------- 1557 */ 1558 1559int 1560TkMacOSXSetupDrawingContext( 1561 Drawable d, 1562 GC gc, 1563 int useCG, /* advisory only ! */ 1564 TkMacOSXDrawingContext *dcPtr) 1565{ 1566 MacDrawable *macDraw = ((MacDrawable*)d); 1567 int dontDraw = 0; 1568 TkMacOSXDrawingContext dc = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1569 {SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX}, false}; 1570 1571 if (tkPictureIsOpen) { 1572 if (useCG) { 1573 TkMacOSXDbgMsg("Ignored CG Drawing with QD Picture open"); 1574 dontDraw = 1; 1575 } 1576 } else { 1577 dc.clipRgn = TkMacOSXGetClipRgn(d); 1578 } 1579 if (!dontDraw) { 1580 ClipToGC(d, gc, &dc.clipRgn); 1581 dontDraw = dc.clipRgn ? HIShapeIsEmpty(dc.clipRgn) : 0; 1582 } 1583 if (dontDraw) { 1584 if (dc.clipRgn) { 1585 CFRelease(dc.clipRgn); 1586 dc.clipRgn = NULL; 1587 } 1588 goto end; 1589 } 1590 if (useCG) { 1591 dc.context = macDraw->context; 1592 } 1593 if (!dc.context || !(macDraw->flags & TK_IS_PIXMAP)) { 1594 dc.port = TkMacOSXGetDrawablePort(d); 1595 if (dc.port) { 1596 GetPortBounds(dc.port, &dc.portBounds); 1597 } 1598 } 1599 if (dc.context) { 1600 if (!dc.port) { 1601 CGRect r; 1602 1603 TK_IF_MAC_OS_X_API (3, CGContextGetClipBoundingBox, 1604 r = CGContextGetClipBoundingBox(dc.context); 1605 ) TK_ELSE_MAC_OS_X (3, 1606 r.origin = CGPointZero; 1607 r.size = macDraw->size; 1608 ) TK_ENDIF 1609 SetRect(&dc.portBounds, r.origin.x + macDraw->xOff, 1610 r.origin.y + macDraw->yOff, 1611 r.origin.x + r.size.width + macDraw->xOff, 1612 r.origin.y + r.size.height + macDraw->yOff); 1613 } 1614 CGContextSaveGState(dc.context); 1615 dc.saveState = (void*)1; 1616 dc.port = NULL; 1617 } else if (dc.port) { 1618 dc.portChanged = QDSwapPort(dc.port, &dc.savePort); 1619 if (useCG && ChkErr(QDBeginCGContext, dc.port, &dc.context) == noErr) { 1620 SyncCGContextOriginWithPort(dc.context, dc.port); 1621 } else { 1622 dc.context = NULL; 1623 } 1624 } else { 1625 Tcl_Panic("TkMacOSXSetupDrawingContext(): " 1626 "no port or context to draw into !"); 1627 } 1628 if (dc.context) { 1629 CGContextConcatCTM(dc.context, CGAffineTransformMake(1.0, 0.0, 0.0, 1630 -1.0, 0.0, dc.portBounds.bottom - dc.portBounds.top)); 1631 if (dc.clipRgn) { 1632#ifdef TK_MAC_DEBUG_DRAWING 1633 CGContextSaveGState(dc.context); 1634 ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); 1635 CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.2); 1636 CGContextEOFillPath(dc.context); 1637 CGContextRestoreGState(dc.context); 1638#endif /* TK_MAC_DEBUG_DRAWING */ 1639 ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); 1640 CGContextEOClip(dc.context); 1641 } 1642 if (gc) { 1643 static const CGLineCap cgCap[] = { 1644 [CapNotLast] = kCGLineCapButt, 1645 [CapButt] = kCGLineCapButt, 1646 [CapRound] = kCGLineCapRound, 1647 [CapProjecting] = kCGLineCapSquare, 1648 }; 1649 static const CGLineJoin cgJoin[] = { 1650 [JoinMiter] = kCGLineJoinMiter, 1651 [JoinRound] = kCGLineJoinRound, 1652 [JoinBevel] = kCGLineJoinBevel, 1653 }; 1654 bool shouldAntialias; 1655 double w = gc->line_width; 1656 1657 TkMacOSXSetColorInContext(gc->foreground, dc.context); 1658 if (dc.port) { 1659 CGContextSetPatternPhase(dc.context, CGSizeMake( 1660 dc.portBounds.right - dc.portBounds.left, 1661 dc.portBounds.bottom - dc.portBounds.top)); 1662 } 1663 if(gc->function != GXcopy) { 1664 TkMacOSXDbgMsg("Logical functions other than GXcopy are " 1665 "not supported for CG drawing!"); 1666 } 1667 /* When should we antialias? */ 1668 shouldAntialias = !notAA(gc->line_width); 1669 if (!shouldAntialias) { 1670 /* Make non-antialiased CG drawing look more like X11 */ 1671 w -= (gc->line_width ? NON_AA_CG_OFFSET : 0); 1672 } 1673 CGContextSetShouldAntialias(dc.context, shouldAntialias); 1674 CGContextSetLineWidth(dc.context, w); 1675 if (gc->line_style != LineSolid) { 1676 int num = 0; 1677 char *p = &(gc->dashes); 1678 double dashOffset = gc->dash_offset; 1679 float lengths[10]; 1680 1681 while (p[num] != '\0' && num < 10) { 1682 lengths[num] = p[num]; 1683 num++; 1684 } 1685 CGContextSetLineDash(dc.context, dashOffset, lengths, num); 1686 } 1687 if ((unsigned)gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) { 1688 CGContextSetLineCap(dc.context, 1689 cgCap[(unsigned)gc->cap_style]); 1690 } 1691 if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) { 1692 CGContextSetLineJoin(dc.context, 1693 cgJoin[(unsigned)gc->join_style]); 1694 } 1695 } 1696 } else if (dc.port) { 1697 PixPatHandle savePat = penPat; 1698 1699 ChkErr(GetThemeDrawingState, &dc.saveState); 1700 penPat = NULL; 1701 TkMacOSXSetUpGraphicsPort(gc, dc.port); 1702 dc.penPat = penPat; 1703 penPat = savePat; 1704 dc.saveClip = NewRgn(); 1705 GetPortClipRegion(dc.port, dc.saveClip); 1706 if (dc.clipRgn) { 1707 ChkErr(HIShapeSetQDClip, dc.clipRgn, dc.port); 1708 } else { 1709 NoQDClip(dc.port); 1710 } 1711 if (!tkPictureIsOpen) { 1712 ShowPen(); 1713 } 1714 } 1715end: 1716 *dcPtr = dc; 1717 return !dontDraw; 1718} 1719 1720/* 1721 *---------------------------------------------------------------------- 1722 * 1723 * TkMacOSXRestoreDrawingContext -- 1724 * 1725 * Restore drawing context. 1726 * 1727 * Results: 1728 * None. 1729 * 1730 * Side effects: 1731 * None. 1732 * 1733 *---------------------------------------------------------------------- 1734 */ 1735 1736void 1737TkMacOSXRestoreDrawingContext( 1738 TkMacOSXDrawingContext *dcPtr) 1739{ 1740 if (dcPtr->context) { 1741 CGContextSynchronize(dcPtr->context); 1742 if (dcPtr->saveState) { 1743 CGContextRestoreGState(dcPtr->context); 1744 } 1745 if (dcPtr->port) { 1746 ChkErr(QDEndCGContext, dcPtr->port, &(dcPtr->context)); 1747 } 1748 } else if (dcPtr->port) { 1749 if (!tkPictureIsOpen) { 1750 HidePen(); 1751 } 1752 PenNormal(); 1753 if (dcPtr->saveClip) { 1754 SetPortClipRegion(dcPtr->port, dcPtr->saveClip); 1755 DisposeRgn(dcPtr->saveClip); 1756 } 1757 if (dcPtr->penPat) { 1758 if (!tmpPixPat) { 1759 tmpPixPat = dcPtr->penPat; 1760 } else { 1761 DisposePixPat(dcPtr->penPat); 1762 } 1763 } 1764 if (dcPtr->saveState) { 1765 ChkErr(SetThemeDrawingState, dcPtr->saveState, true); 1766 } 1767 } 1768 if (dcPtr->clipRgn) { 1769 CFRelease(dcPtr->clipRgn); 1770 } 1771 if (dcPtr->portChanged) { 1772 QDSwapPort(dcPtr->savePort, NULL); 1773 } 1774#ifdef TK_MAC_DEBUG 1775 bzero(dcPtr, sizeof(TkMacOSXDrawingContext)); 1776#endif /* TK_MAC_DEBUG */ 1777} 1778 1779/* 1780 *---------------------------------------------------------------------- 1781 * 1782 * TkMacOSXGetClipRgn -- 1783 * 1784 * Get the clipping region needed to restrict drawing to the given 1785 * drawable. 1786 * 1787 * Results: 1788 * Clipping region. If non-NULL, CFRelease it when done. 1789 * 1790 * Side effects: 1791 * None. 1792 * 1793 *---------------------------------------------------------------------- 1794 */ 1795 1796HIShapeRef 1797TkMacOSXGetClipRgn( 1798 Drawable drawable) /* Drawable. */ 1799{ 1800 MacDrawable *macDraw = (MacDrawable *) drawable; 1801 HIShapeRef clipRgn = NULL; 1802 CGRect r; 1803 1804 if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) { 1805 TkMacOSXUpdateClipRgn(macDraw->winPtr); 1806#ifdef TK_MAC_DEBUG_DRAWING 1807 TkMacOSXDbgMsg("%s visRgn ", macDraw->winPtr->pathName); 1808 TkMacOSXDebugFlashRegion(drawable, macDraw->visRgn); 1809#endif /* TK_MAC_DEBUG_DRAWING */ 1810 } 1811 1812 if (macDraw->flags & TK_CLIPPED_DRAW) { 1813 r = CGRectOffset(macDraw->drawRect, macDraw->xOff, macDraw->yOff); 1814 } 1815 if (macDraw->visRgn) { 1816 if (macDraw->flags & TK_CLIPPED_DRAW) { 1817 HIShapeRef rgn = HIShapeCreateWithRect(&r); 1818 1819 clipRgn = HIShapeCreateIntersection(macDraw->visRgn, rgn); 1820 CFRelease(rgn); 1821 } else { 1822 clipRgn = HIShapeCreateCopy(macDraw->visRgn); 1823 } 1824 } else if (macDraw->flags & TK_CLIPPED_DRAW) { 1825 clipRgn = HIShapeCreateWithRect(&r); 1826 } 1827#ifdef TK_MAC_DEBUG_DRAWING 1828 TkMacOSXDbgMsg("%s clipRgn ", macDraw->winPtr->pathName); 1829 TkMacOSXDebugFlashRegion(drawable, clipRgn); 1830#endif /* TK_MAC_DEBUG_DRAWING */ 1831 1832 return clipRgn; 1833} 1834 1835/* 1836 *---------------------------------------------------------------------- 1837 * 1838 * TkMacOSXSetUpClippingRgn -- 1839 * 1840 * Set up the clipping region so that drawing only occurs on the 1841 * specified X subwindow. 1842 * 1843 * Results: 1844 * None. 1845 * 1846 * Side effects: 1847 * The clipping region in the current port is changed. 1848 * 1849 *---------------------------------------------------------------------- 1850 */ 1851 1852void 1853TkMacOSXSetUpClippingRgn( 1854 Drawable drawable) /* Drawable to update. */ 1855{ 1856 CGrafPtr port = TkMacOSXGetDrawablePort(drawable); 1857 1858 if (port) { 1859 HIShapeRef clipRgn = TkMacOSXGetClipRgn(drawable); 1860 1861 if (clipRgn) { 1862 ChkErr(HIShapeSetQDClip, clipRgn, port); 1863 CFRelease(clipRgn); 1864 } 1865 } 1866} 1867 1868/* 1869 *---------------------------------------------------------------------- 1870 * 1871 * TkpClipDrawableToRect -- 1872 * 1873 * Clip all drawing into the drawable d to the given rectangle. 1874 * If width and height are negative, reset to no clipping. 1875 * 1876 * Results: 1877 * None. 1878 * 1879 * Side effects: 1880 * Subsequent drawing into d is offset and clipped as specified. 1881 * 1882 *---------------------------------------------------------------------- 1883 */ 1884 1885void 1886TkpClipDrawableToRect( 1887 Display *display, 1888 Drawable d, 1889 int x, int y, 1890 int width, int height) 1891{ 1892 MacDrawable *macDraw = (MacDrawable *) d; 1893 1894 if (width < 0 && height < 0) { 1895 macDraw->drawRect = CGRectNull; 1896 macDraw->flags &= ~TK_CLIPPED_DRAW; 1897 } else { 1898 macDraw->drawRect = CGRectMake(x, y, width, height); 1899 macDraw->flags |= TK_CLIPPED_DRAW; 1900 } 1901} 1902 1903/* 1904 *---------------------------------------------------------------------- 1905 * 1906 * ClipToGC -- 1907 * 1908 * Helper function to intersect given region with gc clip region. 1909 * 1910 * Results: 1911 * None. 1912 * 1913 * Side effects: 1914 * None. 1915 * 1916 *---------------------------------------------------------------------- 1917 */ 1918 1919static void 1920ClipToGC( 1921 Drawable d, 1922 GC gc, 1923 HIShapeRef *clipRgnPtr) /* must point to initialized variable */ 1924{ 1925 if (gc && gc->clip_mask && 1926 ((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) { 1927 TkRegion gcClip = ((TkpClipMask*)gc->clip_mask)->value.region; 1928 int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin; 1929 int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin; 1930 HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn; 1931 1932 if (!tkPictureIsOpen) { 1933 TkMacOSXOffsetRegion(gcClip, xOffset, yOffset); 1934 } 1935 gcClipRgn = TkMacOSXGetNativeRegion(gcClip); 1936 if (clipRgn) { 1937 *clipRgnPtr = HIShapeCreateIntersection(gcClipRgn, clipRgn); 1938 CFRelease(clipRgn); 1939 } else { 1940 *clipRgnPtr = HIShapeCreateCopy(gcClipRgn); 1941 } 1942 CFRelease(gcClipRgn); 1943 if (!tkPictureIsOpen) { 1944 TkMacOSXOffsetRegion(gcClip, -xOffset, -yOffset); 1945 } 1946 } 1947} 1948 1949/* 1950 *---------------------------------------------------------------------- 1951 * 1952 * NoQDClip -- 1953 * 1954 * Helper function to setup a QD port to not clip anything. 1955 * 1956 * Results: 1957 * None. 1958 * 1959 * Side effects: 1960 * None. 1961 * 1962 *---------------------------------------------------------------------- 1963 */ 1964 1965static void 1966NoQDClip( 1967 CGrafPtr port) 1968{ 1969 static RgnHandle noClipRgn = NULL; 1970 1971 if (!noClipRgn) { 1972 noClipRgn = NewRgn(); 1973 SetRectRgn(noClipRgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX); 1974 } 1975 SetPortClipRegion(port, noClipRgn); 1976} 1977 1978/* 1979 *---------------------------------------------------------------------- 1980 * 1981 * TkMacOSXMakeStippleMap -- 1982 * 1983 * Given a drawable and a stipple pattern this function draws the 1984 * pattern repeatedly over the drawable. The drawable can then 1985 * be used as a mask for bit-bliting a stipple pattern over an 1986 * object. 1987 * 1988 * Results: 1989 * A BitMap data structure. 1990 * 1991 * Side effects: 1992 * None. 1993 * 1994 *---------------------------------------------------------------------- 1995 */ 1996 1997BitMapPtr 1998TkMacOSXMakeStippleMap( 1999 Drawable drawable, /* Window to apply stipple. */ 2000 Drawable stipple) /* The stipple pattern. */ 2001{ 2002 CGrafPtr stipplePort; 2003 BitMapPtr bitmapPtr; 2004 const BitMap *stippleBitmap; 2005 Rect portRect; 2006 int width, height, stippleHeight, stippleWidth, i, j; 2007 Rect bounds; 2008 2009 GetPortBounds(TkMacOSXGetDrawablePort(drawable), &portRect); 2010 width = portRect.right - portRect.left; 2011 height = portRect.bottom - portRect.top; 2012 bitmapPtr = (BitMap *) ckalloc(sizeof(BitMap)); 2013 bitmapPtr->bounds.top = bitmapPtr->bounds.left = 0; 2014 bitmapPtr->bounds.right = (short) width; 2015 bitmapPtr->bounds.bottom = (short) height; 2016 bitmapPtr->rowBytes = (width / 8) + 1; 2017 bitmapPtr->baseAddr = ckalloc(height * bitmapPtr->rowBytes); 2018 2019 stipplePort = TkMacOSXGetDrawablePort(stipple); 2020 stippleBitmap = GetPortBitMapForCopyBits(stipplePort); 2021 GetPortBounds(stipplePort, &portRect); 2022 stippleWidth = portRect.right - portRect.left; 2023 stippleHeight = portRect.bottom - portRect.top; 2024 2025 for (i = 0; i < height; i += stippleHeight) { 2026 for (j = 0; j < width; j += stippleWidth) { 2027 bounds.left = j; 2028 bounds.top = i; 2029 bounds.right = j + stippleWidth; 2030 bounds.bottom = i + stippleHeight; 2031 CopyBits(stippleBitmap, bitmapPtr, &portRect, &bounds, srcCopy, 2032 NULL); 2033 } 2034 } 2035 return bitmapPtr; 2036} 2037 2038/* 2039 *---------------------------------------------------------------------- 2040 * 2041 * TkpDrawHighlightBorder -- 2042 * 2043 * This procedure draws a rectangular ring around the outside of 2044 * a widget to indicate that it has received the input focus. 2045 * 2046 * On the Macintosh, this puts a 1 pixel border in the bgGC color 2047 * between the widget and the focus ring, except in the case where 2048 * highlightWidth is 1, in which case the border is left out. 2049 * 2050 * For proper Mac L&F, use highlightWidth of 3. 2051 * 2052 * Results: 2053 * None. 2054 * 2055 * Side effects: 2056 * A rectangle "width" pixels wide is drawn in "drawable", 2057 * corresponding to the outer area of "tkwin". 2058 * 2059 *---------------------------------------------------------------------- 2060 */ 2061 2062void 2063TkpDrawHighlightBorder ( 2064 Tk_Window tkwin, 2065 GC fgGC, 2066 GC bgGC, 2067 int highlightWidth, 2068 Drawable drawable) 2069{ 2070 if (highlightWidth == 1) { 2071 TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth, drawable, 0); 2072 } else { 2073 TkDrawInsetFocusHighlight (tkwin, bgGC, highlightWidth, drawable, 0); 2074 if (fgGC != bgGC) { 2075 TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth - 1, 2076 drawable, 0); 2077 } 2078 } 2079} 2080 2081/* 2082 *---------------------------------------------------------------------- 2083 * 2084 * TkpDrawFrame -- 2085 * 2086 * This procedure draws the rectangular frame area. If the user 2087 * has request themeing, it draws with a the background theme. 2088 * 2089 * Results: 2090 * None. 2091 * 2092 * Side effects: 2093 * Draws inside the tkwin area. 2094 * 2095 *---------------------------------------------------------------------- 2096 */ 2097 2098void 2099TkpDrawFrame( 2100 Tk_Window tkwin, 2101 Tk_3DBorder border, 2102 int highlightWidth, 2103 int borderWidth, 2104 int relief) 2105{ 2106 if (useThemedToplevel && Tk_IsTopLevel(tkwin)) { 2107 static Tk_3DBorder themedBorder = NULL; 2108 2109 if (!themedBorder) { 2110 themedBorder = Tk_Get3DBorder(NULL, tkwin, 2111 "systemWindowHeaderBackground"); 2112 } 2113 if (themedBorder) { 2114 border = themedBorder; 2115 } 2116 } 2117 Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), 2118 border, highlightWidth, highlightWidth, 2119 Tk_Width(tkwin) - 2 * highlightWidth, 2120 Tk_Height(tkwin) - 2 * highlightWidth, 2121 borderWidth, relief); 2122} 2123