Release v0.3
This commit is contained in:
@@ -3,15 +3,22 @@ set -euo pipefail
|
||||
|
||||
APP_NAME="I Hate PDFs"
|
||||
EXECUTABLE_NAME="IHatePDFs"
|
||||
APP_VERSION="${APP_VERSION:-0.2.0}"
|
||||
BUILD_NUMBER="${BUILD_NUMBER:-2}"
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/release-version.sh"
|
||||
CONFIGURATION="${CONFIGURATION:-release}"
|
||||
BUNDLE_ID="${BUNDLE_ID:-net.akkolli.ihatepdfs}"
|
||||
STRIP_RELEASE="${STRIP_RELEASE:-1}"
|
||||
SIGNING_IDENTITY="${SIGNING_IDENTITY:-}"
|
||||
ENTITLEMENTS_PATH="${ENTITLEMENTS_PATH:-}"
|
||||
PROVISIONING_PROFILE="${PROVISIONING_PROFILE:-}"
|
||||
CODESIGN_TIMESTAMP="${CODESIGN_TIMESTAMP:-1}"
|
||||
CODESIGN_OPTIONS="${CODESIGN_OPTIONS:-}"
|
||||
PLISTBUDDY="/usr/libexec/PlistBuddy"
|
||||
if [[ -z "${ARCHS+x}" && "$CONFIGURATION" == "release" ]]; then
|
||||
ARCHS="arm64 x86_64"
|
||||
else
|
||||
ARCHS="${ARCHS:-}"
|
||||
fi
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
DIST_DIR="$ROOT_DIR/dist"
|
||||
APP_DIR="$DIST_DIR/$APP_NAME.app"
|
||||
CONTENTS_DIR="$APP_DIR/Contents"
|
||||
@@ -19,6 +26,29 @@ MACOS_DIR="$CONTENTS_DIR/MacOS"
|
||||
RESOURCES_DIR="$CONTENTS_DIR/Resources"
|
||||
ICON_SOURCE="$ROOT_DIR/ihatepdf.png"
|
||||
ICON_NAME="AppIcon"
|
||||
DERIVED_ENTITLEMENTS_PATH=""
|
||||
PROFILE_PLIST_PATH=""
|
||||
|
||||
cleanup() {
|
||||
if [[ -n "$DERIVED_ENTITLEMENTS_PATH" ]]; then
|
||||
rm -f "$DERIVED_ENTITLEMENTS_PATH"
|
||||
fi
|
||||
if [[ -n "$PROFILE_PLIST_PATH" ]]; then
|
||||
rm -f "$PROFILE_PLIST_PATH"
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
set_plist_string() {
|
||||
local plist="$1"
|
||||
local key="$2"
|
||||
local value="$3"
|
||||
|
||||
if "$PLISTBUDDY" -c "Set :$key $value" "$plist" >/dev/null 2>&1; then
|
||||
return
|
||||
fi
|
||||
"$PLISTBUDDY" -c "Add :$key string $value" "$plist"
|
||||
}
|
||||
|
||||
cd "$ROOT_DIR"
|
||||
SWIFT_BUILD_ARGS=(-c "$CONFIGURATION")
|
||||
@@ -26,13 +56,26 @@ for ARCH in $ARCHS; do
|
||||
SWIFT_BUILD_ARGS+=(--arch "$ARCH")
|
||||
done
|
||||
|
||||
swift build "${SWIFT_BUILD_ARGS[@]}"
|
||||
BUILD_DIR="$(swift build "${SWIFT_BUILD_ARGS[@]}" --show-bin-path)"
|
||||
swift build "${SWIFT_BUILD_ARGS[@]}"
|
||||
|
||||
rm -rf "$APP_DIR"
|
||||
mkdir -p "$MACOS_DIR" "$RESOURCES_DIR"
|
||||
cp "$BUILD_DIR/$EXECUTABLE_NAME" "$MACOS_DIR/$EXECUTABLE_NAME"
|
||||
|
||||
if [[ "$CONFIGURATION" == "release" && "$STRIP_RELEASE" != "0" ]]; then
|
||||
strip -x "$MACOS_DIR/$EXECUTABLE_NAME"
|
||||
fi
|
||||
|
||||
if [[ -n "$PROVISIONING_PROFILE" ]]; then
|
||||
if [[ ! -f "$PROVISIONING_PROFILE" ]]; then
|
||||
echo "Missing provisioning profile: $PROVISIONING_PROFILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
cp "$PROVISIONING_PROFILE" "$CONTENTS_DIR/embedded.provisionprofile"
|
||||
xattr -cr "$CONTENTS_DIR/embedded.provisionprofile" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
if [[ ! -f "$ICON_SOURCE" ]]; then
|
||||
echo "Missing app icon source: $ICON_SOURCE" >&2
|
||||
exit 1
|
||||
@@ -72,7 +115,7 @@ cat > "$CONTENTS_DIR/Info.plist" <<PLIST
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$EXECUTABLE_NAME</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.ihatepdfs.app</string>
|
||||
<string>$BUNDLE_ID</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
@@ -104,6 +147,8 @@ cat > "$CONTENTS_DIR/Info.plist" <<PLIST
|
||||
<string>$BUILD_NUMBER</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.productivity</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
@@ -116,4 +161,51 @@ cat > "$CONTENTS_DIR/Info.plist" <<PLIST
|
||||
</plist>
|
||||
PLIST
|
||||
|
||||
if [[ -n "$SIGNING_IDENTITY" ]]; then
|
||||
if [[ -n "$ENTITLEMENTS_PATH" && ! -f "$ENTITLEMENTS_PATH" ]]; then
|
||||
echo "Missing entitlements file: $ENTITLEMENTS_PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
APP_ENTITLEMENTS_PATH="$ENTITLEMENTS_PATH"
|
||||
if [[ -n "$PROVISIONING_PROFILE" ]]; then
|
||||
PROFILE_PLIST_PATH="$(mktemp "$DIST_DIR/profile.XXXXXX.plist")"
|
||||
security cms -D -i "$PROVISIONING_PROFILE" > "$PROFILE_PLIST_PATH"
|
||||
APP_IDENTIFIER="$("$PLISTBUDDY" -c "Print :Entitlements:com.apple.application-identifier" "$PROFILE_PLIST_PATH")"
|
||||
TEAM_IDENTIFIER="$("$PLISTBUDDY" -c "Print :Entitlements:com.apple.developer.team-identifier" "$PROFILE_PLIST_PATH")"
|
||||
|
||||
DERIVED_ENTITLEMENTS_PATH="$(mktemp "$DIST_DIR/entitlements.XXXXXX.plist")"
|
||||
if [[ -n "$ENTITLEMENTS_PATH" ]]; then
|
||||
cp "$ENTITLEMENTS_PATH" "$DERIVED_ENTITLEMENTS_PATH"
|
||||
else
|
||||
cat > "$DERIVED_ENTITLEMENTS_PATH" <<PLIST
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
</plist>
|
||||
PLIST
|
||||
fi
|
||||
|
||||
set_plist_string "$DERIVED_ENTITLEMENTS_PATH" "com.apple.application-identifier" "$APP_IDENTIFIER"
|
||||
set_plist_string "$DERIVED_ENTITLEMENTS_PATH" "com.apple.developer.team-identifier" "$TEAM_IDENTIFIER"
|
||||
APP_ENTITLEMENTS_PATH="$DERIVED_ENTITLEMENTS_PATH"
|
||||
fi
|
||||
|
||||
CODESIGN_ARGS=(--force --sign "$SIGNING_IDENTITY")
|
||||
if [[ "$CODESIGN_TIMESTAMP" != "0" ]]; then
|
||||
CODESIGN_ARGS+=(--timestamp)
|
||||
fi
|
||||
if [[ -n "$CODESIGN_OPTIONS" ]]; then
|
||||
CODESIGN_ARGS+=(--options "$CODESIGN_OPTIONS")
|
||||
fi
|
||||
if [[ -n "$APP_ENTITLEMENTS_PATH" ]]; then
|
||||
CODESIGN_ARGS+=(--entitlements "$APP_ENTITLEMENTS_PATH")
|
||||
fi
|
||||
|
||||
codesign "${CODESIGN_ARGS[@]}" "$APP_DIR"
|
||||
codesign --verify --strict --verbose=2 "$APP_DIR"
|
||||
fi
|
||||
|
||||
echo "Built $APP_DIR"
|
||||
du -sh "$APP_DIR" "$MACOS_DIR/$EXECUTABLE_NAME" "$RESOURCES_DIR/$ICON_NAME.icns"
|
||||
|
||||
69
scripts/make-app-store-pkg.sh
Executable file
69
scripts/make-app-store-pkg.sh
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/release-version.sh"
|
||||
|
||||
APP_NAME="I Hate PDFs"
|
||||
BUNDLE_ID="${BUNDLE_ID:-net.akkolli.ihatepdfs}"
|
||||
APP_SIGNING_IDENTITY="${APP_SIGNING_IDENTITY:-}"
|
||||
INSTALLER_SIGNING_IDENTITY="${INSTALLER_SIGNING_IDENTITY:-}"
|
||||
PROVISIONING_PROFILE="${PROVISIONING_PROFILE:-}"
|
||||
ENTITLEMENTS_PATH="${ENTITLEMENTS_PATH:-$ROOT_DIR/Signing/IHatePDFs-AppStore.entitlements}"
|
||||
DIST_DIR="$ROOT_DIR/dist"
|
||||
APP_DIR="$DIST_DIR/$APP_NAME.app"
|
||||
PKG_PATH="${PKG_PATH:-$DIST_DIR/IHatePDFs-v$RELEASE_VERSION-macos-appstore.pkg}"
|
||||
VALIDATE_WITH_ALTOOL="${VALIDATE_WITH_ALTOOL:-0}"
|
||||
|
||||
require_value() {
|
||||
local name="$1"
|
||||
local value="$2"
|
||||
local hint="$3"
|
||||
|
||||
if [[ -z "$value" ]]; then
|
||||
echo "Missing $name." >&2
|
||||
echo "$hint" >&2
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
require_value "APP_SIGNING_IDENTITY" "$APP_SIGNING_IDENTITY" \
|
||||
"Example: APP_SIGNING_IDENTITY=\"Apple Distribution: Your Name (TEAMID)\" or \"3rd Party Mac Developer Application: Your Name (TEAMID)\""
|
||||
require_value "INSTALLER_SIGNING_IDENTITY" "$INSTALLER_SIGNING_IDENTITY" \
|
||||
"Example: INSTALLER_SIGNING_IDENTITY=\"3rd Party Mac Developer Installer: Your Name (TEAMID)\""
|
||||
require_value "PROVISIONING_PROFILE" "$PROVISIONING_PROFILE" \
|
||||
"Download an App Store provisioning profile for $BUNDLE_ID and pass its local path."
|
||||
|
||||
mkdir -p "$DIST_DIR"
|
||||
|
||||
BUNDLE_ID="$BUNDLE_ID" \
|
||||
APP_VERSION="$APP_VERSION" \
|
||||
BUILD_NUMBER="$BUILD_NUMBER" \
|
||||
SIGNING_IDENTITY="$APP_SIGNING_IDENTITY" \
|
||||
ENTITLEMENTS_PATH="$ENTITLEMENTS_PATH" \
|
||||
PROVISIONING_PROFILE="$PROVISIONING_PROFILE" \
|
||||
"$ROOT_DIR/scripts/build-app.sh"
|
||||
|
||||
xattr -cr "$APP_DIR" 2>/dev/null || true
|
||||
rm -f "$PKG_PATH"
|
||||
productbuild \
|
||||
--component "$APP_DIR" /Applications \
|
||||
--sign "$INSTALLER_SIGNING_IDENTITY" \
|
||||
"$PKG_PATH"
|
||||
|
||||
pkgutil --check-signature "$PKG_PATH"
|
||||
|
||||
if [[ "$VALIDATE_WITH_ALTOOL" == "1" ]]; then
|
||||
require_value "ASC_USERNAME" "${ASC_USERNAME:-}" \
|
||||
"Set ASC_USERNAME to the Apple ID or App Store Connect API key issuer format expected by altool."
|
||||
require_value "ASC_PASSWORD" "${ASC_PASSWORD:-}" \
|
||||
"Set ASC_PASSWORD to an app-specific password or app-store-connect API key password."
|
||||
|
||||
xcrun altool --validate-app \
|
||||
--type macos \
|
||||
--file "$PKG_PATH" \
|
||||
--username "$ASC_USERNAME" \
|
||||
--password "$ASC_PASSWORD"
|
||||
fi
|
||||
|
||||
echo "Created App Store package: $PKG_PATH"
|
||||
@@ -2,14 +2,15 @@
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
source "$ROOT_DIR/scripts/release-version.sh"
|
||||
APP_NAME="I Hate PDFs"
|
||||
RELEASE_VERSION="${RELEASE_VERSION:-0.2}"
|
||||
DIST_DIR="$ROOT_DIR/dist"
|
||||
APP_DIR="$DIST_DIR/$APP_NAME.app"
|
||||
DMG_PATH="$DIST_DIR/IHatePDFs-v$RELEASE_VERSION-macos.dmg"
|
||||
BUILD_APP="${BUILD_APP:-1}"
|
||||
|
||||
if [[ ! -d "$APP_DIR" ]]; then
|
||||
"$ROOT_DIR/scripts/build-app.sh"
|
||||
if [[ "$BUILD_APP" != "0" || ! -d "$APP_DIR" ]]; then
|
||||
APP_VERSION="$APP_VERSION" BUILD_NUMBER="$BUILD_NUMBER" "$ROOT_DIR/scripts/build-app.sh"
|
||||
fi
|
||||
|
||||
rm -f "$DMG_PATH"
|
||||
|
||||
5
scripts/release-version.sh
Executable file
5
scripts/release-version.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
APP_VERSION="${APP_VERSION:-0.3.0}"
|
||||
BUILD_NUMBER="${BUILD_NUMBER:-4}"
|
||||
RELEASE_VERSION="${RELEASE_VERSION:-${APP_VERSION%.0}}"
|
||||
@@ -18,8 +18,9 @@ enum VerificationError: Error, CustomStringConvertible {
|
||||
case missingName(page: Int, index: Int, key: String)
|
||||
case missingString(page: Int, index: Int, key: String)
|
||||
case missingArray(page: Int, index: Int, key: String)
|
||||
case missingPopup(page: Int, index: Int, subtype: String)
|
||||
case missingPopupParent(page: Int, index: Int)
|
||||
case unexpectedMarkupPopup(page: Int, index: Int, subtype: String)
|
||||
case unexpectedPopupLink(page: Int, index: Int, subtype: String)
|
||||
case missingExpectedSubtype(String)
|
||||
|
||||
var description: String {
|
||||
@@ -36,10 +37,12 @@ enum VerificationError: Error, CustomStringConvertible {
|
||||
return "Annotation \(index) on page \(page) is missing string key /\(key)"
|
||||
case .missingArray(let page, let index, let key):
|
||||
return "Annotation \(index) on page \(page) is missing array key /\(key)"
|
||||
case .missingPopup(let page, let index, let subtype):
|
||||
return "\(subtype) annotation \(index) on page \(page) is missing a /Popup dictionary"
|
||||
case .missingPopupParent(let page, let index):
|
||||
return "Popup annotation \(index) on page \(page) is missing a /Parent dictionary"
|
||||
case .unexpectedMarkupPopup(let page, let index, let subtype):
|
||||
return "Popup annotation \(index) on page \(page) points at a /\(subtype) markup annotation; markup comments should export through /Contents"
|
||||
case .unexpectedPopupLink(let page, let index, let subtype):
|
||||
return "\(subtype) annotation \(index) on page \(page) should store comments in /Contents, not a /Popup link"
|
||||
case .missingExpectedSubtype(let subtype):
|
||||
return "Expected at least one /\(subtype) annotation"
|
||||
}
|
||||
@@ -85,7 +88,7 @@ for pageNumber in 1...document.numberOfPages {
|
||||
switch subtype {
|
||||
case "Highlight":
|
||||
try requireMarkupKeys(in: annotation, page: pageNumber, index: annotationIndex)
|
||||
try requirePopup(in: annotation, page: pageNumber, index: annotationIndex, subtype: "Highlight")
|
||||
try rejectPopupLink(in: annotation, subtype: subtype, page: pageNumber, index: annotationIndex)
|
||||
if hasString(in: annotation, key: "IHatePDFsKind") {
|
||||
try requireString(in: annotation, key: "IHatePDFsKind", page: pageNumber, index: annotationIndex)
|
||||
summary.selectedTextComments += 1
|
||||
@@ -95,7 +98,7 @@ for pageNumber in 1...document.numberOfPages {
|
||||
case "Underline":
|
||||
summary.underlines += 1
|
||||
try requireMarkupKeys(in: annotation, page: pageNumber, index: annotationIndex)
|
||||
try requirePopup(in: annotation, page: pageNumber, index: annotationIndex, subtype: "Underline")
|
||||
try rejectPopupLink(in: annotation, subtype: subtype, page: pageNumber, index: annotationIndex)
|
||||
case "Text":
|
||||
try requireTextKeys(in: annotation, page: pageNumber, index: annotationIndex)
|
||||
|
||||
@@ -104,7 +107,6 @@ for pageNumber in 1...document.numberOfPages {
|
||||
try requireString(in: annotation, key: "IRT", page: pageNumber, index: annotationIndex)
|
||||
try requireString(in: annotation, key: "RT", page: pageNumber, index: annotationIndex)
|
||||
} else {
|
||||
try requirePopup(in: annotation, page: pageNumber, index: annotationIndex, subtype: "Text")
|
||||
summary.textNotes += 1
|
||||
}
|
||||
case "FreeText":
|
||||
@@ -118,9 +120,24 @@ for pageNumber in 1...document.numberOfPages {
|
||||
case "Popup":
|
||||
summary.popups += 1
|
||||
var parentDictionary: CGPDFDictionaryRef?
|
||||
guard CGPDFDictionaryGetDictionary(annotation, "Parent", &parentDictionary) else {
|
||||
guard CGPDFDictionaryGetDictionary(annotation, "Parent", &parentDictionary),
|
||||
let parentDictionary
|
||||
else {
|
||||
throw VerificationError.missingPopupParent(page: pageNumber, index: annotationIndex)
|
||||
}
|
||||
let parentSubtype = try nameValue(
|
||||
in: parentDictionary,
|
||||
key: "Subtype",
|
||||
page: pageNumber,
|
||||
index: annotationIndex
|
||||
)
|
||||
if parentSubtype == "Highlight" || parentSubtype == "Underline" {
|
||||
throw VerificationError.unexpectedMarkupPopup(
|
||||
page: pageNumber,
|
||||
index: annotationIndex,
|
||||
subtype: parentSubtype
|
||||
)
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -145,10 +162,6 @@ guard summary.replies > 0 else {
|
||||
guard summary.freeText > 0 else {
|
||||
throw VerificationError.missingExpectedSubtype("FreeText")
|
||||
}
|
||||
guard summary.popups >= 4 else {
|
||||
throw VerificationError.missingExpectedSubtype("Popup")
|
||||
}
|
||||
|
||||
print("Verified raw PDF annotation dictionaries in \(inputURL.path): \(summary.highlights) highlight, \(summary.selectedTextComments) selected-text comment, \(summary.underlines) underline, \(summary.textNotes) text note, \(summary.replies) reply, \(summary.freeText) free-text, \(summary.popups) popups.")
|
||||
|
||||
func annotationDictionary(
|
||||
@@ -251,6 +264,20 @@ func requireMarkupKeys(
|
||||
try requireString(in: dictionary, key: "M", page: page, index: index)
|
||||
}
|
||||
|
||||
func rejectPopupLink(
|
||||
in dictionary: CGPDFDictionaryRef,
|
||||
subtype: String,
|
||||
page: Int,
|
||||
index: Int
|
||||
) throws {
|
||||
var popupDictionary: CGPDFDictionaryRef?
|
||||
guard CGPDFDictionaryGetDictionary(dictionary, "Popup", &popupDictionary) else {
|
||||
return
|
||||
}
|
||||
|
||||
throw VerificationError.unexpectedPopupLink(page: page, index: index, subtype: subtype)
|
||||
}
|
||||
|
||||
func requireTextKeys(
|
||||
in dictionary: CGPDFDictionaryRef,
|
||||
page: Int,
|
||||
@@ -262,22 +289,3 @@ func requireTextKeys(
|
||||
try requireString(in: dictionary, key: "T", page: page, index: index)
|
||||
try requireString(in: dictionary, key: "M", page: page, index: index)
|
||||
}
|
||||
|
||||
func requirePopup(
|
||||
in dictionary: CGPDFDictionaryRef,
|
||||
page: Int,
|
||||
index: Int,
|
||||
subtype: String
|
||||
) throws {
|
||||
var popupDictionary: CGPDFDictionaryRef?
|
||||
guard CGPDFDictionaryGetDictionary(dictionary, "Popup", &popupDictionary),
|
||||
let popupDictionary
|
||||
else {
|
||||
throw VerificationError.missingPopup(page: page, index: index, subtype: subtype)
|
||||
}
|
||||
|
||||
let popupSubtype = try nameValue(in: popupDictionary, key: "Subtype", page: page, index: index)
|
||||
guard popupSubtype == "Popup" else {
|
||||
throw VerificationError.missingPopup(page: page, index: index, subtype: subtype)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ standardize(
|
||||
author: "Professor"
|
||||
)
|
||||
page.addAnnotation(highlight)
|
||||
addPopup(for: highlight, bounds: CGRect(x: 352, y: 592, width: 240, height: 110))
|
||||
|
||||
let selectedTextComment = PDFAnnotation(
|
||||
bounds: CGRect(x: 72, y: 594, width: 260, height: 22),
|
||||
@@ -42,12 +41,11 @@ selectedTextComment.quadrilateralPoints = quadPoints(width: 260, height: 22)
|
||||
standardize(
|
||||
selectedTextComment,
|
||||
name: "verify-selected-text-comment",
|
||||
contents: "This selected-text comment is saved as standard PDF markup with popup contents.",
|
||||
contents: "This selected-text comment is saved as standard parent annotation contents.",
|
||||
author: "Professor"
|
||||
)
|
||||
_ = selectedTextComment.setValue("Comment", forAnnotationKey: PDFAnnotationKey(rawValue: "IHatePDFsKind"))
|
||||
page.addAnnotation(selectedTextComment)
|
||||
addPopup(for: selectedTextComment, bounds: CGRect(x: 352, y: 472, width: 240, height: 110))
|
||||
|
||||
let underline = PDFAnnotation(
|
||||
bounds: CGRect(x: 72, y: 570, width: 260, height: 24),
|
||||
@@ -64,7 +62,6 @@ standardize(
|
||||
author: "Professor"
|
||||
)
|
||||
page.addAnnotation(underline)
|
||||
addPopup(for: underline, bounds: CGRect(x: 352, y: 540, width: 240, height: 110))
|
||||
|
||||
let textNote = PDFAnnotation(
|
||||
bounds: CGRect(x: 360, y: 620, width: 28, height: 28),
|
||||
@@ -153,18 +150,6 @@ func standardize(
|
||||
_ = annotation.setValue("Unmarked", forAnnotationKey: PDFAnnotationKey(rawValue: "State"))
|
||||
}
|
||||
|
||||
func addPopup(for annotation: PDFAnnotation, bounds: CGRect) {
|
||||
let popup = PDFAnnotation(bounds: bounds, forType: .popup, withProperties: nil)
|
||||
popup.contents = annotation.contents
|
||||
popup.userName = annotation.userName
|
||||
popup.modificationDate = annotation.modificationDate
|
||||
popup.isOpen = false
|
||||
popup.shouldDisplay = true
|
||||
popup.shouldPrint = true
|
||||
annotation.popup = popup
|
||||
page.addAnnotation(popup)
|
||||
}
|
||||
|
||||
func quadPoints(width: CGFloat, height: CGFloat) -> [NSValue] {
|
||||
[
|
||||
NSValue(point: CGPoint(x: 0, y: height)),
|
||||
|
||||
Reference in New Issue
Block a user