Revision: 16538
          http://sourceforge.net/p/skim-app/code/16538
Author:   hofman
Date:     2026-09-26 21:41:10 +0000 (Sat, 26 Sep 2026)
Log Message:
-----------
implement custom support methods in PDFAnnotation class rather than in legacy 
subclasses

Modified Paths:
--------------
    trunk/PDFAnnotation_SKExtensions.h
    trunk/PDFAnnotation_SKExtensions.m
    trunk/SKMainDocument.m
    trunk/SKNPDFAnnotationNote_SKExtensions.m
    trunk/SKPDFView.m
    trunk/Skim.xcodeproj/project.pbxproj

Modified: trunk/PDFAnnotation_SKExtensions.h
===================================================================
--- trunk/PDFAnnotation_SKExtensions.h  2026-09-24 08:24:03 UTC (rev 16537)
+++ trunk/PDFAnnotation_SKExtensions.h  2026-09-26 21:41:10 UTC (rev 16538)
@@ -43,11 +43,21 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+extern NSString * const SKPDFAnnotationBezierPathsKey;
+
 extern NSString * const SKPDFAnnotationScriptingColorKey;
 extern NSString * const SKPDFAnnotationScriptingModificationDateKey;
 extern NSString * const SKPDFAnnotationScriptingUserNameKey;
 extern NSString * const SKPDFAnnotationScriptingTextContentsKey;
 extern NSString * const SKPDFAnnotationScriptingInteriorColorKey;
+extern NSString * const SKPDFAnnotationScriptingFontColorKey;
+extern NSString * const SKPDFAnnotationScriptingAlignmentKey;
+extern NSString * const SKPDFAnnotationStartPointAsQDPointKey;
+extern NSString * const SKPDFAnnotationEndPointAsQDPointKey;
+extern NSString * const SKPDFAnnotationScriptingStartLineStyleKey;
+extern NSString * const SKPDFAnnotationScriptingEndLineStyleKey;
+extern NSString * const SKPDFAnnotationScriptingPointListsKey;
+extern NSString * const SKPDFAnnotationSelectionSpecifierKey;
 
 extern NSString * const SKPDFAnnotationBoundsOrderKey;
 
@@ -127,7 +137,6 @@
 
 @property (nonatomic, readonly) NSSet *keysForValuesToObserveForUndo;
 
-@property (class, nonatomic, readonly) NSSet *customScriptingKeys;
 @property (nonatomic, readonly) NSScriptObjectSpecifier *objectSpecifier;
 @property (nonatomic, nullable, copy) NSColor *scriptingColor;
 @property (nonatomic, nullable, readonly) PDFPage *scriptingPage;
@@ -138,15 +147,15 @@
 @property (nonatomic, nullable, copy) id textContents;
 @property (nonatomic, nullable, readonly) id richText;
 @property (nonatomic, copy) NSData *boundsAsQDRect;
-@property (nonatomic, readonly) NSInteger scriptingAlignment;
-@property (nonatomic, nullable, readonly) NSString *fontName;
-@property (nonatomic, readonly) CGFloat fontSize;
-@property (nonatomic, nullable, readonly) NSColor *scriptingFontColor;
-@property (nonatomic, nullable, readonly) NSColor *scriptingInteriorColor;
-@property (nonatomic, nullable, readonly) NSData *startPointAsQDPoint;
-@property (nonatomic, nullable, readonly) NSData *endPointAsQDPoint;
-@property (nonatomic, readonly) PDFLineStyle scriptingStartLineStyle;
-@property (nonatomic, readonly) PDFLineStyle scriptingEndLineStyle;
+@property (nonatomic) NSInteger scriptingAlignment;
+@property (nonatomic, nullable) NSString *fontName;
+@property (nonatomic) CGFloat fontSize;
+@property (nonatomic, nullable) NSColor *scriptingFontColor;
+@property (nonatomic, nullable) NSColor *scriptingInteriorColor;
+@property (nonatomic, nullable) NSData *startPointAsQDPoint;
+@property (nonatomic, nullable) NSData *endPointAsQDPoint;
+@property (nonatomic) PDFLineStyle scriptingStartLineStyle;
+@property (nonatomic) PDFLineStyle scriptingEndLineStyle;
 @property (nonatomic, nullable, readonly) id selectionSpecifier;
 @property (nonatomic, nullable, readonly) NSArray<NSArray<NSData *> *> 
*scriptingPointLists;
 

Modified: trunk/PDFAnnotation_SKExtensions.m
===================================================================
--- trunk/PDFAnnotation_SKExtensions.m  2026-09-24 08:24:03 UTC (rev 16537)
+++ trunk/PDFAnnotation_SKExtensions.m  2026-09-26 21:41:10 UTC (rev 16538)
@@ -37,13 +37,6 @@
  */
 
 #import "PDFAnnotation_SKExtensions.h"
-#import "PDFAnnotationCircle_SKExtensions.h"
-#import "PDFAnnotationSquare_SKExtensions.h"
-#import "PDFAnnotationLine_SKExtensions.h"
-#import "PDFAnnotationMarkup_SKExtensions.h"
-#import "PDFAnnotationFreeText_SKExtensions.h"
-#import "PDFAnnotationText_SKExtensions.h"
-#import "PDFAnnotationInk_SKExtensions.h"
 #import "SKNPDFAnnotationNote_SKExtensions.h"
 #import "SKStringConstants.h"
 #import "SKFDFParser.h"
@@ -62,7 +55,13 @@
 #import "SKNoteText.h"
 #import "PDFView_SKExtensions.h"
 #import "NSDate_SKExtensions.h"
+#import "NSPointerArray_SKExtensions.h"
+#import "NSShadow_SKExtensions.h"
+#import "NSCharacterSet_SKExtensions.h"
+#import "SKRuntime.h"
+#import <objc/objc-runtime.h>
 
+NSString * const SKPDFAnnotationBezierPathsKey = @"bezierPaths";
 
 NSString * const SKPDFAnnotationScriptingColorKey = @"scriptingColor";
 NSString * const SKPDFAnnotationScriptingModificationDateKey = 
@"scriptingModificationDate";
@@ -69,14 +68,138 @@
 NSString * const SKPDFAnnotationScriptingUserNameKey = @"scriptingUserName";
 NSString * const SKPDFAnnotationScriptingTextContentsKey = @"textContents";
 NSString * const SKPDFAnnotationScriptingInteriorColorKey = 
@"scriptingInteriorColor";
+NSString * const SKPDFAnnotationScriptingFontColorKey = @"scriptingFontColor";
+NSString * const SKPDFAnnotationScriptingAlignmentKey = @"scriptingAlignment";
+NSString * const SKPDFAnnotationStartPointAsQDPointKey = 
@"startPointAsQDPoint";
+NSString * const SKPDFAnnotationEndPointAsQDPointKey = @"endPointAsQDPoint";
+NSString * const SKPDFAnnotationScriptingStartLineStyleKey = 
@"scriptingStartLineStyle";
+NSString * const SKPDFAnnotationScriptingEndLineStyleKey = 
@"scriptingEndLineStyle";
+NSString * const SKPDFAnnotationScriptingPointListsKey = 
@"scriptingPointLists";
+NSString * const SKPDFAnnotationSelectionSpecifierKey = @"selectionSpecifier";
 
 NSString * const SKPDFAnnotationBoundsOrderKey = @"boundsOrder";
 
 NSPasteboardType const SKPasteboardTypeSkimNote = 
@"net.sourceforge.skim-app.pasteboard.skimnote";
 
+static char SKLineRectsKey;
+static char SKTextStringKey;
+static char SKNoteTextKey;
 
+/*
+ http://www.cocoabuilder.com/archive/message/cocoa/2007/2/16/178891
+  The docs are wrong (as is Adobe's spec).  The ordering on the rotated page 
is:
+ --------
+ | 0  1 |
+ | 2  3 |
+ --------
+ */
+static NSArray *quadPointsForLineRects(NSPointerArray *lines, NSPoint origin, 
NSInteger lineDirection) {
+    NSMutableArray *quadPoints = [[NSMutableArray alloc] init];
+    NSUInteger i, iMax = [lines count];
+    for (i = 0; i < iMax; i++) {
+        static NSInteger offset[4] = {0, 1, 3, 2};
+        NSRect r = NSOffsetRect([lines rectAtIndex:i], -origin.x, -origin.y);
+        NSInteger j = lineDirection;
+        NSPoint p[4];
+        memset(&p, 0, 4 * sizeof(NSPoint));
+        p[offset[j]] = SKBottomLeftPoint(r);
+        p[offset[++j%4]] = SKTopLeftPoint(r);
+        p[offset[++j%4]] = SKTopRightPoint(r);
+        p[offset[++j%4]] = SKBottomRightPoint(r);
+        for (j = 0; j < 4; j++)
+            [quadPoints addObject:[NSValue valueWithPoint:p[j]]];
+    }
+    return quadPoints;
+}
+
+static NSPointerArray *lineRectsForQuadPoints(NSArray *quadPoints, NSPoint 
origin) {
+    NSPointerArray *lineRects = [[NSPointerArray alloc] initForRectPointers];
+    NSUInteger j, jMax = [quadPoints count] / 4;
+    NSRange range = NSMakeRange(0, 4);
+    for (j = 0; j < jMax; j++) {
+        range.location = 4 * j;
+        NSPoint point;
+        NSUInteger i;
+        CGFloat minX = CGFLOAT_MAX, maxX = -CGFLOAT_MAX, minY = CGFLOAT_MAX, 
maxY = -CGFLOAT_MAX;
+        for (i = 0; i < 4; i++) {
+            point = [[quadPoints objectAtIndex:4 * j + i] pointValue];
+            minX = fmin(minX, point.x);
+            maxX = fmax(maxX, point.x);
+            minY = fmin(minY, point.y);
+            maxY = fmax(maxY, point.y);
+        }
+        NSRect lineRect = NSMakeRect(origin.x + minX, origin.y + minY, maxX - 
minX, maxY - minY);
+        [lineRects addPointer:&lineRect];
+    }
+    return lineRects;
+}
+
+// NSTextAlignment enum values depend on the architecture, on arm64 right=2 
and center=1
+static inline NSTextAlignment textAlignmentFromAlignment(NSInteger alignment) {
+    switch (alignment) {
+        case 0: return NSTextAlignmentLeft;
+        case 1: return NSTextAlignmentRight;
+        case 2: return NSTextAlignmentCenter;
+        default: return NSTextAlignmentLeft;
+    }
+}
+
+static inline NSInteger alignmentFromTextAlignment(NSTextAlignment alignment) {
+    switch (alignment) {
+        case NSTextAlignmentLeft: return 0;
+        case NSTextAlignmentRight: return 1;
+        case NSTextAlignmentCenter: return 2;
+        default: return 0;
+    }
+}
+
 @implementation PDFAnnotation (SKExtensions)
 
+static CGAffineTransform (*CGContextGetBaseCTM_func)(CGContextRef) = NULL;
+
+static void (*original_setColor)(id, SEL, id) = NULL;
+static void (*original_setBounds)(id, SEL, NSRect) = NULL;
+
+// PDFView raises an exception when a highlight has a sRGB black color
+static void replacement_setColor(id self, SEL _cmd, NSColor *color) {
+    if ([[(PDFAnnotation *)self type] isEqualToString:SKNHighlightString]) {
+        static NSColor *blackColor = nil;
+        if (blackColor == nil)
+            blackColor = [NSColor colorWithSRGBRed:0.0 green:0.0 blue:0.0 
alpha:1.0];
+        if ([color isEqual:blackColor])
+            color = [NSColor blackColor];
+    }
+    original_setColor(self, _cmd, color);
+}
+
+static void replacement_setBounds(id self, SEL _cmd , NSRect newBounds) {
+    if ([[(PDFAnnotation *)self type] isEqualToString:SKNLineString]) {
+        NSArray *points = [self 
valueForAnnotationKey:PDFAnnotationKeyLinePoints];
+        if ([points isKindOfClass:[NSArray class]] && [points count] == 4) {
+            NSPoint d = SKSubstractPoints(newBounds.origin, [self 
bounds].origin);
+            if (NSEqualPoints(d, NSZeroPoint))
+                points = nil;
+            else
+                points = @[@([points[0] doubleValue] + d.x), @([points[1] 
doubleValue] + d.y), @([points[2] doubleValue] + d.x), @([points[3] 
doubleValue] + d.y)];
+        } else if (points) {
+            points = nil;
+        }
+        original_setBounds(self, _cmd, newBounds);
+        if (points)
+            [self setValue:points forAnnotationKey:PDFAnnotationKeyLinePoints];
+    } else {
+        original_setBounds(self, _cmd, newBounds);
+    }
+}
+
++ (void)load {
+    CGContextGetBaseCTM_func = 
(typeof(CGContextGetBaseCTM_func))CFBundleGetFunctionPointerForName(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreGraphics")),
 CFSTR("CGContextGetBaseCTM"));
+    original_setColor = (void (*)(id, SEL, 
id))SKReplaceInstanceMethodImplementation(self, @selector(setColor:), 
(IMP)replacement_setColor);
+    if (@available(macOS 10.14, *)) {} else {
+        original_setBounds = (void (*)(id, SEL, 
NSRect))SKReplaceInstanceMethodImplementation(self, @selector(setBounds:), 
(IMP)replacement_setBounds);
+    }
+}
+
 + (NSArray *)readableTypesForPasteboard:(NSPasteboard *)pasteboard {
     return @[SKPasteboardTypeSkimNote];
 }
@@ -113,7 +236,7 @@
 static inline Class SKAnnotationClassForType(NSString *type) {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    if ([type isEqualToString:SKNNoteString] || [type 
isEqualToString:SKNTextString])
+    if ([type isEqualToString:SKNNoteString] || [type 
isEqualToString:SKNTextString] || [type isEqualToString:SKNStampString])
         return [SKNPDFAnnotationNote class];
     else if ([type isEqualToString:SKNFreeTextString])
         return [PDFAnnotationFreeText class];
@@ -121,7 +244,7 @@
         return [PDFAnnotationCircle class];
     else if ([type isEqualToString:SKNSquareString])
         return [PDFAnnotationSquare class];
-    else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNMarkUpString] || [type isEqualToString:SKNUnderlineString] 
|| [type isEqualToString:SKNStrikeOutString])
+    else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString] || [type isEqualToString:SKNMarkUpString])
         return [PDFAnnotationMarkup class];
     else if ([type isEqualToString:SKNLineString])
         return [PDFAnnotationLine class];
@@ -138,17 +261,40 @@
 
 + (PDFAnnotation *)newSkimNoteWithProperties:(NSDictionary *)dict {
     PDFAnnotation *annotation = [[SKAnnotationClassForType([dict 
objectForKey:SKNPDFAnnotationTypeKey]) alloc] initSkimNoteWithProperties:dict];
-    // this is only to make sure markup annotations generate the lineRects, 
for thread safety
-    if ([annotation isMarkup])
-        [annotation boundsOrder];
+    if ([annotation isMarkup]) {
+        // generate the lineRects now, for thread safety
+        NSPointerArray *lines = lineRectsForQuadPoints([annotation 
quadrilateralPoints], [annotation bounds].origin);
+        objc_setAssociatedObject(annotation, &SKLineRectsKey, lines, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    }
     return annotation;
 }
 
 + (PDFAnnotation *)newSkimNoteWithSelection:(PDFSelection *)selection 
forPage:(PDFPage *)page forType:(NSString *)type {
+    NSRect bounds = NSZeroRect;
+    NSPointerArray *lines = nil;
+    if ([selection safeIndexOfFirstCharacterOnPage:page] != NSNotFound) {
+        for (PDFSelection *sel in [selection connectedSelectionsOnPage:page]) {
+            NSRect lineRect = [sel boundsForPage:page];
+            if (NSIsEmptyRect(lineRect) == NO && [[sel string] 
rangeOfCharacterFromSet:[NSCharacterSet 
nonWhitespaceAndNewlineCharacterSet]].length) {
+                if (lines == nil)
+                    lines = [[NSPointerArray alloc] initForRectPointers];
+                [lines addPointer:&lineRect];
+                bounds = NSUnionRect(lineRect, bounds);
+            }
+        }
+    }
+    if (lines == nil)
+        return nil;
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    return [[PDFAnnotationMarkup alloc] initSkimNoteWithSelection:selection 
forPage:page forType:type];
+    PDFAnnotation *annotation = [[PDFAnnotationMarkup alloc] 
initSkimNoteWithBounds:bounds forType:type];
 #pragma clang diagnostic pop
+    if (annotation) {
+        NSArray *quadPoints = quadPointsForLineRects(lines, bounds.origin, 
[page lineDirectionAngle] / 90);
+        [annotation setQuadrilateralPoints:quadPoints];
+        objc_setAssociatedObject(annotation, &SKLineRectsKey, lines, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    }
+    return annotation;
 }
 
 + (PDFAnnotation *)newSkimNoteWithPaths:(NSArray *)paths {
@@ -204,6 +350,83 @@
     return mutableProperties;
 }
 
+- (void)setDefaultSkimNoteProperties {
+    NSUserDefaults *sud = [NSUserDefaults standardUserDefaults];
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNFreeTextString]) {
+        NSFont *font = [sud fontForNameKey:SKFreeTextNoteFontNameKey 
sizeKey:SKFreeTextNoteFontSizeKey];
+        if (font)
+            [self setFont:font];
+        [self setColor:[sud colorForKey:SKFreeTextNoteColorKey]];
+        [self setFontColor:[sud colorForKey:SKFreeTextNoteFontColorKey]];
+        [self setAlignment:textAlignmentFromAlignment([sud 
integerForKey:SKFreeTextNoteAlignmentKey])];
+        PDFBorder *border = [[PDFBorder alloc] init];
+        [border setLineWidth:[sud floatForKey:SKFreeTextNoteLineWidthKey]];
+        [border setDashPattern:[sud arrayForKey:SKFreeTextNoteDashPatternKey]];
+        [border setStyle:[sud floatForKey:SKFreeTextNoteLineStyleKey]];
+        if ([border lineWidth] > 0.0) {
+            [self setBorder:border];
+        } else {
+            [self setBorder:nil];
+            // on 10.12 you can't set the border to nil, so set its lineWidth 
to 0
+            [[self border] setLineWidth:0.0];
+        }
+    } else if ([type isEqualToString:SKNCircleString]) {
+        NSColor *color = [sud colorForKey:SKCircleNoteInteriorColorKey];
+        if ([color alphaComponent] > 0.0)
+            [self setInteriorColor:color];
+        [self setColor:[sud colorForKey:SKCircleNoteColorKey]];
+        [[self border] setLineWidth:[sud 
floatForKey:SKCircleNoteLineWidthKey]];
+        [[self border] setDashPattern:[sud 
arrayForKey:SKCircleNoteDashPatternKey]];
+        [[self border] setStyle:[sud floatForKey:SKCircleNoteLineStyleKey]];
+    } else if ([type isEqualToString:SKNSquareString]) {
+        NSColor *color = [sud colorForKey:SKSquareNoteInteriorColorKey];
+        if ([color alphaComponent] > 0.0)
+            [self setInteriorColor:color];
+        [self setColor:[sud colorForKey:SKSquareNoteColorKey]];
+        [[self border] setLineWidth:[sud 
floatForKey:SKSquareNoteLineWidthKey]];
+        [[self border] setDashPattern:[sud 
arrayForKey:SKSquareNoteDashPatternKey]];
+        [[self border] setStyle:[sud floatForKey:SKSquareNoteLineStyleKey]];
+    } else if ([type isEqualToString:SKNHighlightString]) {
+        [self setColor:[sud colorForKey:SKHighlightNoteColorKey]];
+    } else if ([type isEqualToString:SKNUnderlineString]) {
+        [self setColor:[sud colorForKey:SKUnderlineNoteColorKey]];
+    } else if ([type isEqualToString:SKNStrikeOutString]) {
+        [self setColor:[sud colorForKey:SKStrikeOutNoteColorKey]];
+    } else if ([type isEqualToString:SKNLineString]) {
+        NSRect bounds = [self bounds];
+        [self setColor:[sud colorForKey:SKLineNoteColorKey]];
+        NSColor *color = [sud colorForKey:SKLineNoteInteriorColorKey];
+        if ([color alphaComponent] > 0.0)
+            [self setInteriorColor:color];
+        [self setStartLineStyle:[sud 
integerForKey:SKLineNoteStartLineStyleKey]];
+        [self setEndLineStyle:[sud integerForKey:SKLineNoteEndLineStyleKey]];
+        [self setStartPoint:NSMakePoint(0.0, 0.0)];
+        [self setEndPoint:NSMakePoint(NSWidth(bounds), NSHeight(bounds))];
+        PDFBorder *border = [[PDFBorder alloc] init];
+        [border setLineWidth:[sud floatForKey:SKLineNoteLineWidthKey]];
+        [border setDashPattern:[sud arrayForKey:SKLineNoteDashPatternKey]];
+        [border setStyle:[sud floatForKey:SKLineNoteLineStyleKey]];
+        [self setBorder:[border lineWidth] > 0.0 ? border : nil];
+    } else if ([type isEqualToString:SKNInkString]) {
+        [self setColor:[sud colorForKey:SKInkNoteColorKey]];
+        PDFBorder *border = [[PDFBorder alloc] init];
+        [border setLineWidth:[sud floatForKey:SKInkNoteLineWidthKey]];
+        [border setDashPattern:[sud arrayForKey:SKInkNoteDashPatternKey]];
+        [border setStyle:[sud floatForKey:SKInkNoteLineStyleKey]];
+        [self setBorder:[border lineWidth] > 0.0 ? border : nil];
+    }
+}
+
+static inline NSString *alignmentStyleKeyword(NSTextAlignment alignment) {
+    switch (alignment) {
+        case NSTextAlignmentLeft: return @"left";
+        case NSTextAlignmentRight: return @"right";
+        case NSTextAlignmentCenter: return @"center";
+        default: return @"left";
+    }
+}
+
 - (NSString *)fdfString {
     NSMutableString *fdfString = [NSMutableString string];
     NSRect bounds = [self bounds];
@@ -212,6 +435,7 @@
     NSString *contents = [self contents];
     NSDate *modDate = [self modificationDate];
     NSString *userName = [self userName];
+    NSString *type = [self type];
     [[[self color] colorUsingColorSpaceName:NSDeviceRGBColorSpace] getRed:&r 
green:&g blue:&b alpha:&a];
     [fdfString appendFDFName:SKFDFTypeKey];
     [fdfString appendFDFName:SKFDFAnnotation];
@@ -259,6 +483,85 @@
         [fdfString appendFDFName:SKFDFAnnotationUserNameKey];
         [fdfString appendFormat:@"(%@)", [[userName 
lossyStringUsingEncoding:NSISOLatin1StringEncoding] 
stringByEscapingParenthesis]];
     }
+    if ([self hasInteriorColor]) {
+        a = 0.0;
+        [[[self interiorColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace] 
getRed:&r green:&g blue:&b alpha:&a];
+        if (a > 0.0) {
+            [fdfString appendFDFName:SKFDFAnnotationInteriorColorKey];
+            [fdfString appendFormat:@"[%f %f %f]", r, g, b];
+        }
+    }
+    if ([type isEqualToString:SKNFreeTextString]) {
+        [[[self fontColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace] 
getRed:&r green:&g blue:&b alpha:&a];
+        [fdfString appendFDFName:SKFDFDefaultAppearanceKey];
+        [fdfString appendFormat:@"(/%@ %f Tf %f %f %f rg)", [self fontName], 
[self fontSize], r, g, b];
+        [fdfString appendFDFName:SKFDFDefaultStyleKey];
+        [[[self fontColor] colorUsingColorSpace:[NSColorSpace sRGBColorSpace]] 
getRed:&r green:&g blue:&b alpha:&a];
+        [fdfString appendFormat:@"(font: %@ %fpt; text-align:%@; 
color:#%.2x%.2x%.2x)", [self fontName], [self fontSize], 
alignmentStyleKeyword([self alignment]), (unsigned int)(255*r), (unsigned 
int)(255*g), (unsigned int)(255*b)];
+        [fdfString appendFDFName:SKFDFAnnotationAlignmentKey];
+        [fdfString appendFormat:@" %ld", 
(long)SKFDFFreeTextAnnotationAlignmentFromPDFFreeTextAnnotationAlignment([self 
alignment])];
+    } else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString]) {
+        [fdfString appendFDFName:SKFDFAnnotationQuadrilateralPointsKey];
+        [fdfString appendString:@"["];
+        for (NSValue *value in [self quadrilateralPoints]) {
+            NSPoint point = [value pointValue];
+            [fdfString appendFormat:@"%f %f ", point.x + NSMinX(bounds), 
point.y + NSMinY(bounds)];
+        }
+        [fdfString appendString:@"]"];
+    } else if ([type isEqualToString:SKNLineString]) {
+        [fdfString appendFDFName:SKFDFAnnotationLineStylesKey];
+        [fdfString appendString:@"["];
+        [fdfString appendFDFName:SKFDFLineStyleFromPDFLineStyle([self 
startLineStyle])];
+        [fdfString appendFDFName:SKFDFLineStyleFromPDFLineStyle([self 
endLineStyle])];
+        [fdfString appendString:@"]"];
+        NSPoint startPoint = SKAddPoints([self startPoint], bounds.origin);
+        NSPoint endPoint = SKAddPoints([self endPoint], bounds.origin);
+        [fdfString appendFDFName:SKFDFAnnotationLinePointsKey];
+        [fdfString appendFormat:@"[%f %f %f %f]", startPoint.x, startPoint.y, 
endPoint.x, endPoint.y];
+    } else if ([type isEqualToString:SKNInkString]) {
+        NSPoint point;
+        NSInteger i, iMax;
+        [fdfString appendFDFName:SKFDFAnnotationInkListKey];
+        [fdfString appendString:@"["];
+        for (NSBezierPath *path in [self paths]) {
+            iMax = [path elementCount];
+            [fdfString appendString:@"["];
+            for (i = 0; i < iMax; i++) {
+                point = [path associatedPointForElementAtIndex:i];
+                [fdfString appendFormat:@"%f %f ", point.x + NSMinX(bounds), 
point.y + NSMinY(bounds)];
+            }
+            [fdfString appendString:@"]"];
+        }
+        [fdfString appendString:@"]"];
+    } else if ([type isEqualToString:SKNNoteString] || [type 
isEqualToString:SKNTextString] || [type isEqualToString:SKNStampString]) {
+        [fdfString appendFDFName:SKFDFAnnotationIconTypeKey];
+        [fdfString 
appendFDFName:SKFDFTextAnnotationIconTypeFromPDFTextAnnotationIconType([self 
iconType])];
+    } else if ([type isEqualToString:SKNWidgetString]) {
+        NSString *ft = [self widgetFieldType];
+        if ([ft isEqualToString:PDFAnnotationWidgetSubtypeText]) {
+            [fdfString appendFDFName:SKFDFAnnotationFieldTypeKey];
+            [fdfString appendFDFName:SKFDFFieldTypeText];
+            [fdfString appendFDFName:SKFDFAnnotationFieldNameKey];
+            [fdfString appendFormat:@"(%@)", [[[self fieldName] ?: @"" 
lossyStringUsingEncoding:NSISOLatin1StringEncoding] 
stringByEscapingParenthesis]];
+            [fdfString appendFDFName:SKFDFAnnotationFieldValueKey];
+            [fdfString appendFormat:@"(%@)", [[[self widgetStringValue] ?: @"" 
lossyStringUsingEncoding:NSISOLatin1StringEncoding] 
stringByEscapingParenthesis]];
+        } else if ([ft isEqualToString:PDFAnnotationWidgetSubtypeButton]) {
+            [fdfString appendFDFName:SKFDFAnnotationFieldTypeKey];
+            [fdfString appendFDFName:SKFDFFieldTypeButton];
+            [fdfString appendFDFName:SKFDFAnnotationFieldNameKey];
+            [fdfString appendFormat:@"(%@)", [[[self fieldName] ?: @"" 
lossyStringUsingEncoding:NSISOLatin1StringEncoding] 
stringByEscapingParenthesis]];
+            [fdfString appendFDFName:SKFDFAnnotationFieldValueKey];
+            [fdfString appendFormat:@"/%@", [self buttonWidgetState] == 
kPDFWidgetOnState ? [self buttonWidgetStateString] : @"Off"];
+        } else if ([ft isEqualToString:PDFAnnotationWidgetSubtypeChoice]) {
+            [fdfString appendFDFName:SKFDFAnnotationFieldTypeKey];
+            [fdfString appendFDFName:SKFDFFieldTypeChoice];
+            [fdfString appendFDFName:SKFDFAnnotationFieldNameKey];
+            [fdfString appendFormat:@"(%@)", [[[self fieldName] ?: @"" 
lossyStringUsingEncoding:NSISOLatin1StringEncoding] 
stringByEscapingParenthesis]];
+            [fdfString appendFDFName:SKFDFAnnotationFieldValueKey];
+            [fdfString appendFormat:@"(%@)", [[[self widgetStringValue] ?: @"" 
lossyStringUsingEncoding:NSISOLatin1StringEncoding] 
stringByEscapingParenthesis]];
+        }
+        
+    }
     return fdfString;
 }
 
@@ -371,12 +674,48 @@
 
 - (PDFTextAnnotationIconType)extendedIconType { return [self iconType]; }
 
-- (BOOL)hasNoteText { return NO; }
+- (BOOL)hasNoteText { return [self isMarkup] && [self isEditable]; }
 
-- (SKNoteText *)noteText { return nil; }
+- (SKNoteText *)noteText {
+    if ([self isMarkup] == NO || [self isEditable] == NO)
+        return nil;
+    SKNoteText *noteText = objc_getAssociatedObject(self, &SKNoteTextKey);
+    if (noteText == nil) {
+        noteText = [[SKNoteText alloc] initWithNote:self];
+        objc_setAssociatedObject(self, &SKNoteTextKey, noteText, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    }
+    return noteText;
+}
 
-- (PDFSelection *)selection { return nil; }
+- (PDFSelection *)selectionWithPage:(PDFPage *)page {
+    PDFSelection *selection = nil;
+    NSMutableArray *selections = nil;
+    NSPointerArray *lines = [self lineRects];
+    NSUInteger i, iMax = [lines count];
+    
+    for (i = 0; i < iMax; i++) {
+        // slightly outset the rect to avoid rounding errors, as 
selectionForRect is pretty strict in some OS versions, but unfortunately not in 
others
+        PDFSelection *sel = [page selectionForRect:NSInsetRect([lines 
rectAtIndex:i], -1.0, -1.0)];
+        if ([sel hasCharacters]) {
+            if (selection == nil)
+                selection = sel;
+            else if (selections)
+                [selections addObject:sel];
+            else
+                selections = [NSMutableArray arrayWithObject:sel];
+        }
+    }
+    if (selections)
+        [selection addSelections:selections];
+    return selection;
+}
 
+- (PDFSelection *)selection {
+    if ([self isMarkup])
+        return [self selectionWithPage:[self page]];
+    return nil;
+}
+
 - (id)objectValue {
     if ([[self type] isEqualToString:SKNWidgetString] == NO)
         return [self string];
@@ -410,67 +749,298 @@
     return kSKNPDFWidgetTypeUnknown;
 }
 
-- (NSString *)textString { return nil; }
+- (NSString *)textString {
+    if ([self isMarkup] == NO || [[self page] pageRef] == NULL)
+        return nil;
+    NSString *textString = objc_getAssociatedObject(self, &SKTextStringKey);
+    if (textString == nil) {
+        textString = [[self selection] cleanedString] ?: @"";
+        objc_setAssociatedObject(self, &SKTextStringKey, textString, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    }
+    return textString;
+}
 
-- (BOOL)isMarkup { return NO; }
+- (NSPointerArray *)lineRects {
+    if ([self isMarkup] == NO)
+        return nil;
+    NSPointerArray *lineRects = objc_getAssociatedObject(self, 
&SKLineRectsKey);
+    if (lineRects == nil) {
+        lineRects = lineRectsForQuadPoints([self quadrilateralPoints], [self 
bounds].origin);
+        objc_setAssociatedObject(self, &SKLineRectsKey, lineRects, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    }
+    return lineRects;
+}
 
+- (BOOL)isMarkup {
+    NSString *type = [self type];
+    return [type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString];
+}
+
 - (BOOL)isNote { return NO; }
 
-- (BOOL)isText { return NO; }
+- (BOOL)isText { return [[self type] isEqualToString:SKNFreeTextString]; }
 
-- (BOOL)isShape { return NO; }
+- (BOOL)isShape {
+    NSString *type = [self type];
+    return [type isEqualToString:SKNCircleString] || [type 
isEqualToString:SKNSquareString];
+}
 
-- (BOOL)isLine { return NO; }
+- (BOOL)isLine { return [[self type] isEqualToString:SKNLineString]; }
 
-- (BOOL)isInk { return NO; }
+- (BOOL)isInk { return [[self type] isEqualToString:SKNInkString]; }
 
 - (BOOL)isLink { return [[self type] isEqualToString:@"Link"]; }
 
-- (BOOL)isWidget { return [self widgetType] != kSKNPDFWidgetTypeUnknown; }
+- (BOOL)isWidget {
+    SKNPDFWidgetType widgetType = [self widgetType];
+    if (widgetType == kSKNPDFWidgetTypeUnknown)
+        return NO;
+    if (widgetType != kSKNPDFWidgetTypeButton)
+        return YES;
+    PDFWidgetControlType controlType = [self widgetControlType];
+    return controlType == kPDFWidgetCheckBoxControl || controlType == 
kPDFWidgetRadioButtonControl;
+}
 
-- (BOOL)isResizable { return NO; }
+- (BOOL)isResizable {
+    if ([self isSkimNote] == NO)
+        return NO;
+    static NSSet *resizableTypes = nil;
+    if (resizableTypes == nil)
+        resizableTypes = [NSSet setWithObjects:SKNFreeTextString, 
SKNCircleString, SKNSquareString, SKNLineString, SKNInkString, nil];
+    return [resizableTypes containsObject:[self type]];
+}
 
-- (BOOL)isMovable { return NO; }
+- (BOOL)isMovable {
+    if ([self isSkimNote] == NO)
+        return NO;
+    static NSSet *movableTypes = nil;
+    if (movableTypes == nil)
+        movableTypes = [NSSet setWithObjects:SKNFreeTextString, SKNNoteString, 
SKNCircleString, SKNSquareString, SKNLineString, SKNInkString, nil];
+    return [movableTypes containsObject:[self type]];
+}
 
 - (BOOL)isEditable { return [self isSkimNote] && ([self page] == nil || [[self 
page] isEditable]); }
 
-- (BOOL)hasBorder { return [self isSkimNote]; }
+- (BOOL)hasBorder {
+    static NSSet *borderedTypes = nil;
+    if (borderedTypes == nil)
+        borderedTypes = [NSSet setWithObjects:SKNFreeTextString, 
SKNCircleString, SKNSquareString, SKNLineString, SKNInkString, nil];
+    return [borderedTypes containsObject:[self type]];
+}
 
-- (BOOL)hasInteriorColor { return NO; }
+- (BOOL)hasInteriorColor {
+    if ([self isSkimNote] == NO)
+        return NO;
+    NSString *type = [self type];
+    return [type isEqualToString:SKNCircleString] || [type 
isEqualToString:SKNSquareString] || [type isEqualToString:SKNLineString];
+}
 
 - (BOOL)isConvertibleAnnotation {
     static NSSet *convertibleTypes = nil;
     if (convertibleTypes == nil)
-        convertibleTypes = [[NSSet alloc] initWithObjects:SKNFreeTextString, 
SKNTextString, SKNNoteString, SKNCircleString, SKNSquareString, 
SKNHighlightString, SKNUnderlineString, SKNStrikeOutString, SKNLineString, 
SKNInkString, nil];
+        convertibleTypes = [[NSSet alloc] initWithObjects:SKNFreeTextString, 
SKNTextString, SKNStampString, SKNNoteString, SKNCircleString, SKNSquareString, 
SKNHighlightString, SKNUnderlineString, SKNStrikeOutString, SKNLineString, 
SKNInkString, nil];
     return [convertibleTypes containsObject:[self type]];
 }
 
 - (BOOL)hitTest:(NSPoint)point {
-    return [self shouldDisplay] && [self isSkimNote] && NSPointInRect(point, 
[self bounds]);
+    if ([self shouldDisplay] == NO || [self isSkimNote] == NO)
+        return NO;
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNLineString]) {
+        CGFloat delta = fmax(4.0, 0.5 * [self lineWidth]);
+        return SKPointNearLineFromPointToPoint(SKSubstractPoints(point, [self 
bounds].origin), [self startPoint], [self endPoint], delta);
+    } else if (NSPointInRect(point, [self bounds]) == NO) {
+        return NO;
+    }
+    if ([type isEqualToString:SKNCircleString]) {
+        NSRect bounds = [self bounds];
+        CGFloat dx = 2.0 * (point.x - NSMidX(bounds)) / NSWidth(bounds);
+        CGFloat dy = 2.0 * (point.y - NSMidY(bounds)) / NSHeight(bounds);
+        if (dx * dx + dy * dy > 1.0)
+            return NO;
+        if ([self interiorColor])
+            return YES;
+        CGFloat delta = fmax(8.0, [self lineWidth]);
+        if (NSWidth(bounds) <= 2.0 * delta || NSHeight(bounds) <= 2.0 * delta)
+            return YES;
+        bounds = NSInsetRect(bounds, delta, delta);
+        dx = 2.0 * (point.x - NSMidX(bounds)) / NSWidth(bounds);
+        dy = 2.0 * (point.y - NSMidY(bounds)) / NSHeight(bounds);
+        return dx * dx + dy * dy >= 1.0;
+    } else if ([type isEqualToString:SKNSquareString]) {
+        if ([self interiorColor])
+            return YES;
+        NSRect bounds = [self bounds];
+        CGFloat delta = fmax(8.0, [self lineWidth]);
+        return NSWidth(bounds) <= 2.0 * delta || NSHeight(bounds) <= 2.0 * 
delta || NSPointInRect(point, NSInsetRect(bounds, delta, delta)) == NO;
+    } else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString]) {
+        NSPointerArray *lines = [self lineRects];
+        NSUInteger i = [lines count];
+        BOOL isContained = NO;
+        while (i-- && NO == isContained)
+            isContained = NSPointInRect(point, [lines rectAtIndex:i]);
+        return isContained;
+    }
+    return YES;
 }
 
 - (CGFloat)boundsOrder {
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNLineString]) {
+        CGFloat delta = ceil(fmax(4.0 * [self lineWidth], 4.0));
+        NSPoint origin = [self bounds].origin;
+        NSRect startBounds = SKRectFromCenterAndSquareSize(SKAddPoints(origin, 
[self startPoint]), delta);
+        NSRect endBounds = SKRectFromCenterAndSquareSize(SKAddPoints(origin, 
[self endPoint]), delta);
+        PDFPage *page = [self page];
+        return fmin([page sortOrderForBounds:startBounds], [page 
sortOrderForBounds:endBounds]);
+    } else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString]) {
+        NSPointerArray *lines = [self lineRects];
+        NSRect bounds = [lines count] > 0 ? [lines rectAtIndex:0] : [self 
bounds];
+        return [[self page] sortOrderForBounds:bounds];
+    }
     return [[self page] sortOrderForBounds:[self bounds]];
 }
 
 - (SKRectEdges)resizeHandleForPoint:(NSPoint)point 
scaleFactor:(CGFloat)scaleFactor {
-    return [self isResizable] ? SKResizeHandleForPointFromRect(point, [self 
bounds], 4.0 / scaleFactor) : SKRectEdgesNone;
+    if ([self isResizable] == NO)
+        return SKRectEdgesNone;
+    if ([[self type] isEqualToString:SKNLineString]) {
+        NSSize size = SKMakeSquareSize(8.0 / scaleFactor);
+        point = SKSubstractPoints(point, [self bounds].origin);
+        if (NSPointInRect(point, SKRectFromCenterAndSize([self endPoint], 
size)))
+            return SKRectEdgesMaxX;
+        else if (NSPointInRect(point, SKRectFromCenterAndSize([self 
startPoint], size)))
+            return SKRectEdgesMinX;
+        else
+            return SKRectEdgesNone;
+    }
+    return SKResizeHandleForPointFromRect(point, [self bounds], 4.0 / 
scaleFactor);
 }
 
+- (void)drawShadowWithUnitWidth:(CGFloat)unitWidth 
inContext:(CGContextRef)context {
+    NSRect bounds = [self bounds];
+    CGFloat r = fmin(2.0, 2.0 * unitWidth);
+    CGRect rect = NSRectToCGRect(NSInsetRect(bounds, 2.0 * r, 2.0 * r));
+    CGAffineTransform t = CGAffineTransformConcat(CGContextGetCTM(context), 
CGAffineTransformInvert(CGContextGetBaseCTM_func(context)));
+    r = fabs(CGSizeApplyAffineTransform(CGSizeMake(r, r), t).height);
+    t = CGAffineTransformMakeTranslation(NSMinX(bounds), NSMinY(bounds));
+    CGMutablePathRef path = CGPathCreateMutable();
+    for (NSBezierPath *aPath in [self paths])
+        [aPath addToCGPath:path transform:&t];
+    CGContextSaveGState(context);
+    CGContextSetAlpha(context, [[self color] alphaComponent]);
+    CGContextBeginTransparencyLayerWithRect(context, rect, NULL);
+    CGContextSetLineWidth(context, [self lineWidth]);
+    if ([self borderStyle] == kPDFBorderStyleDashed) {
+        NSArray *dashPattern = [self dashPattern];
+        NSUInteger i, count = [dashPattern count];
+        CGFloat pattern[count];
+        for (i = 0; i < count; i++)
+            pattern[i] = [[dashPattern objectAtIndex:i] doubleValue];
+        CGContextSetLineDash(context, 0.0, pattern, count);
+        CGContextSetLineCap(context, kCGLineCapButt);
+    } else {
+        CGContextSetLineCap(context, kCGLineCapRound);
+    }
+    CGContextSetShadow(context, CGSizeMake(0.0, -r), r);
+    CGContextAddPath(context, path);
+    CGContextStrokePath(context);
+    CGContextSetShadowWithColor(context, CGSizeZero, 0.0, NULL);
+    CGContextSetBlendMode(context, kCGBlendModeClear);
+    CGContextAddPath(context, path);
+    CGContextStrokePath(context);
+    CGContextEndTransparencyLayer(context);
+    CGContextRestoreGState(context);
+    CGPathRelease(path);
+}
+
+- (void)drawFallbackShadowWithUnitWidth:(CGFloat)unitWidth 
inContext:(CGContextRef)context {
+    CGFloat r = fmin(2.0 / unitWidth, 2.0);
+    NSSize offset = NSZeroSize;
+    switch ([[self page] rotation]) {
+        case 0:   offset.height = -r; break;
+        case 90:  offset.width = r;   break;
+        case 180: offset.height = r;  break;
+        case 270: offset.width = -r;  break;
+        default:  offset.height = -r; break;
+    }
+    NSRect bounds = [self bounds];
+    NSRect rect = NSIntersectionRect(NSOffsetRect(NSInsetRect(bounds, -r * 
unitWidth, -r * unitWidth), offset.width * unitWidth, offset.height * 
unitWidth), NSRectFromCGRect(CGContextGetClipBoundingBox(context)));
+    if (NSIsEmptyRect(rect) == NO) {
+        NSRect imgRect = NSMakeRect(0.0, 0.0, ceil(NSWidth(rect) / unitWidth), 
ceil(NSHeight(rect) / unitWidth));
+        rect.size = NSMakeSize(NSWidth(imgRect) * unitWidth, NSHeight(imgRect) 
* unitWidth);
+        NSImage *image = [NSImage imageWithSize:imgRect.size flipped:NO 
drawingHandler:^(NSRect dstRect){
+            NSAffineTransform *transform = [NSAffineTransform transform];
+            [transform scaleBy:1.0 / unitWidth];
+            [transform translateXBy:NSMinX(bounds) - NSMinX(rect) 
yBy:NSMinY(bounds) - NSMinY(rect)];
+            [transform concat];
+            NSBezierPath *path = [NSBezierPath bezierPath];
+            for (NSBezierPath *aPath in [self paths])
+                [path appendBezierPath:aPath];
+            [path setLineWidth:fmax(1.0, [self lineWidth])];
+            [path setLineJoinStyle:NSRoundLineJoinStyle];
+            if ([self borderStyle] == kPDFBorderStyleDashed) {
+                [path setDashPattern:[self dashPattern]];
+                [path setLineCapStyle:NSButtLineCapStyle];
+            } else {
+                [path setLineCapStyle:NSRoundLineCapStyle];
+            }
+            [NSGraphicsContext saveGraphicsState];
+            [NSShadow setShadowWithColor:[NSColor 
colorWithGenericGamma22White:0.0 alpha:0.33333] blurRadius:r offset:offset];
+            [path stroke];
+            [NSGraphicsContext restoreGraphicsState];
+            [[NSGraphicsContext currentContext] 
setCompositingOperation:NSCompositingOperationClear];
+            [path stroke];
+            return YES;
+        }];
+        [NSGraphicsContext saveGraphicsState];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext 
graphicsContextWithCGContext:context flipped:NO]];
+        [image drawInRect:rect fromRect:imgRect 
operation:NSCompositingOperationSourceOver fraction:[[self color] 
alphaComponent]];
+        [NSGraphicsContext restoreGraphicsState];
+    }
+}
+
 - (void)drawSelectionHighlightWithUnitWidth:(CGFloat)unitWidth 
active:(BOOL)active inContext:(CGContextRef)context {
     if (NSIsEmptyRect([self bounds]))
         return;
     if ([self isSkimNote]) {
-        CGRect rect = CGContextConvertRectToUserSpace(context, 
CGRectIntegral(CGContextConvertRectToDeviceSpace(context, NSRectToCGRect([self 
bounds]))));
-        CGContextSaveGState(context);
-        if ([self isResizable]) {
-            SKDrawResizeHandles(context, NSRectFromCGRect(rect), unitWidth, 
YES, active);
-        } else {
+        NSString *type = [self type];
+        if ([type isEqualToString:SKNLineString]) {
+            NSPoint origin = [self bounds].origin;
+            SKDrawResizeHandlePair(context, SKAddPoints(origin, [self 
startPoint]), SKAddPoints(origin, [self endPoint]), unitWidth, active);
+        } else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString]) {
+            NSPointerArray *lines = [self lineRects];
+            NSUInteger i, iMax = [lines count];
             CGColorRef color = [[NSColor selectionHighlightColor:active] 
CGColor];
+            
+            CGContextSaveGState(context);
             CGContextSetStrokeColorWithColor(context, color);
-            CGContextStrokeRectWithWidth(context, CGRectInset(rect, -0.5 * 
unitWidth, -0.5 * unitWidth), unitWidth);
+            CGContextSetLineWidth(context, unitWidth);
+            for (i = 0; i < iMax; i++) {
+                CGRect rect = CGContextConvertRectToUserSpace(context, 
CGRectIntegral(CGContextConvertRectToDeviceSpace(context, NSRectToCGRect([lines 
rectAtIndex:i]))));
+                CGContextStrokeRect(context, CGRectInset(rect, -0.5 * 
unitWidth, -0.5 * unitWidth));
+            }
+            CGContextRestoreGState(context);
+        } else {
+            if ([type isEqualToString:SKNInkString]) {
+                if (NSIsEmptyRect([self bounds]) == NO && [self isSkimNote]) {
+                    if (CGContextGetBaseCTM_func != NULL)
+                        [self drawShadowWithUnitWidth:unitWidth 
inContext:context];
+                    else
+                        [self drawFallbackShadowWithUnitWidth:unitWidth 
inContext:context];
+                }
+            }
+            CGRect rect = CGContextConvertRectToUserSpace(context, 
CGRectIntegral(CGContextConvertRectToDeviceSpace(context, NSRectToCGRect([self 
bounds]))));
+            CGContextSaveGState(context);
+            if ([self isResizable]) {
+                SKDrawResizeHandles(context, NSRectFromCGRect(rect), 
unitWidth, YES, active);
+            } else {
+                CGColorRef color = [[NSColor selectionHighlightColor:active] 
CGColor];
+                CGContextSetStrokeColorWithColor(context, color);
+                CGContextStrokeRectWithWidth(context, CGRectInset(rect, -0.5 * 
unitWidth, -0.5 * unitWidth), unitWidth);
+            }
+            CGContextRestoreGState(context);
         }
-        CGContextRestoreGState(context);
     } else if ([self isLink]) {
         CGContextSaveGState(context);
         CGColorRef color = CGColorCreateGenericGray(0.0, 0.2);
@@ -490,21 +1060,133 @@
         [self setModificationDate:[NSDate date]];
 }
 
-- (void)autoUpdateStringWithPage:(PDFPage *)page {}
+- (void)autoUpdateStringWithPage:(PDFPage *)page {
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNCircleString]) {
+        // this calculation is roughly the inverse of -[PDFView 
addOtherAnnotationWithType:selection:point:]
+        NSRect bounds = NSInsetRect([self bounds], [self lineWidth] - 1.0, 
[self lineWidth] - 1.0);
+        CGFloat t, w = NSWidth(bounds), h = NSWidth(bounds);
+        if (w <= 0.0 || h <= 0.0)
+            return;
+        t = 0.5 * w * h * (w + h - sqrt(2.0 * w * h)) / (w * w + h * h);
+        bounds = NSInsetRect(bounds, t, t);
+        NSString *selString = [[page selectionForRect:bounds] cleanedString];
+        if ([selString length])
+            [self setString:selString];
+    } else if ([type isEqualToString:SKNSquareString]) {
+        NSRect bounds = NSInsetRect([self bounds], [self lineWidth] - 1.0, 
[self lineWidth] - 1.0);
+        if (NSWidth(bounds) <= 0.0 || NSHeight(bounds) <= 0.0)
+            return;
+        NSString *selString = [[page selectionForRect:bounds] cleanedString];
+        if ([selString length])
+            [self setString:selString];
+    } else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString]) {
+        NSString *selString = [[self selectionWithPage:page] cleanedString];
+        if ([selString length]) {
+            // page should be future [self page] and textString will not have 
been called
+            objc_setAssociatedObject(self, &SKTextStringKey, selString, 
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+            [self setString:selString];
+        }
+    }
+}
 
-- (NSString *)colorDefaultKey { return nil; }
+- (NSString *)colorDefaultKey {
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNFreeTextString])
+        return SKFreeTextNoteColorKey;
+    else if ([type isEqualToString:SKNCircleString])
+        return SKCircleNoteColorKey;
+    else if ([type isEqualToString:SKNSquareString])
+        return SKSquareNoteColorKey;
+    else if ([type isEqualToString:SKNHighlightString])
+        return SKHighlightNoteColorKey;
+    else if ([type isEqualToString:SKNUnderlineString])
+        return SKUnderlineNoteColorKey;
+    else if ([type isEqualToString:SKNStrikeOutString])
+        return SKStrikeOutNoteColorKey;
+    else if ([type isEqualToString:SKNLineString])
+        return SKLineNoteColorKey;
+    else if ([type isEqualToString:SKNInkString])
+        return SKInkNoteColorKey;
+    else
+        return nil;
+}
 
-- (NSString *)alternateColorDefaultKey { return nil; }
+- (NSString *)alternateColorDefaultKey {
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNFreeTextString])
+        return SKFreeTextNoteFontColorKey;
+    else if ([type isEqualToString:SKNCircleString])
+        return SKCircleNoteInteriorColorKey;
+    else if ([type isEqualToString:SKNSquareString])
+        return SKSquareNoteInteriorColorKey;
+    else if ([type isEqualToString:SKNLineString])
+        return SKLineNoteInteriorColorKey;
+    else
+        return nil;
+}
 
-- (NSString *)lineWidthDefaultKey { return nil; }
+- (NSString *)lineWidthDefaultKey {
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNFreeTextString])
+        return SKFreeTextNoteLineWidthKey;
+    else if ([type isEqualToString:SKNCircleString])
+        return SKCircleNoteLineWidthKey;
+    else if ([type isEqualToString:SKNSquareString])
+        return SKSquareNoteLineWidthKey;
+    else if ([type isEqualToString:SKNLineString])
+        return SKLineNoteLineWidthKey;
+    else if ([type isEqualToString:SKNInkString])
+        return SKInkNoteLineWidthKey;
+    else
+        return nil;
+}
 
-- (NSString *)borderStyleDefaultKey { return nil; }
+- (NSString *)borderStyleDefaultKey {
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNFreeTextString])
+        return SKFreeTextNoteLineStyleKey;
+    else if ([type isEqualToString:SKNCircleString])
+        return SKCircleNoteLineStyleKey;
+    else if ([type isEqualToString:SKNSquareString])
+        return SKSquareNoteLineStyleKey;
+    else if ([type isEqualToString:SKNLineString])
+        return SKLineNoteLineStyleKey;
+    else if ([type isEqualToString:SKNInkString])
+        return SKInkNoteLineStyleKey;
+    else
+        return nil;
+}
 
-- (NSString *)dashPatternDefaultKey { return nil; }
+- (NSString *)dashPatternDefaultKey {
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNFreeTextString])
+        return SKFreeTextNoteDashPatternKey;
+    else if ([type isEqualToString:SKNCircleString])
+        return SKCircleNoteDashPatternKey;
+    else if ([type isEqualToString:SKNSquareString])
+        return SKSquareNoteDashPatternKey;
+    else if ([type isEqualToString:SKNLineString])
+        return SKLineNoteDashPatternKey;
+    else if ([type isEqualToString:SKNInkString])
+        return SKInkNoteDashPatternKey;
+    else
+        return nil;
+}
 
-- (NSString *)startLineStyleDefaultKey { return nil; }
+- (NSString *)startLineStyleDefaultKey {
+    if ([[self type] isEqualToString:SKNLineString])
+        return SKLineNoteStartLineStyleKey;
+    else
+        return nil;
+}
 
-- (NSString *)endLineStyleDefaultKey { return nil; }
+- (NSString *)endLineStyleDefaultKey {
+    if ([[self type] isEqualToString:SKNLineString])
+        return SKLineNoteEndLineStyleKey;
+    else
+        return nil;
+}
 
 - (void)setColor:(NSColor *)color alternate:(BOOL)alternate 
updateDefaults:(BOOL)update {
     BOOL isFill = alternate && [self hasInteriorColor];
@@ -575,12 +1257,42 @@
 }
 
 - (NSSet *)keysForValuesToObserveForUndo {
-    if ([[self type] isEqualToString:SKNWidgetString])
+    NSString *type = [self type];
+    if ([type isEqualToString:SKNFreeTextString]) {
+        static NSSet *keys = nil;
+        if (keys == nil)
+            keys = [[NSSet alloc] initWithObjects:SKNPDFAnnotationBoundsKey, 
SKNPDFAnnotationStringKey, SKNPDFAnnotationColorKey, SKNPDFAnnotationBorderKey, 
SKNPDFAnnotationModificationDateKey, SKNPDFAnnotationUserNameKey, 
SKNPDFAnnotationFontKey, SKNPDFAnnotationFontColorKey, 
SKNPDFAnnotationAlignmentKey, nil];
+        return keys;
+    } else if ([type isEqualToString:SKNNoteString]) {
+        static NSSet *keys = nil;
+        if (keys == nil)
+            keys = [[NSSet alloc] initWithObjects:SKNPDFAnnotationBoundsKey, 
SKNPDFAnnotationStringKey, SKNPDFAnnotationColorKey, 
SKNPDFAnnotationModificationDateKey, SKNPDFAnnotationUserNameKey, 
SKNPDFAnnotationNameKey, SKNPDFAnnotationTextKey, SKNPDFAnnotationImageKey, 
SKNPDFAnnotationDrawsImageKey, nil];
+        return keys;
+    } else if ([type isEqualToString:SKNCircleString] || [type 
isEqualToString:SKNSquareString]) {
+        static NSSet *keys = nil;
+        if (keys == nil)
+            keys = [[NSSet alloc] initWithObjects:SKNPDFAnnotationBoundsKey, 
SKNPDFAnnotationStringKey, SKNPDFAnnotationColorKey, SKNPDFAnnotationBorderKey, 
SKNPDFAnnotationModificationDateKey, SKNPDFAnnotationUserNameKey, 
SKNPDFAnnotationInteriorColorKey, nil];
+        return keys;
+    } else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString]) {
+        static NSSet *keys = nil;
+        if (keys == nil)
+            keys = [[NSSet alloc] initWithObjects:SKNPDFAnnotationBoundsKey, 
SKNPDFAnnotationStringKey, SKNPDFAnnotationColorKey, 
SKNPDFAnnotationModificationDateKey, SKNPDFAnnotationUserNameKey, nil];
+        return keys;
+    } else if ([type isEqualToString:SKNLineString]) {
+        static NSSet *keys = nil;
+        if (keys == nil)
+            keys = [[NSSet alloc] initWithObjects:SKNPDFAnnotationBoundsKey, 
SKNPDFAnnotationStringKey, SKNPDFAnnotationColorKey, SKNPDFAnnotationBorderKey, 
SKNPDFAnnotationModificationDateKey, SKNPDFAnnotationUserNameKey, 
SKNPDFAnnotationStartLineStyleKey, SKNPDFAnnotationEndLineStyleKey, 
SKNPDFAnnotationStartPointKey, SKNPDFAnnotationEndPointKey, 
SKNPDFAnnotationInteriorColorKey, nil];
+        return keys;
+    } else if ([type isEqualToString:SKNInkString]) {
+        static NSSet *keys = nil;
+        if (keys == nil)
+            keys = [[NSSet alloc] initWithObjects:SKNPDFAnnotationBoundsKey, 
SKNPDFAnnotationStringKey, SKNPDFAnnotationColorKey, SKNPDFAnnotationBorderKey, 
SKNPDFAnnotationModificationDateKey, SKNPDFAnnotationUserNameKey, 
SKPDFAnnotationBezierPathsKey, nil];
+        return keys;
+    } else if ([type isEqualToString:SKNWidgetString] && [self isWidget]) {
         return [NSSet setWithObject:@"objectValue"];
-    static NSSet *keys = nil;
-    if (keys == nil)
-        keys = [[NSSet alloc] initWithObjects:SKNPDFAnnotationBoundsKey, 
SKNPDFAnnotationStringKey, SKNPDFAnnotationColorKey, SKNPDFAnnotationBorderKey, 
SKNPDFAnnotationModificationDateKey, SKNPDFAnnotationUserNameKey, nil];
-    return keys;
+    } else {
+        return [NSSet set];
+    }
 }
 
 #pragma mark Scripting support
@@ -595,35 +1307,51 @@
     return [NSString stringWithFormat:@"%p", (void *)self];
 }
 
-// overridden by subclasses to add or remove custom scripting keys relevant 
for the class, subclasses should call super first
-+ (NSSet *)customScriptingKeys {
-    static NSSet *customScriptingKeys = nil;
-    if (customScriptingKeys == nil)
-        customScriptingKeys = [[NSSet alloc] 
initWithObjects:SKNPDFAnnotationLineWidthKey, SKNPDFAnnotationBorderStyleKey, 
SKNPDFAnnotationDashPatternKey, nil];
-    return customScriptingKeys;
+static NSArray *invalidScriptingKeysForType(NSString *type) {
+    if ([type isEqualToString:SKNFreeTextString]) {
+        static NSArray *keys = nil;
+        if (keys == nil)
+            keys = @[SKPDFAnnotationStartPointAsQDPointKey, 
SKPDFAnnotationEndPointAsQDPointKey, SKPDFAnnotationScriptingStartLineStyleKey, 
SKPDFAnnotationScriptingEndLineStyleKey, 
SKPDFAnnotationScriptingInteriorColorKey, 
SKPDFAnnotationScriptingPointListsKey, SKPDFAnnotationSelectionSpecifierKey, 
SKPDFAnnotationScriptingIconTypeKey, SKPDFAnnotationRichTextKey, 
SKPDFAnnotationScriptingImageDataKey];
+        return keys;
+    } else if ([type isEqualToString:SKNNoteString]) {
+        static NSArray *keys = nil;
+        if (keys == nil)
+            keys = @[SKNPDFAnnotationLineWidthKey, 
SKNPDFAnnotationBorderStyleKey, SKNPDFAnnotationDashPatternKey, 
SKPDFAnnotationStartPointAsQDPointKey, SKPDFAnnotationEndPointAsQDPointKey, 
SKPDFAnnotationScriptingStartLineStyleKey, 
SKPDFAnnotationScriptingEndLineStyleKey, 
SKPDFAnnotationScriptingInteriorColorKey, SKNPDFAnnotationFontNameKey, 
SKNPDFAnnotationFontSizeKey, SKPDFAnnotationScriptingFontColorKey, 
SKPDFAnnotationScriptingAlignmentKey, SKPDFAnnotationScriptingPointListsKey, 
SKPDFAnnotationSelectionSpecifierKey];
+        return keys;
+    } else if ([type isEqualToString:SKNCircleString] || [type 
isEqualToString:SKNSquareString]) {
+        static NSArray *keys = nil;
+        if (keys == nil)
+            keys = @[SKPDFAnnotationStartPointAsQDPointKey, 
SKPDFAnnotationEndPointAsQDPointKey, SKPDFAnnotationScriptingStartLineStyleKey, 
SKPDFAnnotationScriptingEndLineStyleKey, SKNPDFAnnotationFontNameKey, 
SKNPDFAnnotationFontSizeKey, SKPDFAnnotationScriptingFontColorKey, 
SKPDFAnnotationScriptingAlignmentKey, SKPDFAnnotationScriptingPointListsKey, 
SKPDFAnnotationSelectionSpecifierKey, SKPDFAnnotationScriptingIconTypeKey, 
SKPDFAnnotationRichTextKey, SKPDFAnnotationScriptingImageDataKey];
+        return keys;
+    } else if ([type isEqualToString:SKNHighlightString] || [type 
isEqualToString:SKNUnderlineString] || [type 
isEqualToString:SKNStrikeOutString]) {
+        static NSArray *keys = nil;
+        if (keys == nil)
+            keys = @[SKNPDFAnnotationLineWidthKey, 
SKNPDFAnnotationBorderStyleKey, SKNPDFAnnotationDashPatternKey, 
SKPDFAnnotationStartPointAsQDPointKey, SKPDFAnnotationEndPointAsQDPointKey, 
SKPDFAnnotationScriptingStartLineStyleKey, 
SKPDFAnnotationScriptingEndLineStyleKey, 
SKPDFAnnotationScriptingInteriorColorKey, SKNPDFAnnotationFontNameKey, 
SKNPDFAnnotationFontSizeKey, SKPDFAnnotationScriptingFontColorKey, 
SKPDFAnnotationScriptingAlignmentKey, SKPDFAnnotationScriptingIconTypeKey, 
SKPDFAnnotationRichTextKey, SKPDFAnnotationScriptingImageDataKey];
+        return keys;
+    } else if ([type isEqualToString:SKNLineString]) {
+        static NSArray *keys = nil;
+        if (keys == nil)
+            keys = @[SKNPDFAnnotationFontNameKey, SKNPDFAnnotationFontSizeKey, 
SKPDFAnnotationScriptingFontColorKey, SKPDFAnnotationScriptingAlignmentKey, 
SKPDFAnnotationScriptingPointListsKey, SKPDFAnnotationSelectionSpecifierKey, 
SKPDFAnnotationScriptingIconTypeKey, SKPDFAnnotationRichTextKey, 
SKPDFAnnotationScriptingImageDataKey];
+        return keys;
+    } else if ([type isEqualToString:SKNInkString]) {
+        static NSArray *keys = nil;
+        if (keys == nil)
+            keys = @[SKPDFAnnotationStartPointAsQDPointKey, 
SKPDFAnnotationEndPointAsQDPointKey, SKPDFAnnotationScriptingStartLineStyleKey, 
SKPDFAnnotationScriptingEndLineStyleKey, 
SKPDFAnnotationScriptingInteriorColorKey, SKNPDFAnnotationFontNameKey, 
SKNPDFAnnotationFontSizeKey, SKPDFAnnotationScriptingFontColorKey, 
SKPDFAnnotationScriptingAlignmentKey, SKPDFAnnotationSelectionSpecifierKey, 
SKPDFAnnotationScriptingIconTypeKey, SKPDFAnnotationRichTextKey, 
SKPDFAnnotationScriptingImageDataKey];
+        return keys;
+    } else if ([type isEqualToString:SKNWidgetString]) {
+        static NSArray *keys = nil;
+        if (keys == nil)
+            keys = @[SKNPDFAnnotationLineWidthKey, 
SKNPDFAnnotationBorderStyleKey, SKNPDFAnnotationDashPatternKey, 
SKPDFAnnotationStartPointAsQDPointKey, SKPDFAnnotationEndPointAsQDPointKey, 
SKPDFAnnotationScriptingStartLineStyleKey, 
SKPDFAnnotationScriptingEndLineStyleKey, 
SKPDFAnnotationScriptingInteriorColorKey, SKNPDFAnnotationFontNameKey, 
SKNPDFAnnotationFontSizeKey, SKPDFAnnotationScriptingFontColorKey, 
SKPDFAnnotationScriptingAlignmentKey, SKPDFAnnotationScriptingPointListsKey, 
SKPDFAnnotationSelectionSpecifierKey, SKPDFAnnotationScriptingIconTypeKey, 
SKPDFAnnotationRichTextKey, SKPDFAnnotationScriptingImageDataKey];
+        return keys;
+    } else {
+        return [NSArray array];
+    }
 }
 
 - (NSDictionary *)scriptingProperties {
-    static NSSet *allCustomScriptingKeys = nil;
-    if (allCustomScriptingKeys == nil) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        NSMutableSet *customScriptingKeys = [NSMutableSet set];
-        [customScriptingKeys unionSet:[PDFAnnotationCircle 
customScriptingKeys]];
-        [customScriptingKeys unionSet:[PDFAnnotationSquare 
customScriptingKeys]];
-        [customScriptingKeys unionSet:[PDFAnnotationFreeText 
customScriptingKeys]];
-        [customScriptingKeys unionSet:[SKNPDFAnnotationNote 
customScriptingKeys]];
-        [customScriptingKeys unionSet:[PDFAnnotationMarkup 
customScriptingKeys]];
-        [customScriptingKeys unionSet:[PDFAnnotationLine customScriptingKeys]];
-        [customScriptingKeys unionSet:[PDFAnnotationInk customScriptingKeys]];
-        allCustomScriptingKeys = [customScriptingKeys copy];
-#pragma clang diagnostic pop
-    }
     // remove all custom properties that are not valid for this class
     NSMutableDictionary *properties = [[super scriptingProperties] 
mutableCopy];
-    NSMutableSet *customKeys = [allCustomScriptingKeys mutableCopy];
-    [customKeys minusSet:[[self class] customScriptingKeys]];
-    [properties removeObjectsForKeys:[customKeys allObjects]];
+    [properties removeObjectsForKeys:invalidScriptingKeysForType([self type])];
     return properties;
 }
 
@@ -679,7 +1407,16 @@
 
 - (id)textContents;
 {
-    return [self string] == nil ? nil : [[NSTextStorage alloc] 
initWithString:[self string]];
+    if ([self string] == nil)
+        return nil;
+    NSTextStorage *textContents = [[NSTextStorage alloc] initWithString:[self 
string]];
+    if ([[self type] isEqualToString:SKNFreeTextString]) {
+        if ([self font])
+            [textContents addAttribute:NSFontAttributeName value:[self font] 
range:NSMakeRange(0, [textContents length])];
+        if ([self fontColor])
+            [textContents addAttribute:NSForegroundColorAttributeName 
value:[self fontColor] range:NSMakeRange(0, [textContents length])];
+    }
+    return textContents;
 }
 
 - (void)setTextContents:(id)text;
@@ -699,11 +1436,36 @@
     return nil;
 }
 
+- (NSData *)boundsAsQDRect {
+    return [NSData dataWithRectAsQDRect:[self bounds]];
+}
+
 - (void)setBoundsAsQDRect:(NSData *)inQDBoundsAsData {
     if ([self isMovable] && [self isEditable]) {
         NSRect newBounds = [inQDBoundsAsData rectValueAsQDRect];
         if ([self isResizable] == NO) {
             newBounds.size = [self bounds].size;
+        } else if ([[self type] isEqualToString:SKNInkString]) {
+            CGFloat margin = [self pathInset];
+            NSRect bounds = [self bounds];
+            
+            if (NSWidth(newBounds) < 2.0 * margin)
+                newBounds.size.width = 2.0 * margin;
+            if (NSHeight(newBounds) < 2.0 * margin)
+                newBounds.size.height = 2.0 * margin;
+            
+            if (NSEqualSizes(bounds.size, newBounds.size) == NO) {
+                NSMutableArray *paths = [NSMutableArray array];
+                NSAffineTransform *transform = [NSAffineTransform transform];
+                [transform translateXBy:margin yBy:margin];
+                [transform scaleXBy:fmax(1.0, NSWidth(newBounds) - 2.0 * 
margin) / fmax(1.0, NSWidth(bounds) - 2.0 * margin) yBy:fmax(1.0, 
NSHeight(newBounds) - 2.0 * margin) / fmax(1.0, NSHeight(bounds) - 2.0 * 
margin)];
+                [transform translateXBy:-margin yBy:-margin];
+                
+                for (NSBezierPath *path in [self paths])
+                    [paths addObject:[transform transformBezierPath:path]];
+                
+                [self setBezierPaths:paths];
+            }
         } else {
             if (NSWidth(newBounds) < 0.0)
                 newBounds.size.width = 0.0;
@@ -712,55 +1474,228 @@
         }
         [self setBounds:newBounds];
     }
-
 }
 
-- (NSData *)boundsAsQDRect {
-    return [NSData dataWithRectAsQDRect:[self bounds]];
+- (NSColor *)scriptingInteriorColor {
+    return [self interiorColor];
 }
 
-- (NSColor *)scriptingInteriorColor {
-    return nil;
+- (void)setScriptingInteriorColor:(NSColor *)color {
+    if ([self isEditable] && [self hasInteriorColor]) {
+        [self setInteriorColor:color];
+    }
 }
 
 - (NSString *)fontName {
-    return nil;
+    if ([[self type] isEqualToString:SKNFreeTextString]) {
+        return [[self font] fontName];
+    } else {
+        return nil;
+    }
 }
 
+- (void)setFontName:(NSString *)fontName {
+    if ([self isEditable] && [[self type] isEqualToString:SKNFreeTextString]) {
+        NSFont *font = [NSFont fontWithName:fontName size:[[self font] 
pointSize]];
+        if (font)
+            [self setFont:font];
+    }
+}
+
 - (CGFloat)fontSize {
-    return 0;
+    if ([[self type] isEqualToString:SKNFreeTextString]) {
+        return [[self font] pointSize];
+    } else {
+        return 0.0;
+    }
 }
 
+- (void)setFontSize:(CGFloat)pointSize {
+    if ([self isEditable] && [[self type] isEqualToString:SKNFreeTextString]) {
+        NSFont *font = [NSFont fontWithName:[[self font] fontName] 
size:pointSize];
+        if (font)
+            [self setFont:font];
+    }
+}
+
 - (NSColor *)scriptingFontColor {
-    return nil;
+    if ([[self type] isEqualToString:SKNFreeTextString]) {
+        return [self fontColor];
+    } else {
+        return nil;
+    }
 }
 
+- (void)setScriptingFontColor:(NSColor *)newScriptingFontColor {
+    if ([self isEditable] && [[self type] isEqualToString:SKNFreeTextString]) {
+        [self setFontColor:newScriptingFontColor];
+    }
+}
+
 - (NSInteger)scriptingAlignment {
-    return NSTextAlignmentLeft;
+    if ([[self type] isEqualToString:SKNFreeTextString]) {
+        return alignmentFromTextAlignment([self alignment]);
+    } else {
+        return NSTextAlignmentLeft;
+    }
 }
 
+- (void)setScriptingAlignment:(NSInteger)alignment {
+    if ([self isEditable] && [[self type] isEqualToString:SKNFreeTextString]) {
+        [self setAlignment:textAlignmentFromAlignment(alignment)];
+    }
+}
+
 - (NSData *)startPointAsQDPoint {
-    return nil;
+    if ([[self type] isEqualToString:SKNLineString]) {
+        NSRect bounds = [self bounds];
+        NSPoint startPoint = SKAddPoints([self startPoint], bounds.origin);
+        startPoint.x = floor(startPoint.x);
+        startPoint.y = floor(startPoint.y);
+        return [NSData dataWithPointAsQDPoint:startPoint];
+    } else {
+        return nil;
+    }
 }
 
+- (void)setStartPointAsQDPoint:(NSData *)inQDPointAsData {
+    if ([self isEditable] && [[self type] isEqualToString:SKNLineString] && 
inQDPointAsData && [inQDPointAsData isEqual:[NSNull null]] == NO) {
+        NSPoint startPoint = [inQDPointAsData pointValueAsQDPoint];
+        
+        NSRect bounds = [self bounds];
+        NSPoint endPoint = SKIntegralPoint(SKAddPoints([self endPoint], 
bounds.origin));
+        
+        bounds = SKIntegralRectFromPoints(startPoint, endPoint);
+        
+        if (NSWidth(bounds) < 8.0) {
+            bounds.size.width = 8.0;
+            bounds.origin.x = floor(0.5 * (startPoint.x + endPoint.x) - 4.0);
+        }
+        if (NSHeight(bounds) < 8.0) {
+            bounds.size.height = 8.0;
+            bounds.origin.y = floor(0.5 * (startPoint.y + endPoint.y) - 4.0);
+        }
+        
+        startPoint = SKSubstractPoints(startPoint, bounds.origin);
+        endPoint = SKSubstractPoints(endPoint, bounds.origin);
+        
+        [self setBounds:bounds];
+        [self setStartPoint:startPoint];
+        [self setEndPoint:endPoint];
+    }
+}
+
 - (NSData *)endPointAsQDPoint {
-    return nil;
+    if ([[self type] isEqualToString:SKNLineString]) {
+        NSRect bounds = [self bounds];
+        NSPoint endPoint = SKAddPoints([self endPoint], bounds.origin);
+        endPoint.x = floor(endPoint.x);
+        endPoint.y = floor(endPoint.y);
+        return [NSData dataWithPointAsQDPoint:endPoint];
+    } else {
+        return nil;
+    }
 }
 
+- (void)setEndPointAsQDPoint:(NSData *)inQDPointAsData {
+    if ([self isEditable] && [[self type] isEqualToString:SKNLineString] && 
inQDPointAsData && [inQDPointAsData isEqual:[NSNull null]] == NO) {
+        NSPoint endPoint = [inQDPointAsData pointValueAsQDPoint];
+        
+        NSRect bounds = [self bounds];
+        NSPoint startPoint = SKIntegralPoint(SKAddPoints([self startPoint], 
bounds.origin));
+        
+        bounds = SKIntegralRectFromPoints(startPoint, endPoint);
+        
+        if (NSWidth(bounds) < 8.0) {
+            bounds.size.width = 8.0;
+            bounds.origin.x = floor(0.5 * (startPoint.x + endPoint.x) - 4.0);
+        }
+        if (NSHeight(bounds) < 8.0) {
+            bounds.size.height = 8.0;
+            bounds.origin.y = floor(0.5 * (startPoint.y + endPoint.y) - 4.0);
+        }
+        
+        startPoint = SKSubstractPoints(startPoint, bounds.origin);
+        endPoint = SKSubstractPoints(endPoint, bounds.origin);
+        
+        [self setBounds:bounds];
+        [self setStartPoint:startPoint];
+        [self setEndPoint:endPoint];
+    }
+}
+
 - (PDFLineStyle)scriptingStartLineStyle {
-    return kPDFLineStyleNone;
+    if ([[self type] isEqualToString:SKNLineString]) {
+        return [self startLineStyle];
+    } else {
+        return kPDFLineStyleNone;
+    }
 }
 
+- (void)setScriptingStartLineStyle:(PDFLineStyle)style {
+    if ([self isEditable] && [[self type] isEqualToString:SKNLineString]) {
+        [self setStartLineStyle:style];
+    }
+}
+
 - (PDFLineStyle)scriptingEndLineStyle {
-    return kPDFLineStyleNone;
+    if ([[self type] isEqualToString:SKNLineString]) {
+        return [self endLineStyle];
+    } else {
+        return kPDFLineStyleNone;
+    }
 }
 
+- (void)setScriptingEndLineStyle:(PDFLineStyle)style {
+    if ([self isEditable] && [[self type] isEqualToString:SKNLineString]) {
+        [self setEndLineStyle:style];
+    }
+}
+
 - (id)selectionSpecifier {
-    return nil;
+    if ([self isMarkup]) {
+        PDFSelection *sel = [self selection];
+        return [sel hasCharacters] ? [sel objectSpecifiers] : @[];
+    } else {
+        return nil;
+    }
 }
 
 - (NSArray *)scriptingPointLists {
-    return nil;
+    if ([[self type] isEqualToString:SKNInkString]) {
+        NSPoint origin = [self bounds].origin;
+        NSMutableArray *pointLists = [NSMutableArray array];
+        NSMutableArray *pointValues;
+        NSPoint point;
+        NSInteger i, iMax;
+        for (NSBezierPath *path in [self paths]) {
+            iMax = [path elementCount];
+            pointValues = [[NSMutableArray alloc] initWithCapacity:iMax];
+            for (i = 0; i < iMax; i++) {
+                point = [path associatedPointForElementAtIndex:i];
+                [pointValues addObject:[NSData 
dataWithPointAsNSPoint:SKAddPoints(point, origin)]];
+            }
+            [pointLists addObject:pointValues];
+        }
+        return pointLists;
+    } else if ([self isMarkup]) {
+        NSPoint origin = [self bounds].origin;
+        NSMutableArray *pointLists = [NSMutableArray array];
+        NSMutableArray *pointValues;
+        NSPoint point;
+        NSInteger i, j, iMax = [[self quadrilateralPoints] count] / 4;
+        for (i = 0; i < iMax; i++) {
+            pointValues = [[NSMutableArray alloc] initWithCapacity:iMax];
+            for (j = 0; j < 4; j++) {
+                point = [[[self quadrilateralPoints] objectAtIndex:4 * i + j] 
pointValue];
+                [pointValues addObject:[NSData 
dataWithPointAsNSPoint:SKAddPoints(point, origin)]];
+            }
+            [pointLists addObject:pointValues];
+        }
+        return pointLists;
+    } else {
+        return nil;
+    }
 }
 
 - (SKPDFView *)containingPdfView {

Modified: trunk/SKMainDocument.m
===================================================================
--- trunk/SKMainDocument.m      2026-09-24 08:24:03 UTC (rev 16537)
+++ trunk/SKMainDocument.m      2026-09-26 21:41:10 UTC (rev 16538)
@@ -71,7 +71,6 @@
 #import "NSDocument_SKExtensions.h"
 #import "SKApplication.h"
 #import "SKTextFieldSheetController.h"
-#import "PDFAnnotationMarkup_SKExtensions.h"
 #import "NSWindowController_SKExtensions.h"
 #import "SKSyncPreferences.h"
 #import "NSScreen_SKExtensions.h"

Modified: trunk/SKNPDFAnnotationNote_SKExtensions.m
===================================================================
--- trunk/SKNPDFAnnotationNote_SKExtensions.m   2026-09-24 08:24:03 UTC (rev 
16537)
+++ trunk/SKNPDFAnnotationNote_SKExtensions.m   2026-09-26 21:41:10 UTC (rev 
16538)
@@ -54,9 +54,8 @@
 NSString * const SKPDFAnnotationScriptingImageDataKey = @"scriptingImageData";
 
 @interface SKNPDFAnnotationNote (SKPrivateDeclarations)
-- (NSTextStorage *)mutableText;
-- (NSArray *)texts;
-- (void)setTexts:(NSArray *)texts;
+@property (nonatomic, readonly) NSTextStorage *mutableText;
+@property (nonatomic, strong, nullable) NSArray *texts;
 @end
 
 @implementation SKNPDFAnnotationNote (SKExtensions)
@@ -138,40 +137,8 @@
 
 - (NSString *)colorDefaultKey { return SKAnchoredNoteColorKey; }
 
-- (NSSet *)keysForValuesToObserveForUndo {
-    static NSSet *noteKeys = nil;
-    if (noteKeys == nil) {
-        NSMutableSet *mutableKeys = [[super keysForValuesToObserveForUndo] 
mutableCopy];
-        [mutableKeys removeObject:SKNPDFAnnotationBorderKey];
-        [mutableKeys addObject:SKNPDFAnnotationNameKey];
-        [mutableKeys addObject:SKNPDFAnnotationTextKey];
-        [mutableKeys addObject:SKNPDFAnnotationImageKey];
-        [mutableKeys addObject:SKNPDFAnnotationDrawsImageKey];
-        noteKeys = [mutableKeys copy];
-    }
-    return noteKeys;
-}
-
 #pragma mark Scripting support
 
-+ (NSSet *)customScriptingKeys {
-    static NSSet *customNoteScriptingKeys = nil;
-    if (customNoteScriptingKeys == nil) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        NSMutableSet *customKeys = [[super customScriptingKeys] mutableCopy];
-#pragma clang diagnostic pop
-        [customKeys removeObject:SKNPDFAnnotationLineWidthKey];
-        [customKeys removeObject:SKNPDFAnnotationBorderStyleKey];
-        [customKeys removeObject:SKNPDFAnnotationDashPatternKey];
-        [customKeys addObject:SKPDFAnnotationScriptingIconTypeKey];
-        [customKeys addObject:SKPDFAnnotationRichTextKey];
-        [customKeys addObject:SKPDFAnnotationScriptingImageDataKey];
-        customNoteScriptingKeys = [customKeys copy];
-    }
-    return customNoteScriptingKeys;
-}
-
 - (id)richText {
     return [self mutableText];
 }

Modified: trunk/SKPDFView.m
===================================================================
--- trunk/SKPDFView.m   2026-09-24 08:24:03 UTC (rev 16537)
+++ trunk/SKPDFView.m   2026-09-26 21:41:10 UTC (rev 16538)
@@ -40,9 +40,6 @@
 #import "SKImageToolTipWindow.h"
 #import <SkimNotes/SkimNotes.h>
 #import "PDFAnnotation_SKExtensions.h"
-#import "PDFAnnotationMarkup_SKExtensions.h"
-#import "PDFAnnotationInk_SKExtensions.h"
-#import "PDFAnnotationLine_SKExtensions.h"
 #import "SKNPDFAnnotationNote_SKExtensions.h"
 #import "PDFPage_SKExtensions.h"
 #import "NSString_SKExtensions.h"

Modified: trunk/Skim.xcodeproj/project.pbxproj
===================================================================
--- trunk/Skim.xcodeproj/project.pbxproj        2026-09-24 08:24:03 UTC (rev 
16537)
+++ trunk/Skim.xcodeproj/project.pbxproj        2026-09-26 21:41:10 UTC (rev 
16538)
@@ -126,7 +126,6 @@
                CE454B3E226DEB3C0034FD6B /* SKNoteTableRowView.m in Sources */ 
= {isa = PBXBuildFile; fileRef = CE454B3D226DEB3C0034FD6B /* 
SKNoteTableRowView.m */; };
                CE454B51226E33150034FD6B /* SKHighlightingTableRowView.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CE454B50226E33150034FD6B /* 
SKHighlightingTableRowView.m */; };
                CE455394111DA4290060CAC9 /* SKImageToolTipContext.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = CE455393111DA4290060CAC9 /* 
SKImageToolTipContext.m */; };
-               CE4642E50DF5CBD900CFD8D2 /* PDFAnnotationText_SKExtensions.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CE4642E40DF5CBD900CFD8D2 /* 
PDFAnnotationText_SKExtensions.m */; };
                CE4643CF0DF6B5A400CFD8D2 /* SKJoinCommand.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CE4643CE0DF6B5A400CFD8D2 /* SKJoinCommand.m */; 
};
                CE4645910DF8140200CFD8D2 /* SKNumberArrayFormatter.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = CE4645900DF8140200CFD8D2 /* 
SKNumberArrayFormatter.m */; };
                CE48BAD80C089EA300A166C6 /* SKTemplateParser.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CE48BAD60C089EA300A166C6 /* SKTemplateParser.m 
*/; };
@@ -238,7 +237,6 @@
                CEC1B0602BBF03AB006786B0 /* SKPDFSyncParser.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CEC1B05F2BBF03AB006786B0 /* SKPDFSyncParser.m 
*/; };
                CEC29533275A66A2000F2D4C /* SKNotePrefs.m in Sources */ = {isa 
= PBXBuildFile; fileRef = CEC29532275A66A2000F2D4C /* SKNotePrefs.m */; };
                CEC29536275A7D58000F2D4C /* SKPreferencesCommand.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = CEC29535275A7D58000F2D4C /* 
SKPreferencesCommand.m */; };
-               CEC3AD240E23EC0300F40B0B /* PDFAnnotationLink_SKExtensions.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CEC3AD230E23EC0300F40B0B /* 
PDFAnnotationLink_SKExtensions.m */; };
                CECB03D30DC7503A0000B16B /* SKGroupedSearchResult.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = CECB03D20DC7503A0000B16B /* 
SKGroupedSearchResult.m */; };
                CECDC4FF0C5966A80026AAEC /* NSImage_SKExtensions.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = CECDC4FD0C5966A80026AAEC /* 
NSImage_SKExtensions.m */; };
                CECE6C3F2188AE9A00F6179D /* SKSelectionCommand.m in Sources */ 
= {isa = PBXBuildFile; fileRef = CECE6C3E2188AE9A00F6179D /* 
SKSelectionCommand.m */; };
@@ -283,27 +281,17 @@
                CEE229390BFB7CE9002B746B /* ReleaseNotes.rtf in Resources */ = 
{isa = PBXBuildFile; fileRef = CE54AA8E0BBC037400008750 /* ReleaseNotes.rtf */; 
};
                CEE22EA30BFB8672002B746B /* displayline in Copy Files: Shared 
Support */ = {isa = PBXBuildFile; fileRef = CE1E2F120BDB86A10011D9DD /* 
displayline */; };
                CEE54D880DA2E37B0037169F /* PDFAnnotation_SKExtensions.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CEE54D870DA2E37B0037169F /* 
PDFAnnotation_SKExtensions.m */; };
-               CEE54D930DA2E5E10037169F /* PDFAnnotationCircle_SKExtensions.m 
in Sources */ = {isa = PBXBuildFile; fileRef = CEE54D920DA2E5E10037169F /* 
PDFAnnotationCircle_SKExtensions.m */; };
-               CEE54D980DA2E6FC0037169F /* PDFAnnotationSquare_SKExtensions.m 
in Sources */ = {isa = PBXBuildFile; fileRef = CEE54D970DA2E6FC0037169F /* 
PDFAnnotationSquare_SKExtensions.m */; };
-               CEE54D9C0DA2E7B30037169F /* PDFAnnotationLine_SKExtensions.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CEE54D9B0DA2E7B30037169F /* 
PDFAnnotationLine_SKExtensions.m */; };
-               CEE54DAE0DA2E8CD0037169F /* 
PDFAnnotationFreeText_SKExtensions.m in Sources */ = {isa = PBXBuildFile; 
fileRef = CEE54DAD0DA2E8CD0037169F /* PDFAnnotationFreeText_SKExtensions.m */; 
};
-               CEE54DB40DA2E99D0037169F /* PDFAnnotationMarkup_SKExtensions.m 
in Sources */ = {isa = PBXBuildFile; fileRef = CEE54DB30DA2E99D0037169F /* 
PDFAnnotationMarkup_SKExtensions.m */; };
                CEE54F6C0DA3FB060037169F /* SKMainToolbarController.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CEE54F6B0DA3FB060037169F /* 
SKMainToolbarController.m */; };
                CEE54F700DA3FBE00037169F /* NSSegmentedControl_SKExtensions.m 
in Sources */ = {isa = PBXBuildFile; fileRef = CEE54F6F0DA3FBE00037169F /* 
NSSegmentedControl_SKExtensions.m */; };
                CEE54F900DA3FE9A0037169F /* NSValueTransformer_SKExtensions.m 
in Sources */ = {isa = PBXBuildFile; fileRef = CEE54F8F0DA3FE9A0037169F /* 
NSValueTransformer_SKExtensions.m */; };
-               CEE7E76524426BFF0034690E /* 
PDFAnnotationTextWidget_SKExtensions.m in Sources */ = {isa = PBXBuildFile; 
fileRef = CEE7E76424426BFF0034690E /* PDFAnnotationTextWidget_SKExtensions.m 
*/; };
-               CEE7E77824426C180034690E /* 
PDFAnnotationButtonWidget_SKExtensions.m in Sources */ = {isa = PBXBuildFile; 
fileRef = CEE7E77724426C180034690E /* PDFAnnotationButtonWidget_SKExtensions.m 
*/; };
-               CEE7E77B24426C380034690E /* 
PDFAnnotationChoiceWidget_SKExtensions.m in Sources */ = {isa = PBXBuildFile; 
fileRef = CEE7E77A24426C380034690E /* PDFAnnotationChoiceWidget_SKExtensions.m 
*/; };
                CEE8DFC80E5C806400EFA97F /* SkimNotes.framework in Copy Files: 
Frameworks */ = {isa = PBXBuildFile; fileRef = CE7DC7320E09286500D6D76D /* 
SkimNotes.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
                CEE8DFC90E5C806400EFA97F /* Sparkle.framework in Copy Files: 
Frameworks */ = {isa = PBXBuildFile; fileRef = CE2BD8200BD4127A00A5F4DB /* 
Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
                CEE8DFCE0E5C809C00EFA97F /* SkimNotes.framework in Frameworks 
*/ = {isa = PBXBuildFile; fileRef = CE7DC7320E09286500D6D76D /* 
SkimNotes.framework */; };
                CEE8DFCF0E5C809C00EFA97F /* Sparkle.framework in Frameworks */ 
= {isa = PBXBuildFile; fileRef = CE2BD8200BD4127A00A5F4DB /* Sparkle.framework 
*/; };
                CEE9BC0814CDD98100262718 /* SKBookmarkSheetController.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CEE9BC0714CDD98100262718 /* 
SKBookmarkSheetController.m */; };
-               CEEA05D32CCD49F400D7417A /* PDFAnnotationStamp_SKExtensions.m 
in Sources */ = {isa = PBXBuildFile; fileRef = CEEA05D22CCD49F400D7417A /* 
PDFAnnotationStamp_SKExtensions.m */; };
                CEEC0A0A0DCB2594003DD9B6 /* SKMainWindowController_UI.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CEEC0A090DCB2594003DD9B6 /* 
SKMainWindowController_UI.m */; };
                CEECD61C12E9E30B00B9E35E /* NSError_SKExtensions.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = CEECD61B12E9E30B00B9E35E /* 
NSError_SKExtensions.m */; };
                CEED148C2709EE4D00A8C4AA /* SKBasePDFView.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CEED148B2709EE4D00A8C4AA /* SKBasePDFView.m */; 
};
-               CEEE7C520E7D3F2000B7B208 /* PDFAnnotationInk_SKExtensions.m in 
Sources */ = {isa = PBXBuildFile; fileRef = CEEE7C510E7D3F2000B7B208 /* 
PDFAnnotationInk_SKExtensions.m */; };
                CEF02AEA2C087F3A001C150A /* SKThumbnailStamp.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CEF02AE92C087F3A001C150A /* SKThumbnailStamp.m 
*/; };
                CEF60D6A114C0DA60074ACC4 /* TransitionSheet.strings in 
Resources */ = {isa = PBXBuildFile; fileRef = CEF60D40114C0DA60074ACC4 /* 
TransitionSheet.strings */; };
                CEF60D6C114C0DA60074ACC4 /* ScaleSheet.strings in Resources */ 
= {isa = PBXBuildFile; fileRef = CEF60D44114C0DA60074ACC4 /* ScaleSheet.strings 
*/; };
@@ -3102,7 +3090,6 @@
                                CE3A41580B790C56006B64D3 /* SKDragImageView.m 
in Sources */,
                                CE3A45530B7A04A4006B64D3 /* 
NSBezierPath_SKExtensions.m in Sources */,
                                CEBCA4C02868A93A00E6376E /* SKLine.m in Sources 
*/,
-                               CEEA05D32CCD49F400D7417A /* 
PDFAnnotationStamp_SKExtensions.m in Sources */,
                                CE4EBDDA0B7BF3B30091F228 /* SKSideWindow.m in 
Sources */,
                                CE2526362B3834E40084F43D /* 
NSToolbarItem_SKExtensions.m in Sources */,
                                CE38ECD30B8093B200A1B779 /* 
NSString_SKExtensions.m in Sources */,
@@ -3113,7 +3100,6 @@
                                CE820AEF21A04EB100AD34BE /* 
NSWindow_SKExtensions.m in Sources */,
                                CE2DE4EE0B85DB6300D0DA12 /* 
NSCursor_SKExtensions.m in Sources */,
                                CE2DE4FD0B85DBD400D0DA12 /* 
SKImageToolTipWindow.m in Sources */,
-                               CEE7E77B24426C380034690E /* 
PDFAnnotationChoiceWidget_SKExtensions.m in Sources */,
                                CE2DE50D0B85DC4000D0DA12 /* 
PDFPage_SKExtensions.m in Sources */,
                                CE2DEB1C0B8618DE00D0DA12 /* SKFindController.m 
in Sources */,
                                CE2DED6C0B86334900D0DA12 /* SKFieldEditor.m in 
Sources */,
@@ -3184,24 +3170,17 @@
                                CEA8FCD60D89C34A00E8A6F4 /* 
SKAnimatedBorderlessWindow.m in Sources */,
                                CEB4EC502D87409100CA01A1 /* 
SKNoteToolbarController.m in Sources */,
                                CEE54D880DA2E37B0037169F /* 
PDFAnnotation_SKExtensions.m in Sources */,
-                               CEE54D930DA2E5E10037169F /* 
PDFAnnotationCircle_SKExtensions.m in Sources */,
-                               CEE54D980DA2E6FC0037169F /* 
PDFAnnotationSquare_SKExtensions.m in Sources */,
                                CECE6C3F2188AE9A00F6179D /* 
SKSelectionCommand.m in Sources */,
-                               CEE54D9C0DA2E7B30037169F /* 
PDFAnnotationLine_SKExtensions.m in Sources */,
-                               CEE54DAE0DA2E8CD0037169F /* 
PDFAnnotationFreeText_SKExtensions.m in Sources */,
-                               CEE54DB40DA2E99D0037169F /* 
PDFAnnotationMarkup_SKExtensions.m in Sources */,
                                CE5CB23F2740329E00315060 /* 
SKChainedUndoManager.m in Sources */,
                                CEE54F6C0DA3FB060037169F /* 
SKMainToolbarController.m in Sources */,
                                CEE54F700DA3FBE00037169F /* 
NSSegmentedControl_SKExtensions.m in Sources */,
                                CEE54F900DA3FE9A0037169F /* 
NSValueTransformer_SKExtensions.m in Sources */,
                                CECF61FF0DB258D600587D96 /* SKFontWell.m in 
Sources */,
-                               CEE7E77824426C180034690E /* 
PDFAnnotationButtonWidget_SKExtensions.m in Sources */,
                                CEE176E40DBD5B0C00E6C317 /* 
PDFDocumentView_SKExtensions.m in Sources */,
                                CECB03D30DC7503A0000B16B /* 
SKGroupedSearchResult.m in Sources */,
                                CEEC0A0A0DCB2594003DD9B6 /* 
SKMainWindowController_UI.m in Sources */,
                                CE7F43910DE1F1980061A839 /* 
NSUserDefaults_SKExtensions.m in Sources */,
                                CE0ECD1C0DE73604006EEDDB /* 
NSDocument_SKExtensions.m in Sources */,
-                               CE4642E50DF5CBD900CFD8D2 /* 
PDFAnnotationText_SKExtensions.m in Sources */,
                                CE4643CF0DF6B5A400CFD8D2 /* SKJoinCommand.m in 
Sources */,
                                CE4645910DF8140200CFD8D2 /* 
SKNumberArrayFormatter.m in Sources */,
                                CE34FFA80DFF58FB00A7FFE6 /* 
NSEvent_SKExtensions.m in Sources */,
@@ -3210,12 +3189,10 @@
                                CE08EBF5218C5DCD00D2DFCC /* 
NSPasteboard_SKExtensions.m in Sources */,
                                CEDC7B1A2913CD2500032269 /* SKLoupeController.m 
in Sources */,
                                CE3401E60E01388700A7FFE6 /* 
NSNumber_SKExtensions.m in Sources */,
-                               CEC3AD240E23EC0300F40B0B /* 
PDFAnnotationLink_SKExtensions.m in Sources */,
                                CE3364310E2761E9005F99E6 /* synctex_parser.c in 
Sources */,
                                CE3366DF0E28BCFA005F99E6 /* SKPDFSyncRecord.m 
in Sources */,
                                CEC29536275A7D58000F2D4C /* 
SKPreferencesCommand.m in Sources */,
                                CE09FC3C0E3886C100BDF413 /* SKRuntime.m in 
Sources */,
-                               CEEE7C520E7D3F2000B7B208 /* 
PDFAnnotationInk_SKExtensions.m in Sources */,
                                CE05A7380E9024ED0060BB07 /* 
SKPresentationOptionsSheetController.m in Sources */,
                                CEDE68E5201FDCB5000D881A /* SKKeychain.m in 
Sources */,
                                CE05A86F0E90ED950060BB07 /* 
SKTextFieldSheetController.m in Sources */,
@@ -3223,7 +3200,6 @@
                                CE7611650EA49D1400301E45 /* SKPrintableView.m 
in Sources */,
                                CE19E7A9275B7BC1007EBD8B /* SKDisplayPrefs.m in 
Sources */,
                                CE32531F0F4723EA0021BADD /* 
SKMainWindowController_Actions.m in Sources */,
-                               CEE7E76524426BFF0034690E /* 
PDFAnnotationTextWidget_SKExtensions.m in Sources */,
                                CE9B804A1030642400EA8774 /* SKTransitionInfo.m 
in Sources */,
                                CEA2045F1050233E008E082B /* 
SKPrintAccessoryController.m in Sources */,
                                CE5BAF4410511A0F00161B87 /* 
PDFOutline_SKExtensions.m in Sources */,
@@ -3480,7 +3456,7 @@
                                CE157ED512D4EBC000515B85 /* ja */,
                                CE1632AC1582AC1300CFF419 /* zh_CN */,
                                CE0E84EF114D521F00E37F38 /* zh_TW */,
-x                      );
+                       );
                        name = DisplayPreferences.strings;
                        sourceTree = "<group>";
                };

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit

Reply via email to