Revision: 15208 http://sourceforge.net/p/skim-app/code/15208 Author: hofman Date: 2025-05-14 15:30:52 +0000 (Wed, 14 May 2025) Log Message: ----------- draw page for tooltip image directly in image bbitmap instead of first drawing a full thumbnail, avoids drawing parts of the image that won't be visible, and potentially can be expensive.
Modified Paths: -------------- trunk/SKImageToolTipContext.m Modified: trunk/SKImageToolTipContext.m =================================================================== --- trunk/SKImageToolTipContext.m 2025-05-13 21:44:48 UTC (rev 15207) +++ trunk/SKImageToolTipContext.m 2025-05-14 15:30:52 UTC (rev 15208) @@ -48,6 +48,8 @@ #import "NSColor_SKExtensions.h" #import "NSAttributedString_SKExtensions.h" #import "PDFDestination_SKExtensions.h" +#import "NSBitmapImageRep_SKExtensions.h" +#import "SKStringConstants.h" #define TEXT_MARGIN_X 2.0 #define TEXT_MARGIN_Y 2.0 @@ -112,31 +114,21 @@ if (labelColor == nil) labelColor = [NSColor colorWithGenericGamma22White:0.55 alpha:0.8]; - if (selections) { - selections = [[NSArray alloc] initWithArray:selections copyItems:YES]; - [selections setValue:[NSColor findHighlightColor] forKey:@"color"]; - } + PDFPage *page = [self page]; - BOOL isScaled = fabs(scale - 1.0) > 0.01; - PDFPage *page = [self page]; + if (page == nil) + return nil; + + NSRect sourceRect = NSZeroRect; NSPoint point = [[self effectiveDestinationForView:nil] point]; NSRect bounds = [page boundsForBox:kPDFDisplayBoxCropBox]; - CGFloat size = isScaled ? ceil(scale * fmax(NSWidth(bounds), NSHeight(bounds))) : 0.0; - NSImage *pageImage = [page thumbnailWithSize:size scale:backingScale forBox:kPDFDisplayBoxCropBox hasShadow:NO highlights:selections]; - NSRect pageImageRect = {NSZeroPoint, [pageImage size]}; - NSRect sourceRect = NSZeroRect; - PDFSelection *pageSelection = [page selectionForRect:bounds]; - NSRect selBounds; NSAffineTransform *transform = [page affineTransformForBox:kPDFDisplayBoxCropBox]; - if (isScaled) { + if (fabs(scale - 1.0) > 0.0) { NSAffineTransform *scaleTransform = [NSAffineTransform transform]; - [scaleTransform scaleBy:size / fmax(NSWidth(bounds), NSHeight(bounds))]; + [scaleTransform scaleBy:scale]; [transform appendTransform:scaleTransform]; } - if (page == nil) - return nil; - sourceRect.size.width = [[NSUserDefaults standardUserDefaults] doubleForKey:SKToolTipWidthKey]; sourceRect.size.height = [[NSUserDefaults standardUserDefaults] doubleForKey:SKToolTipHeightKey]; sourceRect.origin = [transform transformPoint:point]; @@ -143,7 +135,9 @@ sourceRect.origin.x -= OFFSET_X; sourceRect.origin.y -= NSHeight(sourceRect) - OFFSET_Y; - if ([pageSelection hasCharacters]) + NSRect selBounds; + PDFSelection *pageSelection = [page selectionForRect:bounds]; + if ([pageSelection hasCharacters]) selBounds = NSIntersectionRect(NSInsetRect([pageSelection boundsForPage:page], -2.0, -2.0), bounds); else selBounds = [page boundingBox]; @@ -151,13 +145,25 @@ sourceRect.origin.x = fmax(floor(NSMinX(selBounds)), fmin(floor(NSMaxX(selBounds) - NSWidth(sourceRect)), NSMinX(sourceRect))); sourceRect.origin.y = fmin(ceil(NSMaxY(selBounds)), fmax(ceil(NSMinY(selBounds) + NSHeight(sourceRect)), NSMaxY(sourceRect))) - NSHeight(sourceRect); - sourceRect = SKConstrainRect(sourceRect, pageImageRect); + NSRect pageRect = NSZeroRect; + if (([page rotation] % 180)) { + pageRect.size.width = round(scale * NSHeight(bounds)); + pageRect.size.height = round(scale * NSWidth(bounds)); + } else { + pageRect.size.width = round(scale * NSWidth(bounds)); + pageRect.size.height = round(scale * NSHeight(bounds)); + } + sourceRect = SKConstrainRect(sourceRect, pageRect); + if (selections) { + selections = [[NSArray alloc] initWithArray:selections copyItems:YES]; + [selections setValue:[NSColor findHighlightColor] forKey:@"color"]; + } + if (label == nil) label = [NSString stringWithFormat:NSLocalizedString(@"Page %@", @"Tool tip label format"), [page displayLabel]]; NSAttributedString *labelString = [[NSAttributedString alloc] initWithString:label attributes:labelAttributes]; NSRect labelRect = [labelString boundingRectWithSize:NSZeroSize options:NSStringDrawingUsesLineFragmentOrigin]; - labelRect.size.width = floor(NSWidth(labelRect)); labelRect.size.height = 2.0 * floor(0.5 * NSHeight(labelRect)); // make sure the cap radius is integral labelRect.origin.x = NSWidth(sourceRect) - NSWidth(labelRect) - 0.5 * NSHeight(labelRect) - TEXT_MARGIN_X; @@ -164,28 +170,44 @@ labelRect.origin.y = TEXT_MARGIN_Y; labelRect = NSIntegralRect(labelRect); - NSImage *image = [NSImage imageWithSize:sourceRect.size flipped:NO drawingHandler:^(NSRect dstRect){ + CGFloat radius = 0.5 * NSHeight(labelRect); + NSBezierPath *path = [NSBezierPath bezierPath]; + [path moveToPoint:SKTopLeftPoint(labelRect)]; + [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(labelRect), NSMidY(labelRect)) radius:radius startAngle:90.0 endAngle:270.0]; + [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(labelRect), NSMidY(labelRect)) radius:radius startAngle:-90.0 endAngle:90.0]; + [path closePath]; + + transform = [NSAffineTransform transform]; + [transform translateXBy:-NSMinX(sourceRect) yBy:-NSMinY(sourceRect)]; + [transform scaleBy:scale]; + + NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithSize:sourceRect.size scale:backingScale drawingHandler:^(NSRect dstRect){ - [pageImage drawInRect:dstRect fromRect:sourceRect operation:NSCompositingOperationCopy fraction:1.0]; + [NSGraphicsContext saveGraphicsState]; + [[NSColor whiteColor] setFill]; + NSRectFill(dstRect); + [NSGraphicsContext restoreGraphicsState]; - CGFloat radius = 0.5 * NSHeight(labelRect); - NSBezierPath *path = [NSBezierPath bezierPath]; + [NSGraphicsContext saveGraphicsState]; + [[NSGraphicsContext currentContext] setImageInterpolation:[[NSUserDefaults standardUserDefaults] integerForKey:SKInterpolationQualityKey] + 1]; + [transform concat]; + [page drawWithBox:kPDFDisplayBoxCropBox toContext:[[NSGraphicsContext currentContext] CGContext]]; + for (PDFSelection *selection in selections) + [selection drawForPage:page withBox:kPDFDisplayBoxCropBox active:YES]; + [NSGraphicsContext restoreGraphicsState]; - [path moveToPoint:SKTopLeftPoint(labelRect)]; - [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(labelRect), NSMidY(labelRect)) radius:radius startAngle:90.0 endAngle:270.0]; - [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(labelRect), NSMidY(labelRect)) radius:radius startAngle:-90.0 endAngle:90.0]; - [path closePath]; - + [NSGraphicsContext saveGraphicsState]; [labelColor setFill]; [path fill]; - [labelString drawWithRect:labelRect options:NSStringDrawingUsesLineFragmentOrigin]; - - return YES; + [NSGraphicsContext restoreGraphicsState]; }]; - [[[image representations] firstObject] setOpaque:YES]; + [imageRep setOpaque:YES]; + NSImage *image = [[NSImage alloc] initWithSize:sourceRect.size]; + [image addRepresentation:imageRep]; + return image; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. _______________________________________________ Skim-app-commit mailing list Skim-app-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/skim-app-commit