1/* 2 NSBitmapImageRep_PPUtilities_ImageBitmaps.m 3 4 Copyright 2013-2018 Josh Freeman 5 http://www.twilightedge.com 6 7 This file is part of PikoPixel for Mac OS X and GNUstep. 8 PikoPixel is a graphical application for drawing & editing pixel-art images. 9 10 PikoPixel is free software: you can redistribute it and/or modify it under 11 the terms of the GNU Affero General Public License as published by the 12 Free Software Foundation, either version 3 of the License, or (at your 13 option) any later version approved for PikoPixel by its copyright holder (or 14 an authorized proxy). 15 16 PikoPixel is distributed in the hope that it will be useful, but WITHOUT ANY 17 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more 19 details. 20 21 You should have received a copy of the GNU Affero General Public License 22 along with this program. If not, see <http://www.gnu.org/licenses/>. 23*/ 24 25#import "NSBitmapImageRep_PPUtilities.h" 26 27#import "PPDefines.h" 28#import "PPGeometry.h" 29#import "NSColor_PPUtilities.h" 30#import "NSImage_PPUtilities.h" 31 32 33#define kImageBitmapBitsPerSample \ 34 (sizeof(PPImagePixelComponent) * 8) 35 36#define kImageBitmapSamplesPerPixel \ 37 (sizeof(PPImageBitmapPixel) / sizeof(PPImagePixelComponent)) 38 39 40#define kMaxScalingFactorToForceDotsGridType 6 41#define kCrosshairLegSizeToScalingFactorRatio (1.0/7.0) 42 43 44@implementation NSBitmapImageRep (PPUtilities_ImageBitmaps) 45 46+ (NSBitmapImageRep *) ppImageBitmapOfSize: (NSSize) size 47{ 48 NSBitmapImageRep *imageBitmap; 49 50 size = PPGeometry_SizeClippedToIntegerValues(size); 51 52 if (PPGeometry_IsZeroSize(size)) 53 { 54 goto ERROR; 55 } 56 57 imageBitmap = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL 58 pixelsWide: size.width 59 pixelsHigh: size.height 60 bitsPerSample: kImageBitmapBitsPerSample 61 samplesPerPixel: kImageBitmapSamplesPerPixel 62 hasAlpha: YES 63 isPlanar: NO 64 colorSpaceName: NSCalibratedRGBColorSpace 65 bytesPerRow: 0 66 bitsPerPixel: 0] 67 autorelease]; 68 69 if (!imageBitmap) 70 goto ERROR; 71 72 // use sRGB colorspace 73 [imageBitmap ppAttachSRGBColorProfile]; 74 75 [imageBitmap ppClearBitmap]; 76 77 return imageBitmap; 78 79ERROR: 80 return nil; 81} 82 83+ (NSBitmapImageRep *) ppImageBitmapWithImportedData: (NSData *) importedData 84{ 85 return [[NSBitmapImageRep imageRepWithData: importedData] ppImageBitmap]; 86} 87 88+ (NSBitmapImageRep *) ppImageBitmapFromImageResource: (NSString *) imageName 89{ 90 NSString *imageResourcePath; 91 NSData *imageData; 92 93 if (!imageName) 94 goto ERROR; 95 96 imageResourcePath = [[NSBundle mainBundle] pathForImageResource: imageName]; 97 98 if (!imageResourcePath) 99 goto ERROR; 100 101 imageData = [NSData dataWithContentsOfFile: imageResourcePath]; 102 103 if (!imageData) 104 goto ERROR; 105 106 return [NSBitmapImageRep ppImageBitmapWithImportedData: imageData]; 107 108ERROR: 109 return nil; 110} 111 112- (bool) ppIsImageBitmap 113{ 114 return (([self samplesPerPixel] == kImageBitmapSamplesPerPixel) 115 && ([self bitsPerSample] == kImageBitmapBitsPerSample)) 116 ? YES : NO; 117} 118 119- (bool) ppIsImageBitmapAndSameSizeAsMaskBitmap: (NSBitmapImageRep *) maskBitmap 120{ 121 if ([self ppIsImageBitmap] 122 && [maskBitmap ppIsMaskBitmap] 123 && NSEqualSizes([self ppSizeInPixels], [maskBitmap ppSizeInPixels])) 124 { 125 return YES; 126 } 127 else 128 { 129 return NO; 130 } 131} 132 133// ppImageColorAtPoint: is used instead of the Cocoa-native -[NSBitmapImageRep colorAtX:y:], 134// because it returns image-bitmap colors in the correct colorspace (sRGB); As of OS X 10.6, 135// colorAtX:y: incorrectly ignores image-bitmaps' custom colorspace, returning colors in 136// NSCalibratedRGBColorSpace 137 138- (NSColor *) ppImageColorAtPoint: (NSPoint) point 139{ 140 NSRect bitmapFrame; 141 unsigned char *bitmapData; 142 int rowOffset, dataOffset; 143 PPImageBitmapPixel *bitmapPixel; 144 CGFloat alphaComponent, redValue, greenValue, blueValue, alphaValue; 145 146 if (![self ppIsImageBitmap]) 147 { 148 goto ERROR; 149 } 150 151 bitmapFrame = [self ppFrameInPixels]; 152 153 point = PPGeometry_PointClippedToRect(PPGeometry_PointClippedToIntegerValues(point), 154 bitmapFrame); 155 156 bitmapData = [self bitmapData]; 157 158 if (!bitmapData) 159 goto ERROR; 160 161 rowOffset = bitmapFrame.size.height - 1 - point.y; 162 163 dataOffset = rowOffset * [self bytesPerRow] + point.x * sizeof(PPImageBitmapPixel); 164 165 bitmapPixel = (PPImageBitmapPixel *) &bitmapData[dataOffset]; 166 167 alphaComponent = macroImagePixelComponent_Alpha(bitmapPixel); 168 169 if (alphaComponent > 0) 170 { 171 // nonzero alpha: un-premultiply RGB components 172 redValue= ((CGFloat) macroImagePixelComponent_Red(bitmapPixel)) / alphaComponent; 173 174 greenValue = ((CGFloat) macroImagePixelComponent_Green(bitmapPixel)) / alphaComponent; 175 176 blueValue = ((CGFloat) macroImagePixelComponent_Blue(bitmapPixel)) / alphaComponent; 177 178 alphaValue = alphaComponent / ((CGFloat) kMaxImagePixelComponentValue); 179 } 180 else 181 { 182 // zero alpha: all components are zero due to premultiply 183 redValue = greenValue = blueValue = alphaValue = 0; 184 } 185 186 return [NSColor ppSRGBColorWithRed: redValue 187 green: greenValue 188 blue: blueValue 189 alpha: alphaValue]; 190 191ERROR: 192 return nil; 193} 194 195- (bool) ppImageBitmapHasTransparentPixels 196{ 197 unsigned char *bitmapRow; 198 int bytesPerRow, pixelsPerRow, rowCounter, pixelCounter; 199 NSSize bitmapSize; 200 PPImageBitmapPixel *bitmapPixel; 201 202 if (![self ppIsImageBitmap]) 203 { 204 goto ERROR; 205 } 206 207 bitmapRow = [self bitmapData]; 208 209 if (!bitmapRow) 210 goto ERROR; 211 212 bytesPerRow = [self bytesPerRow]; 213 214 bitmapSize = [self ppSizeInPixels]; 215 216 pixelsPerRow = bitmapSize.width; 217 rowCounter = bitmapSize.height; 218 219 while (rowCounter--) 220 { 221 bitmapPixel = (PPImageBitmapPixel *) bitmapRow; 222 pixelCounter = pixelsPerRow; 223 224 while (pixelCounter--) 225 { 226 if (macroImagePixelComponent_Alpha(bitmapPixel) != kMaxImagePixelComponentValue) 227 { 228 return YES; 229 } 230 231 bitmapPixel++; 232 } 233 234 bitmapRow += bytesPerRow; 235 } 236 237 return NO; 238 239ERROR: 240 return NO; 241} 242 243- (void) ppMaskedFillUsingMask: (NSBitmapImageRep *) maskBitmap 244 inBounds: (NSRect) fillBounds 245 fillPixelValue: (PPImageBitmapPixel) fillPixelValue 246{ 247 NSRect bitmapFrame; 248 unsigned char *destinationData, *maskData, *destinationRow, *maskRow; 249 int destinationBytesPerRow, maskBytesPerRow, rowOffset, destinationDataOffset, 250 maskDataOffset, pixelsPerRow, rowCounter, pixelCounter; 251 PPImageBitmapPixel *destinationPixel; 252 PPMaskBitmapPixel *maskPixel; 253 254 if (![self ppIsImageBitmapAndSameSizeAsMaskBitmap: maskBitmap]) 255 { 256 goto ERROR; 257 } 258 259 bitmapFrame = [self ppFrameInPixels]; 260 261 fillBounds = 262 NSIntersectionRect(PPGeometry_PixelBoundsCoveredByRect(fillBounds), bitmapFrame); 263 264 if (NSIsEmptyRect(fillBounds)) 265 { 266 goto ERROR; 267 } 268 269 destinationData = [self bitmapData]; 270 maskData = [maskBitmap bitmapData]; 271 272 if (!destinationData || !maskData) 273 { 274 goto ERROR; 275 } 276 277 rowOffset = bitmapFrame.size.height - fillBounds.size.height - fillBounds.origin.y; 278 279 destinationBytesPerRow = [self bytesPerRow]; 280 destinationDataOffset = 281 rowOffset * destinationBytesPerRow + fillBounds.origin.x * sizeof(PPImageBitmapPixel); 282 destinationRow = &destinationData[destinationDataOffset]; 283 284 maskBytesPerRow = [maskBitmap bytesPerRow]; 285 maskDataOffset = 286 rowOffset * maskBytesPerRow + fillBounds.origin.x * sizeof(PPMaskBitmapPixel); 287 maskRow = &maskData[maskDataOffset]; 288 289 pixelsPerRow = fillBounds.size.width; 290 rowCounter = fillBounds.size.height; 291 292 while (rowCounter--) 293 { 294 destinationPixel = (PPImageBitmapPixel *) destinationRow; 295 maskPixel = (PPMaskBitmapPixel *) maskRow; 296 297 pixelCounter = pixelsPerRow; 298 299 while (pixelCounter--) 300 { 301 if (*maskPixel++) 302 { 303 *destinationPixel = fillPixelValue; 304 } 305 306 destinationPixel++; 307 } 308 309 destinationRow += destinationBytesPerRow; 310 maskRow += maskBytesPerRow; 311 } 312 313 return; 314 315ERROR: 316 return; 317} 318 319- (void) ppMaskedEraseUsingMask: (NSBitmapImageRep *) maskBitmap 320{ 321 [self ppMaskedFillUsingMask: maskBitmap 322 inBounds: [self ppFrameInPixels] 323 fillPixelValue: 0]; 324} 325 326- (void) ppMaskedEraseUsingMask: (NSBitmapImageRep *) maskBitmap 327 inBounds: (NSRect) eraseBounds 328{ 329 [self ppMaskedFillUsingMask: maskBitmap 330 inBounds: eraseBounds 331 fillPixelValue: 0]; 332} 333 334- (void) ppMaskedCopyFromImageBitmap: (NSBitmapImageRep *) sourceBitmap 335 usingMask: (NSBitmapImageRep *) maskBitmap 336{ 337 return [self ppMaskedCopyFromImageBitmap: sourceBitmap 338 usingMask: maskBitmap 339 inBounds: [self ppFrameInPixels]]; 340} 341 342- (void) ppMaskedCopyFromImageBitmap: (NSBitmapImageRep *) sourceBitmap 343 usingMask: (NSBitmapImageRep *) maskBitmap 344 inBounds: (NSRect) copyBounds 345{ 346 NSRect bitmapFrame; 347 unsigned char *destinationData, *sourceData, *maskData, *destinationRow, *sourceRow, 348 *maskRow; 349 int destinationBytesPerRow, sourceBytesPerRow, maskBytesPerRow, rowOffset, 350 destinationDataOffset, sourceDataOffset, maskDataOffset, 351 pixelsPerRow, rowCounter, pixelCounter; 352 PPImageBitmapPixel *destinationPixel, *sourcePixel; 353 PPMaskBitmapPixel *maskPixel; 354 355 if (![self ppIsImageBitmap] 356 || ![sourceBitmap ppIsImageBitmapAndSameSizeAsMaskBitmap: maskBitmap]) 357 { 358 goto ERROR; 359 } 360 361 bitmapFrame = [self ppFrameInPixels]; 362 363 if (!NSEqualSizes(bitmapFrame.size, [sourceBitmap ppSizeInPixels])) 364 { 365 goto ERROR; 366 } 367 368 copyBounds = 369 NSIntersectionRect(PPGeometry_PixelBoundsCoveredByRect(copyBounds), bitmapFrame); 370 371 if (NSIsEmptyRect(copyBounds)) 372 { 373 goto ERROR; 374 } 375 376 destinationData = [self bitmapData]; 377 sourceData = [sourceBitmap bitmapData]; 378 maskData = [maskBitmap bitmapData]; 379 380 if (!destinationData || !sourceData || !maskData) 381 { 382 goto ERROR; 383 } 384 385 destinationBytesPerRow = [self bytesPerRow]; 386 sourceBytesPerRow = [sourceBitmap bytesPerRow]; 387 maskBytesPerRow = [maskBitmap bytesPerRow]; 388 389 rowOffset = bitmapFrame.size.height - copyBounds.size.height - copyBounds.origin.y; 390 391 destinationDataOffset = 392 rowOffset * destinationBytesPerRow + copyBounds.origin.x * sizeof(PPImageBitmapPixel); 393 394 sourceDataOffset = 395 rowOffset * sourceBytesPerRow + copyBounds.origin.x * sizeof(PPImageBitmapPixel); 396 397 maskDataOffset = 398 rowOffset * maskBytesPerRow + copyBounds.origin.x * sizeof(PPMaskBitmapPixel); 399 400 destinationRow = &destinationData[destinationDataOffset]; 401 sourceRow = &sourceData[sourceDataOffset]; 402 maskRow = &maskData[maskDataOffset]; 403 404 pixelsPerRow = copyBounds.size.width; 405 rowCounter = copyBounds.size.height; 406 407 while (rowCounter--) 408 { 409 destinationPixel = (PPImageBitmapPixel *) destinationRow; 410 sourcePixel = (PPImageBitmapPixel *) sourceRow; 411 maskPixel = (PPMaskBitmapPixel *) maskRow; 412 413 pixelCounter = pixelsPerRow; 414 415 while (pixelCounter--) 416 { 417 if (*maskPixel++) 418 { 419 *destinationPixel = *sourcePixel; 420 } 421 422 destinationPixel++; 423 sourcePixel++; 424 } 425 426 destinationRow += destinationBytesPerRow; 427 sourceRow += sourceBytesPerRow; 428 maskRow += maskBytesPerRow; 429 } 430 431 return; 432 433ERROR: 434 return; 435} 436 437- (void) ppMaskedCopyFromImageBitmap:(NSBitmapImageRep *) sourceBitmap 438 usingMask: (NSBitmapImageRep *) maskBitmap 439 toPoint: (NSPoint) targetPoint 440{ 441 NSRect destinationFrame, sourceFrame, destinationCopyBounds, sourceCopyBounds; 442 unsigned char *destinationData, *sourceData, *maskData, *destinationRow, *sourceRow, 443 *maskRow; 444 int destinationBytesPerRow, sourceBytesPerRow, maskBytesPerRow, rowOffset, 445 destinationDataOffset, sourceDataOffset, maskDataOffset, 446 pixelsPerRow, rowCounter, pixelCounter; 447 PPImageBitmapPixel *destinationPixel, *sourcePixel; 448 PPMaskBitmapPixel *maskPixel; 449 450 if (![self ppIsImageBitmap] 451 || ![sourceBitmap ppIsImageBitmapAndSameSizeAsMaskBitmap: maskBitmap]) 452 { 453 goto ERROR; 454 } 455 456 targetPoint = PPGeometry_PointClippedToIntegerValues(targetPoint); 457 458 destinationFrame = [self ppFrameInPixels]; 459 sourceFrame = [sourceBitmap ppFrameInPixels]; 460 461 destinationCopyBounds = 462 NSIntersectionRect(NSOffsetRect(sourceFrame, targetPoint.x, targetPoint.y), 463 destinationFrame); 464 465 if (NSIsEmptyRect(destinationCopyBounds)) 466 { 467 goto ERROR; 468 } 469 470 sourceCopyBounds = NSOffsetRect(destinationCopyBounds, -targetPoint.x, -targetPoint.y); 471 472 destinationData = [self bitmapData]; 473 sourceData = [sourceBitmap bitmapData]; 474 maskData = [maskBitmap bitmapData]; 475 476 if (!destinationData || !sourceData || !maskData) 477 { 478 goto ERROR; 479 } 480 481 destinationBytesPerRow = [self bytesPerRow]; 482 sourceBytesPerRow = [sourceBitmap bytesPerRow]; 483 maskBytesPerRow = [maskBitmap bytesPerRow]; 484 485 rowOffset = destinationFrame.size.height - destinationCopyBounds.size.height 486 - destinationCopyBounds.origin.y; 487 488 destinationDataOffset = rowOffset * destinationBytesPerRow 489 + destinationCopyBounds.origin.x * sizeof(PPImageBitmapPixel); 490 491 rowOffset = sourceFrame.size.height - sourceCopyBounds.size.height 492 - sourceCopyBounds.origin.y; 493 494 sourceDataOffset = rowOffset * sourceBytesPerRow 495 + sourceCopyBounds.origin.x * sizeof(PPImageBitmapPixel); 496 497 maskDataOffset = rowOffset * maskBytesPerRow 498 + sourceCopyBounds.origin.x * sizeof(PPMaskBitmapPixel); 499 500 destinationRow = &destinationData[destinationDataOffset]; 501 sourceRow = &sourceData[sourceDataOffset]; 502 maskRow = &maskData[maskDataOffset]; 503 504 pixelsPerRow = destinationCopyBounds.size.width; 505 rowCounter = destinationCopyBounds.size.height; 506 507 while (rowCounter--) 508 { 509 destinationPixel = (PPImageBitmapPixel *) destinationRow; 510 sourcePixel = (PPImageBitmapPixel *) sourceRow; 511 maskPixel = (PPMaskBitmapPixel *) maskRow; 512 513 pixelCounter = pixelsPerRow; 514 515 while (pixelCounter--) 516 { 517 if (*maskPixel++) 518 { 519 *destinationPixel = *sourcePixel; 520 } 521 522 destinationPixel++; 523 sourcePixel++; 524 } 525 526 destinationRow += destinationBytesPerRow; 527 sourceRow += sourceBytesPerRow; 528 maskRow += maskBytesPerRow; 529 } 530 531 return; 532 533ERROR: 534 return; 535} 536 537- (void) ppScaledCopyFromImageBitmap: (NSBitmapImageRep *) sourceBitmap 538 inRect: (NSRect) sourceRect 539 toPoint: (NSPoint) destinationPoint 540 scalingFactor: (unsigned) scalingFactor 541{ 542 NSRect destinationRect, sourceBitmapFrame, destinationBitmapFrame; 543 unsigned char *sourceData, *destinationData, *scaledRowData, *sourceRow, *destinationRow; 544 int sourceBytesPerRow, numSourceRowsToSkip, sourceDataOffset, destinationBytesPerRow, 545 numDestinationRowsToSkip, destinationDataOffset, scaledRowDataSize, 546 numTimesToCopyScaledRow, pixelsPerRow, rowCounter, pixelCounter, scaleCounter; 547 PPImageBitmapPixel *currentSourcePixel, *currentScaledPixel; 548 549 if (scalingFactor == 1) 550 { 551 [self ppCopyFromBitmap: sourceBitmap 552 inRect: sourceRect 553 toPoint: destinationPoint]; 554 555 return; 556 } 557 558 if (![self ppIsImageBitmap] || ![sourceBitmap ppIsImageBitmap] 559 || (scalingFactor < 1)) 560 { 561 goto ERROR; 562 } 563 564 sourceRect = PPGeometry_PixelBoundsCoveredByRect(sourceRect); 565 566 if (NSIsEmptyRect(sourceRect)) 567 { 568 goto ERROR; 569 } 570 571 destinationRect.origin = PPGeometry_PointClippedToIntegerValues(destinationPoint); 572 destinationRect.size = NSMakeSize(sourceRect.size.width * scalingFactor, 573 sourceRect.size.height * scalingFactor); 574 575 sourceBitmapFrame = [sourceBitmap ppFrameInPixels]; 576 destinationBitmapFrame = [self ppFrameInPixels]; 577 578 if (!NSContainsRect(sourceBitmapFrame, sourceRect) 579 || !NSContainsRect(destinationBitmapFrame, destinationRect)) 580 { 581 goto ERROR; 582 } 583 584 sourceData = [sourceBitmap bitmapData]; 585 destinationData = [self bitmapData]; 586 587 if (!sourceData || !destinationData) 588 { 589 goto ERROR; 590 } 591 592 sourceBytesPerRow = [sourceBitmap bytesPerRow]; 593 numSourceRowsToSkip = 594 sourceBitmapFrame.size.height - (sourceRect.origin.y + sourceRect.size.height); 595 sourceDataOffset = numSourceRowsToSkip * sourceBytesPerRow 596 + sizeof(PPImageBitmapPixel) * sourceRect.origin.x; 597 sourceRow = &sourceData[sourceDataOffset]; 598 599 destinationBytesPerRow = [self bytesPerRow]; 600 numDestinationRowsToSkip = destinationBitmapFrame.size.height 601 - (destinationRect.origin.y + destinationRect.size.height); 602 destinationDataOffset = numDestinationRowsToSkip * destinationBytesPerRow 603 + sizeof(PPImageBitmapPixel) * destinationRect.origin.x; 604 destinationRow = &destinationData[destinationDataOffset]; 605 606 scaledRowDataSize = sourceRect.size.width * sizeof(PPImageBitmapPixel) * scalingFactor; 607 numTimesToCopyScaledRow = scalingFactor - 1; 608 609 pixelsPerRow = sourceRect.size.width; 610 rowCounter = sourceRect.size.height; 611 612 while (rowCounter--) 613 { 614 currentSourcePixel = (PPImageBitmapPixel *) sourceRow; 615 currentScaledPixel = (PPImageBitmapPixel *) destinationRow; 616 617 pixelCounter = pixelsPerRow; 618 619 while (pixelCounter--) 620 { 621 scaleCounter = scalingFactor; 622 623 while (scaleCounter--) 624 { 625 *currentScaledPixel++ = *currentSourcePixel; 626 } 627 628 currentSourcePixel++; 629 } 630 631 scaledRowData = destinationRow; 632 destinationRow += destinationBytesPerRow; 633 634 scaleCounter = numTimesToCopyScaledRow; 635 636 while (scaleCounter--) 637 { 638 memcpy(destinationRow, scaledRowData, scaledRowDataSize); 639 640 destinationRow += destinationBytesPerRow; 641 } 642 643 sourceRow += sourceBytesPerRow; 644 } 645 646 return; 647 648ERROR: 649 return; 650} 651 652- (void) ppScaledCopyFromImageBitmap: (NSBitmapImageRep *) sourceBitmap 653 inRect: (NSRect) sourceRect 654 toPoint: (NSPoint) destinationPoint 655 scalingFactor: (unsigned) scalingFactor 656 gridType: (PPGridType) gridType 657 gridPixelValue: (PPImageBitmapPixel) gridPixelValue 658{ 659 NSRect destinationRect, sourceBitmapFrame, destinationBitmapFrame; 660 unsigned char *sourceData, *destinationData, *sourceRow, *destinationRow, *scaledRowData; 661 int scaledRowDataSize, sourceBytesPerRow, numSourceRowsToSkip, sourceDataOffset, 662 destinationBytesPerRow, numDestinationRowsToSkip, destinationDataOffset, 663 pixelsPerRow, rowCounter, pixelCounter, scaledPixelCounter, scaledRowCounter; 664 PPImageBitmapPixel *currentSourcePixel, *currentScaledPixel; 665 666 if (scalingFactor < kMinScalingFactorToDrawGrid) 667 { 668 if (scalingFactor == 1) 669 { 670 [self ppCopyFromBitmap: sourceBitmap 671 inRect: sourceRect 672 toPoint: destinationPoint]; 673 674 return; 675 } 676 else 677 { 678 [self ppScaledCopyFromImageBitmap: sourceBitmap 679 inRect: sourceRect 680 toPoint: destinationPoint 681 scalingFactor: scalingFactor]; 682 683 return; 684 } 685 } 686 687 if (![self ppIsImageBitmap] || ![sourceBitmap ppIsImageBitmap]) 688 { 689 goto ERROR; 690 } 691 692 if (scalingFactor <= kMaxScalingFactorToForceDotsGridType) 693 { 694 if (gridType != kPPGridType_Lines) 695 { 696 gridType = kPPGridType_Dots; 697 } 698 } 699 700 sourceRect = PPGeometry_PixelBoundsCoveredByRect(sourceRect); 701 702 if (NSIsEmptyRect(sourceRect)) 703 { 704 goto ERROR; 705 } 706 707 destinationRect.origin = PPGeometry_PointClippedToIntegerValues(destinationPoint); 708 destinationRect.size = NSMakeSize(sourceRect.size.width * scalingFactor, 709 sourceRect.size.height * scalingFactor); 710 711 sourceBitmapFrame = [sourceBitmap ppFrameInPixels]; 712 destinationBitmapFrame = [self ppFrameInPixels]; 713 714 if (!NSContainsRect(sourceBitmapFrame, sourceRect) 715 || !NSContainsRect(destinationBitmapFrame, destinationRect)) 716 { 717 goto ERROR; 718 } 719 720 sourceData = [sourceBitmap bitmapData]; 721 destinationData = [self bitmapData]; 722 723 if (!sourceData || !destinationData) 724 { 725 goto ERROR; 726 } 727 728 sourceBytesPerRow = [sourceBitmap bytesPerRow]; 729 numSourceRowsToSkip = 730 sourceBitmapFrame.size.height - (sourceRect.origin.y + sourceRect.size.height); 731 sourceDataOffset = numSourceRowsToSkip * sourceBytesPerRow 732 + sizeof(PPImageBitmapPixel) * sourceRect.origin.x; 733 sourceRow = &sourceData[sourceDataOffset]; 734 735 destinationBytesPerRow = [self bytesPerRow]; 736 numDestinationRowsToSkip = destinationBitmapFrame.size.height 737 - (destinationRect.origin.y + destinationRect.size.height); 738 destinationDataOffset = numDestinationRowsToSkip * destinationBytesPerRow 739 + sizeof(PPImageBitmapPixel) * destinationRect.origin.x; 740 destinationRow = &destinationData[destinationDataOffset]; 741 742 pixelsPerRow = sourceRect.size.width; 743 744 scaledRowDataSize = pixelsPerRow * scalingFactor * sizeof(PPImageBitmapPixel); 745 746 switch (gridType) 747 { 748 case kPPGridType_Lines: // GRIDTYPE: Lines 749 { 750 unsigned char *scaledHorizontalGridLineData; 751 752 // set up horizontal grid line 753 754 scaledHorizontalGridLineData = destinationRow; 755 756 currentScaledPixel = (PPImageBitmapPixel *) scaledHorizontalGridLineData; 757 scaledPixelCounter = pixelsPerRow * scalingFactor; 758 759 while (scaledPixelCounter--) 760 { 761 *currentScaledPixel++ = gridPixelValue; 762 } 763 764 // row loop 765 766 rowCounter = sourceRect.size.height; 767 768 while (rowCounter--) 769 { 770 // copy horizontal grid line 771 772 if (destinationRow != scaledHorizontalGridLineData) 773 { 774 memcpy(destinationRow, scaledHorizontalGridLineData, scaledRowDataSize); 775 } 776 777 destinationRow += destinationBytesPerRow; 778 779 // set up scaled row data 780 781 scaledRowData = destinationRow; 782 783 currentSourcePixel = (PPImageBitmapPixel *) sourceRow; 784 currentScaledPixel = (PPImageBitmapPixel *) scaledRowData; 785 786 pixelCounter = pixelsPerRow; 787 788 while (pixelCounter--) 789 { 790 // vertical grid line 791 *currentScaledPixel++ = gridPixelValue; 792 793 // scaled source-pixel data 794 scaledPixelCounter = scalingFactor - 1; 795 796 while (scaledPixelCounter--) 797 { 798 *currentScaledPixel++ = *currentSourcePixel; 799 } 800 801 currentSourcePixel++; 802 } 803 804 destinationRow += destinationBytesPerRow; 805 806 // copy scaled row data to remaining rows 807 808 scaledRowCounter = scalingFactor - 2; 809 810 while (scaledRowCounter--) 811 { 812 memcpy(destinationRow, scaledRowData, scaledRowDataSize); 813 destinationRow += destinationBytesPerRow; 814 } 815 816 sourceRow += sourceBytesPerRow; 817 } 818 } 819 break; 820 821 case kPPGridType_Dots: // GRIDTYPE: Dots 822 { 823 rowCounter = sourceRect.size.height; 824 825 while (rowCounter--) 826 { 827 // set up scaled row data 828 829 scaledRowData = destinationRow; 830 831 currentSourcePixel = (PPImageBitmapPixel *) sourceRow; 832 currentScaledPixel = (PPImageBitmapPixel *) scaledRowData; 833 834 pixelCounter = pixelsPerRow; 835 836 while (pixelCounter--) 837 { 838 // scaled source-pixel data (no grid pixels - dots are drawn at the end) 839 840 scaledPixelCounter = scalingFactor; 841 842 while (scaledPixelCounter--) 843 { 844 *currentScaledPixel++ = *currentSourcePixel; 845 } 846 847 currentSourcePixel++; 848 } 849 850 destinationRow += destinationBytesPerRow; 851 852 // copy scaled row data to remaining rows 853 854 scaledRowCounter = scalingFactor - 1; 855 856 while (scaledRowCounter--) 857 { 858 memcpy(destinationRow, scaledRowData, scaledRowDataSize); 859 destinationRow += destinationBytesPerRow; 860 } 861 862 // draw dots to first scaled row 863 864 currentScaledPixel = (PPImageBitmapPixel *) scaledRowData; 865 866 pixelCounter = pixelsPerRow; 867 868 while (pixelCounter--) 869 { 870 *currentScaledPixel = gridPixelValue; 871 currentScaledPixel += scalingFactor; 872 } 873 874 sourceRow += sourceBytesPerRow; 875 } 876 } 877 break; 878 879 default: // GRIDTYPE: Crosshairs or Large Dots 880 { 881 unsigned gridLegLength, numScaledPixelsBetweenGridLegs; 882 unsigned char *scaledRowWithVerticalGridLegData; 883 884 if (gridType == kPPGridType_LargeDots) 885 { 886 // Large Dots 887 gridLegLength = 1; 888 } 889 else 890 { 891 // Crosshairs 892 gridLegLength = roundf(scalingFactor * kCrosshairLegSizeToScalingFactorRatio); 893 } 894 895 numScaledPixelsBetweenGridLegs = scalingFactor - 2 * gridLegLength - 1; 896 897 // row loop 898 899 rowCounter = sourceRect.size.height; 900 901 while (rowCounter--) 902 { 903 // set up scaled row data 904 905 scaledRowData = destinationRow; 906 907 currentSourcePixel = (PPImageBitmapPixel *) sourceRow; 908 currentScaledPixel = (PPImageBitmapPixel *) scaledRowData; 909 910 pixelCounter = pixelsPerRow; 911 912 while (pixelCounter--) 913 { 914 // scaled source-pixel data (no grid pixels) 915 916 scaledPixelCounter = scalingFactor; 917 918 while (scaledPixelCounter--) 919 { 920 *currentScaledPixel++ = *currentSourcePixel; 921 } 922 923 currentSourcePixel++; 924 } 925 926 destinationRow += destinationBytesPerRow; 927 928 // set up scaled row with vertical grid-leg data (single left-edge grid-pixel) 929 930 scaledRowWithVerticalGridLegData = destinationRow; 931 memcpy(scaledRowWithVerticalGridLegData, scaledRowData, scaledRowDataSize); 932 933 currentScaledPixel = (PPImageBitmapPixel *) scaledRowWithVerticalGridLegData; 934 935 pixelCounter = pixelsPerRow; 936 937 while (pixelCounter--) 938 { 939 *currentScaledPixel = gridPixelValue; 940 currentScaledPixel += scalingFactor; 941 } 942 943 destinationRow += destinationBytesPerRow; 944 945 // copy scaled row with vertical grid-leg data to upper rows 946 947 scaledRowCounter = gridLegLength - 1; 948 949 while (scaledRowCounter--) 950 { 951 memcpy(destinationRow, scaledRowWithVerticalGridLegData, scaledRowDataSize); 952 destinationRow += destinationBytesPerRow; 953 } 954 955 // copy scaled row data between grid-leg rows 956 957 scaledRowCounter = numScaledPixelsBetweenGridLegs; 958 959 while (scaledRowCounter--) 960 { 961 memcpy(destinationRow, scaledRowData, scaledRowDataSize); 962 destinationRow += destinationBytesPerRow; 963 } 964 965 // copy scaled row with vertical grid-leg data to lower rows 966 967 scaledRowCounter = gridLegLength; 968 969 while (scaledRowCounter--) 970 { 971 memcpy(destinationRow, scaledRowWithVerticalGridLegData, scaledRowDataSize); 972 destinationRow += destinationBytesPerRow; 973 } 974 975 // draw horizontal grid-legs on first scaled row 976 977 currentScaledPixel = (PPImageBitmapPixel *) scaledRowData; 978 979 pixelCounter = pixelsPerRow; 980 981 while (pixelCounter--) 982 { 983 // center pixel at intersection of horizontal & vertical grid legs 984 *currentScaledPixel++ = gridPixelValue; 985 986 scaledPixelCounter = gridLegLength; 987 988 while (scaledPixelCounter--) 989 { 990 *currentScaledPixel++ = gridPixelValue; 991 } 992 993 currentScaledPixel += numScaledPixelsBetweenGridLegs; 994 995 scaledPixelCounter = gridLegLength; 996 997 while (scaledPixelCounter--) 998 { 999 *currentScaledPixel++ = gridPixelValue; 1000 } 1001 } 1002 1003 sourceRow += sourceBytesPerRow; 1004 } 1005 } 1006 break; 1007 } 1008 1009 return; 1010 1011ERROR: 1012 return; 1013} 1014 1015- (NSBitmapImageRep *) ppImageBitmapWithMaxDimension: (float) maxDimension 1016{ 1017 NSSize originalBitmapSize, maxSize, shrunkenBitmapSize; 1018 NSBitmapImageRep *shrunkenBitmap; 1019 NSImage *originalBitmapImage; 1020 1021 originalBitmapSize = [self ppSizeInPixels]; 1022 1023 if (!PPGeometry_SizeExceedsDimension(originalBitmapSize, maxDimension)) 1024 { 1025 return [self ppImageBitmap]; 1026 } 1027 1028 maxSize = NSMakeSize(maxDimension, maxDimension); 1029 1030 shrunkenBitmapSize = 1031 PPGeometry_ScaledBoundsForFrameOfSizeToFitFrameOfSize(originalBitmapSize, maxSize).size; 1032 1033 shrunkenBitmap = [NSBitmapImageRep ppImageBitmapOfSize: shrunkenBitmapSize]; 1034 1035 originalBitmapImage = [NSImage ppImageWithBitmap: self]; 1036 1037 if (!shrunkenBitmap || !originalBitmapImage) 1038 { 1039 goto ERROR; 1040 } 1041 1042 [shrunkenBitmap ppSetAsCurrentGraphicsContext]; 1043 1044 [[NSGraphicsContext currentContext] setImageInterpolation: NSImageInterpolationNone]; 1045 1046 [originalBitmapImage drawInRect: PPGeometry_OriginRectOfSize(shrunkenBitmapSize) 1047 fromRect: PPGeometry_OriginRectOfSize(originalBitmapSize) 1048 operation: NSCompositeCopy 1049 fraction: 1.0f]; 1050 1051 [shrunkenBitmap ppRestoreGraphicsContext]; 1052 1053 return shrunkenBitmap; 1054 1055ERROR: 1056 return nil; 1057} 1058 1059- (NSBitmapImageRep *) ppImageBitmapCompositedWithBackgroundColor: (NSColor *) backgroundColor 1060 andBackgroundImage: (NSImage *) backgroundImage 1061 backgroundImageInterpolation: 1062 (NSImageInterpolation) backgroundImageInterpolation 1063{ 1064 NSRect bitmapFrame; 1065 NSBitmapImageRep *compositedBitmap; 1066 NSImage *bitmapImage; 1067 1068 if (!backgroundColor && !backgroundImage) 1069 { 1070 goto ERROR; 1071 } 1072 1073 bitmapFrame = [self ppFrameInPixels]; 1074 compositedBitmap = [NSBitmapImageRep ppImageBitmapOfSize: bitmapFrame.size]; 1075 1076 bitmapImage = [NSImage ppImageWithBitmap: self]; 1077 1078 if (!compositedBitmap || !bitmapImage) 1079 { 1080 goto ERROR; 1081 } 1082 1083 [compositedBitmap ppSetAsCurrentGraphicsContext]; 1084 1085 if (backgroundColor) 1086 { 1087 [backgroundColor set]; 1088 NSRectFill(bitmapFrame); 1089 } 1090 1091 if (backgroundImage) 1092 { 1093 NSRect backgroundImageFrame, backgroundDestinationBounds; 1094 1095 backgroundImageFrame = PPGeometry_OriginRectOfSize([backgroundImage size]); 1096 1097 backgroundDestinationBounds = 1098 PPGeometry_ScaledBoundsForFrameOfSizeToFitFrameOfSize(backgroundImageFrame.size, 1099 bitmapFrame.size); 1100 1101 [[NSGraphicsContext currentContext] 1102 setImageInterpolation: backgroundImageInterpolation]; 1103 1104 [backgroundImage drawInRect: backgroundDestinationBounds 1105 fromRect: backgroundImageFrame 1106 operation: NSCompositeSourceOver 1107 fraction: 1.0f]; 1108 } 1109 1110 [[NSGraphicsContext currentContext] setImageInterpolation: NSImageInterpolationNone]; 1111 1112 [bitmapImage drawInRect: bitmapFrame 1113 fromRect: bitmapFrame 1114 operation: NSCompositeSourceOver 1115 fraction: 1.0f]; 1116 1117 [compositedBitmap ppRestoreGraphicsContext]; 1118 1119 return compositedBitmap; 1120 1121ERROR: 1122 return self; 1123} 1124 1125- (NSBitmapImageRep *) ppImageBitmapDissolvedToOpacity: (float) opacity 1126{ 1127 NSBitmapImageRep *dissolvedBitmap; 1128 1129 if (![self ppIsImageBitmap]) 1130 { 1131 goto ERROR; 1132 } 1133 1134 if (opacity >= 1.0f) 1135 { 1136 dissolvedBitmap = [[self copy] autorelease]; 1137 1138 if (!dissolvedBitmap) 1139 goto ERROR; 1140 } 1141 else 1142 { 1143 NSRect bitmapFrame = [self ppFrameInPixels]; 1144 1145 dissolvedBitmap = [NSBitmapImageRep ppImageBitmapOfSize: bitmapFrame.size]; 1146 1147 if (!dissolvedBitmap) 1148 goto ERROR; 1149 1150 if (opacity > 0.0f) 1151 { 1152 NSImage *image = [NSImage ppImageWithBitmap: self]; 1153 1154 if (!image) 1155 goto ERROR; 1156 1157 [dissolvedBitmap ppSetAsCurrentGraphicsContext]; 1158 1159 [image drawInRect: bitmapFrame 1160 fromRect: bitmapFrame 1161 operation: NSCompositeCopy 1162 fraction: opacity]; 1163 1164 [dissolvedBitmap ppRestoreGraphicsContext]; 1165 } 1166 } 1167 1168 return dissolvedBitmap; 1169 1170ERROR: 1171 return nil; 1172} 1173 1174- (NSBitmapImageRep *) ppImageBitmapMaskedWithMask: (NSBitmapImageRep *) maskBitmap 1175{ 1176 NSBitmapImageRep *maskedBitmap; 1177 1178 if (![self ppIsImageBitmapAndSameSizeAsMaskBitmap: maskBitmap]) 1179 { 1180 goto ERROR; 1181 } 1182 1183 maskedBitmap = [NSBitmapImageRep ppImageBitmapOfSize: [self ppSizeInPixels]]; 1184 1185 if (!maskedBitmap) 1186 goto ERROR; 1187 1188 [maskedBitmap ppMaskedCopyFromImageBitmap: self 1189 usingMask: maskBitmap]; 1190 1191 return maskedBitmap; 1192 1193ERROR: 1194 return nil; 1195} 1196 1197- (NSBitmapImageRep *) ppImageBitmapScaledByFactor: (unsigned) scalingFactor 1198 shouldDrawGrid: (bool) shouldDrawGrid 1199 gridType: (PPGridType) gridType 1200 gridColor: (NSColor *) gridColor 1201{ 1202 NSRect bitmapFrame; 1203 NSSize scaledBitmapSize; 1204 NSBitmapImageRep *scaledBitmap; 1205 1206 if (![self ppIsImageBitmap] || !scalingFactor) 1207 { 1208 goto ERROR; 1209 } 1210 1211 bitmapFrame = [self ppFrameInPixels]; 1212 1213 scaledBitmapSize = NSMakeSize(bitmapFrame.size.width * scalingFactor, 1214 bitmapFrame.size.height * scalingFactor); 1215 1216 scaledBitmap = [NSBitmapImageRep ppImageBitmapOfSize: scaledBitmapSize]; 1217 1218 if (!scaledBitmap) 1219 goto ERROR; 1220 1221 if (shouldDrawGrid) 1222 { 1223 [scaledBitmap ppScaledCopyFromImageBitmap: self 1224 inRect: bitmapFrame 1225 toPoint: NSZeroPoint 1226 scalingFactor: scalingFactor 1227 gridType: gridType 1228 gridPixelValue: [gridColor ppImageBitmapPixelValue]]; 1229 } 1230 else 1231 { 1232 [scaledBitmap ppScaledCopyFromImageBitmap: self 1233 inRect: bitmapFrame 1234 toPoint: NSZeroPoint 1235 scalingFactor: scalingFactor]; 1236 } 1237 1238 return scaledBitmap; 1239 1240ERROR: 1241 return nil; 1242} 1243 1244- (NSBitmapImageRep *) ppMaskBitmapForVisiblePixelsInImageBitmap 1245{ 1246 NSSize bitmapSize; 1247 NSBitmapImageRep *maskBitmap; 1248 1249 if (![self ppIsImageBitmap]) 1250 { 1251 goto ERROR; 1252 } 1253 1254 bitmapSize = [self ppSizeInPixels]; 1255 1256 if (PPGeometry_IsZeroSize(bitmapSize)) 1257 { 1258 goto ERROR; 1259 } 1260 1261 maskBitmap = [NSBitmapImageRep ppMaskBitmapOfSize: bitmapSize]; 1262 1263 if (!maskBitmap) 1264 goto ERROR; 1265 1266 [maskBitmap ppMaskVisiblePixelsInImageBitmap: self selectionMask: nil]; 1267 1268 return maskBitmap; 1269 1270ERROR: 1271 return nil; 1272} 1273 1274- (void) ppDrawImageGuidelinesInBounds: (NSRect) drawBounds 1275 topLeftPhase: (NSPoint) topLeftPhase 1276 unscaledSpacingSize: (NSSize) unscaledSpacingSize 1277 scalingFactor: (unsigned) scalingFactor 1278 guidelinePixelValue: (PPImageBitmapPixel) guidelinePixelValue 1279{ 1280 NSRect bitmapFrame; 1281 int colOffsetToNextVerticalLine, rowOffsetToNextHorizontalLine, drawBoundsLeftCol, 1282 drawBoundsRightCol, drawBoundsTopRow, drawBoundsBottomRow, colOfFirstVerticalLine, 1283 numVerticalLines = 0, rowOfFirstHorizontalLine, numHorizontalLines = 0, bytesPerRow, 1284 startRow, rowIncrement, rowDataOffsetToFirstVerticalLine, dataOffset, rowDataIncrement, 1285 horizontalLineDataSize, rowOfNextHorizontalLine, row, verticalLineCounter; 1286 NSPoint offsetToNextGuidelineVertex; 1287 unsigned char *bitmapData, *previousHorizontalLineData = NULL, *rowData; 1288 PPImageBitmapPixel *verticalLinePixel; 1289 1290 if (![self ppIsImageBitmap]) 1291 { 1292 goto ERROR; 1293 } 1294 1295 bitmapFrame = [self ppFrameInPixels]; 1296 1297 drawBounds = 1298 NSIntersectionRect(PPGeometry_PixelBoundsCoveredByRect(drawBounds), bitmapFrame); 1299 1300 if (NSIsEmptyRect(drawBounds)) 1301 { 1302 goto ERROR; 1303 } 1304 1305 topLeftPhase = PPGeometry_PointClippedToIntegerValues(topLeftPhase); 1306 1307 if (scalingFactor > kMaxCanvasZoomFactor) 1308 { 1309 goto ERROR; 1310 } 1311 1312 colOffsetToNextVerticalLine = unscaledSpacingSize.width * scalingFactor; 1313 rowOffsetToNextHorizontalLine = unscaledSpacingSize.height * scalingFactor; 1314 1315 if ((colOffsetToNextVerticalLine < kMinScalingFactorToDrawGrid) 1316 || (rowOffsetToNextHorizontalLine < kMinScalingFactorToDrawGrid)) 1317 { 1318 // guidelines are too close together at current scalingFactor, so don't draw 1319 return; 1320 } 1321 1322 drawBoundsLeftCol = drawBounds.origin.x; 1323 drawBoundsRightCol = drawBoundsLeftCol + drawBounds.size.width - 1; 1324 1325 drawBoundsTopRow = 1326 bitmapFrame.size.height - (drawBounds.origin.y + drawBounds.size.height); 1327 drawBoundsBottomRow = drawBoundsTopRow + drawBounds.size.height - 1; 1328 1329 offsetToNextGuidelineVertex = 1330 PPGeometry_OffsetPointToNextNearestVertexOnGridWithSpacingSize( 1331 NSMakePoint(drawBoundsLeftCol + topLeftPhase.x, 1332 drawBoundsTopRow + topLeftPhase.y), 1333 NSMakeSize(colOffsetToNextVerticalLine, 1334 rowOffsetToNextHorizontalLine)); 1335 1336 if ((offsetToNextGuidelineVertex.x < 0) || (offsetToNextGuidelineVertex.y < 0)) 1337 { 1338 goto ERROR; 1339 } 1340 1341 colOfFirstVerticalLine = drawBoundsLeftCol + offsetToNextGuidelineVertex.x; 1342 1343 if (colOfFirstVerticalLine <= drawBoundsRightCol) 1344 { 1345 numVerticalLines = 1 + (drawBoundsRightCol - colOfFirstVerticalLine) 1346 / colOffsetToNextVerticalLine; 1347 } 1348 1349 rowOfFirstHorizontalLine = drawBoundsTopRow + offsetToNextGuidelineVertex.y; 1350 1351 if (rowOfFirstHorizontalLine <= drawBoundsBottomRow) 1352 { 1353 numHorizontalLines = 1 + (drawBoundsBottomRow - rowOfFirstHorizontalLine) 1354 / rowOffsetToNextHorizontalLine; 1355 } 1356 1357 if (!numVerticalLines && !numHorizontalLines) 1358 { 1359 // no guidelines within drawBounds - nothing to draw 1360 return; 1361 } 1362 1363 bitmapData = [self bitmapData]; 1364 bytesPerRow = [self bytesPerRow]; 1365 1366 if (!bitmapData || (bytesPerRow <= 0)) 1367 { 1368 goto ERROR; 1369 } 1370 1371 if (numVerticalLines > 0) 1372 { 1373 startRow = drawBoundsTopRow; 1374 rowIncrement = 1; 1375 1376 rowDataOffsetToFirstVerticalLine = 1377 (colOfFirstVerticalLine - drawBoundsLeftCol) * sizeof(PPImageBitmapPixel); 1378 } 1379 else 1380 { 1381 // no vertical guidelines within drawBounds - only need to draw horizontal guidelines 1382 startRow = rowOfFirstHorizontalLine; 1383 rowIncrement = rowOffsetToNextHorizontalLine; 1384 1385 rowDataOffsetToFirstVerticalLine = 0; // avoids analyzer warning (undefined subscript) 1386 } 1387 1388 dataOffset = startRow * bytesPerRow + drawBoundsLeftCol * sizeof(PPImageBitmapPixel); 1389 1390 rowData = &bitmapData[dataOffset]; 1391 1392 rowDataIncrement = rowIncrement * bytesPerRow; 1393 1394 horizontalLineDataSize = drawBounds.size.width * sizeof(PPImageBitmapPixel); 1395 1396 rowOfNextHorizontalLine = rowOfFirstHorizontalLine; 1397 1398 row = startRow; 1399 1400 while (row <= drawBoundsBottomRow) 1401 { 1402 if (row == rowOfNextHorizontalLine) 1403 { 1404 // row with horizontal line 1405 1406 if (!previousHorizontalLineData) 1407 { 1408 PPImageBitmapPixel *currentPixel = (PPImageBitmapPixel *) rowData; 1409 int pixelCounter = drawBounds.size.width; 1410 1411 while (pixelCounter--) 1412 { 1413 *currentPixel++ = guidelinePixelValue; 1414 } 1415 } 1416 else 1417 { 1418 memcpy(rowData, previousHorizontalLineData, horizontalLineDataSize); 1419 } 1420 1421 previousHorizontalLineData = rowData; 1422 1423 rowOfNextHorizontalLine += rowOffsetToNextHorizontalLine; 1424 } 1425 else 1426 { 1427 // row with vertical lines 1428 1429 verticalLinePixel = 1430 (PPImageBitmapPixel *) &rowData[rowDataOffsetToFirstVerticalLine]; 1431 1432 verticalLineCounter = numVerticalLines; 1433 1434 while (verticalLineCounter--) 1435 { 1436 *verticalLinePixel = guidelinePixelValue; 1437 1438 verticalLinePixel += colOffsetToNextVerticalLine; 1439 } 1440 } 1441 1442 rowData += rowDataIncrement; 1443 row += rowIncrement; 1444 } 1445 1446 return; 1447 1448ERROR: 1449 return; 1450} 1451 1452@end 1453