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

Reply via email to