@swiftbrowser/swift 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Package.swift +200 -9
- package/README.md +7 -9
- package/Sources/AVFoundation/AVFoundation.swift +131 -0
- package/Sources/AVFoundation/Asset.swift +487 -0
- package/Sources/AVFoundation/AudioSession.swift +144 -0
- package/Sources/AVFoundation/CMTime.swift +303 -0
- package/Sources/AVFoundation/Capture.swift +688 -0
- package/Sources/AVFoundation/Player.swift +749 -0
- package/Sources/AVFoundation/PlayerView.swift +117 -0
- package/Sources/AVKit/AVKit.swift +132 -0
- package/Sources/Accelerate/Accelerate.swift +122 -0
- package/Sources/AppIntents/AppIntents.swift +144 -0
- package/Sources/AppIntents/Parameters.swift +220 -0
- package/Sources/AppIntents/Shortcuts.swift +159 -0
- package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
- package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
- package/Sources/AuthenticationServices/Authorization.swift +251 -0
- package/Sources/Charts/Charts.swift +0 -4
- package/Sources/Combine/AnyCancellable.swift +65 -0
- package/Sources/Combine/AnyPublisher.swift +148 -0
- package/Sources/Combine/AnySubscriber.swift +230 -0
- package/Sources/Combine/Cancellable.swift +35 -0
- package/Sources/Combine/Codable.swift +29 -0
- package/Sources/Combine/CombineIdentifier.swift +45 -0
- package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
- package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
- package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
- package/Sources/Combine/CurrentValueSubject.swift +252 -0
- package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
- package/Sources/Combine/Future.swift +228 -0
- package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
- package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
- package/Sources/Combine/Helpers/ConduitList.swift +59 -0
- package/Sources/Combine/Helpers/DebugHook.swift +177 -0
- package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
- package/Sources/Combine/Helpers/Locking.swift +30 -0
- package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
- package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
- package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
- package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
- package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
- package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
- package/Sources/Combine/Helpers/Utils.swift +30 -0
- package/Sources/Combine/Helpers/Violations.swift +33 -0
- package/Sources/Combine/ImmediateScheduler.swift +178 -0
- package/Sources/Combine/LICENSE +21 -0
- package/Sources/Combine/NotificationPublisher.swift +48 -0
- package/Sources/Combine/ObjectWillChange.swift +46 -0
- package/Sources/Combine/PassthroughSubject.swift +222 -0
- package/Sources/Combine/Publisher+Subscribe.swift +53 -0
- package/Sources/Combine/Publishers/Deferred.swift +48 -0
- package/Sources/Combine/Publishers/Empty.swift +54 -0
- package/Sources/Combine/Publishers/Fail.swift +42 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
- package/Sources/Combine/Publishers/Just.swift +313 -0
- package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
- package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
- package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
- package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
- package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
- package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
- package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
- package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
- package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
- package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
- package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
- package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
- package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
- package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
- package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
- package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
- package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
- package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
- package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
- package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
- package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
- package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
- package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
- package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
- package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
- package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
- package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
- package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
- package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
- package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
- package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
- package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
- package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
- package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
- package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
- package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
- package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
- package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
- package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
- package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
- package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
- package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
- package/Sources/Combine/Publishers/Publishers.swift +13 -0
- package/Sources/Combine/Publishers/Record.swift +237 -0
- package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
- package/Sources/Combine/Result.swift +46 -0
- package/Sources/Combine/Scheduler.swift +89 -0
- package/Sources/Combine/Schedulers.swift +211 -0
- package/Sources/Combine/Subject+Void.swift +17 -0
- package/Sources/Combine/Subscriber+Void.swift +20 -0
- package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
- package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
- package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
- package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
- package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
- package/Sources/Combine/Subscription.swift +22 -0
- package/Sources/Combine/Subscriptions.swift +42 -0
- package/Sources/Combine/SwiftUIObservation.swift +10 -0
- package/Sources/Combine/_Introspection.swift +107 -0
- package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
- package/Sources/Compression/Compression.swift +365 -0
- package/Sources/Compression/Deflate.swift +407 -0
- package/Sources/Compression/Zlib.swift +179 -0
- package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
- package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
- package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
- package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
- package/Sources/CoreImage/CIColor.swift +41 -0
- package/Sources/CoreImage/CIContext.swift +31 -0
- package/Sources/CoreImage/CIDetector.swift +57 -0
- package/Sources/CoreImage/CIFilter.swift +243 -0
- package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
- package/Sources/CoreImage/CIImage.swift +162 -0
- package/Sources/CoreImage/QRCode.swift +393 -0
- package/Sources/CoreLocation/Coordinate.swift +30 -0
- package/Sources/CoreLocation/Location.swift +65 -0
- package/Sources/CoreML/Evaluation.swift +414 -0
- package/Sources/CoreML/FeatureValue.swift +266 -0
- package/Sources/CoreML/Model.swift +269 -0
- package/Sources/CoreML/MultiArray.swift +92 -0
- package/Sources/CoreML/Specification.swift +233 -0
- package/Sources/CoreText/CoreText.swift +64 -0
- package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
- package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
- package/Sources/CryptoKit/CryptoKit.swift +375 -0
- package/Sources/CryptoKit/Curve25519.swift +317 -0
- package/Sources/CryptoKit/P256.swift +321 -0
- package/Sources/FoundationBridge/AppStorage.swift +165 -0
- package/Sources/FoundationBridge/AssetResources.swift +90 -0
- package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
- package/Sources/FoundationBridge/AsyncImage.swift +116 -0
- package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
- package/Sources/{_FoundationCommon → FoundationBridge}/Bundle.swift +41 -4
- package/Sources/FoundationBridge/CombineExports.swift +8 -0
- package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
- package/Sources/FoundationBridge/Dispatch.swift +458 -0
- package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
- package/Sources/FoundationBridge/FileImporter.swift +128 -0
- package/Sources/FoundationBridge/FileSystem.swift +68 -0
- package/Sources/FoundationBridge/FoundationBridge.swift +24 -72
- package/Sources/FoundationBridge/HostResolution.swift +31 -0
- package/Sources/FoundationBridge/ItemProvider.swift +655 -0
- package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
- package/Sources/FoundationBridge/Links.swift +127 -0
- package/Sources/FoundationBridge/ListFormatter.swift +32 -0
- package/Sources/FoundationBridge/Localization.swift +149 -0
- package/Sources/FoundationBridge/Locks.swift +50 -0
- package/Sources/FoundationBridge/Markdown.swift +527 -0
- package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
- package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
- package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
- package/Sources/FoundationBridge/Operation.swift +195 -0
- package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
- package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
- package/Sources/FoundationBridge/SceneStorage.swift +78 -0
- package/Sources/FoundationBridge/SecurityExports.swift +8 -0
- package/Sources/FoundationBridge/Selector.swift +226 -0
- package/Sources/FoundationBridge/StringComparators.swift +17 -0
- package/Sources/FoundationBridge/Table.swift +211 -0
- package/Sources/FoundationBridge/TextAttributes.swift +42 -0
- package/Sources/FoundationBridge/Timer.swift +6 -1
- package/Sources/FoundationBridge/URLSession.swift +718 -0
- package/Sources/{_FoundationCommon → FoundationBridge}/UserDefaults.swift +17 -4
- package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
- package/Sources/FoundationBridge/WebSocket.swift +187 -0
- package/Sources/FoundationModels/FoundationModels.swift +1098 -0
- package/Sources/ImageIO/GIF.swift +72 -0
- package/Sources/ImageIO/ImageIO.swift +248 -0
- package/Sources/ImageIO/ImageTypes.swift +28 -0
- package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
- package/Sources/LocalAuthentication/LAContext.swift +86 -0
- package/Sources/MapKit/Geometry.swift +223 -0
- package/Sources/MapKit/Map.swift +638 -0
- package/Sources/MapKit/MapView.swift +229 -0
- package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
- package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
- package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
- package/Sources/OSLog/OSLog.swift +6 -0
- package/Sources/Photos/Photos.swift +572 -0
- package/Sources/PhotosUI/PhotosPicker.swift +248 -0
- package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
- package/Sources/QuickLook/QuickLook.swift +168 -0
- package/Sources/SafariServices/SafariServices.swift +106 -0
- package/Sources/Security/Security.swift +332 -0
- package/Sources/StoreKit/AppStore.swift +207 -0
- package/Sources/StoreKit/Products.swift +280 -0
- package/Sources/StoreKit/RequestReview.swift +28 -0
- package/Sources/StoreKit/StoreKit1.swift +486 -0
- package/Sources/StoreKit/StoreViews.swift +428 -0
- package/Sources/StoreKit/Transactions.swift +197 -0
- package/Sources/SwiftData/Macros.swift +58 -0
- package/Sources/SwiftData/ModelActor.swift +38 -0
- package/Sources/SwiftData/ModelContainer.swift +129 -0
- package/Sources/SwiftData/ModelContext.swift +451 -0
- package/Sources/SwiftData/PersistentModel.swift +238 -0
- package/Sources/SwiftData/Properties.swift +261 -0
- package/Sources/SwiftData/Query.swift +256 -0
- package/Sources/SwiftData/Schema.swift +192 -0
- package/Sources/SwiftData/Store.swift +146 -0
- package/Sources/SwiftData/StringPredicates.swift +125 -0
- package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
- package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
- package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
- package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
- package/Sources/SwiftDataMacros/Plugin.swift +18 -0
- package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
- package/Sources/SwiftUI/API/Accessibility.swift +55 -6
- package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
- package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
- package/Sources/SwiftUI/API/Alert.swift +1 -1
- package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
- package/Sources/SwiftUI/API/Animation.swift +37 -5
- package/Sources/SwiftUI/API/App.swift +31 -1
- package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
- package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
- package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
- package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
- package/Sources/SwiftUI/API/Canvas.swift +337 -0
- package/Sources/SwiftUI/API/Color.swift +104 -28
- package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
- package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
- package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
- package/Sources/SwiftUI/API/Commands.swift +106 -0
- package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
- package/Sources/SwiftUI/API/ContentShape.swift +33 -0
- package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
- package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
- package/Sources/SwiftUI/API/Controls.swift +59 -27
- package/Sources/SwiftUI/API/CustomLayout.swift +49 -10
- package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
- package/Sources/SwiftUI/API/Decorations.swift +1 -1
- package/Sources/SwiftUI/API/EditMode.swift +25 -82
- package/Sources/SwiftUI/API/Effects.swift +105 -7
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +93 -9
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +11 -3
- package/Sources/SwiftUI/API/Gauge.swift +3 -2
- package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
- package/Sources/SwiftUI/API/GeometryReader.swift +13 -2
- package/Sources/SwiftUI/API/GestureState.swift +65 -0
- package/Sources/SwiftUI/API/Gestures.swift +1 -1
- package/Sources/SwiftUI/API/Glass.swift +127 -0
- package/Sources/SwiftUI/API/Grid.swift +1 -1
- package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
- package/Sources/SwiftUI/API/KeyPress.swift +54 -0
- package/Sources/SwiftUI/API/LabelStyle.swift +13 -6
- package/Sources/SwiftUI/API/Layout.swift +67 -12
- package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
- package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
- package/Sources/SwiftUI/API/Lists.swift +61 -6
- package/Sources/SwiftUI/API/Menu.swift +8 -1
- package/Sources/SwiftUI/API/Modifiers.swift +80 -10
- package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
- package/Sources/SwiftUI/API/Namespace.swift +44 -0
- package/Sources/SwiftUI/API/Navigation.swift +24 -9
- package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
- package/Sources/SwiftUI/API/ObservableObject.swift +16 -2
- package/Sources/SwiftUI/API/Path.swift +543 -0
- package/Sources/SwiftUI/API/Phase8Controls.swift +48 -31
- package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
- package/Sources/SwiftUI/API/Picker.swift +11 -2
- package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
- package/Sources/SwiftUI/API/Popover.swift +41 -0
- package/Sources/SwiftUI/API/Preferences.swift +262 -0
- package/Sources/SwiftUI/API/Presentation.swift +17 -4
- package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
- package/Sources/SwiftUI/API/Primitives.swift +164 -37
- package/Sources/SwiftUI/API/Publishers.swift +4 -4
- package/Sources/SwiftUI/API/Redaction.swift +75 -0
- package/Sources/SwiftUI/API/RowActions.swift +3 -2
- package/Sources/SwiftUI/API/Scenes.swift +131 -0
- package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
- package/Sources/SwiftUI/API/ScrollTargets.swift +3 -3
- package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
- package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
- package/Sources/SwiftUI/API/Shape.swift +214 -0
- package/Sources/SwiftUI/API/ShapeStyle.swift +105 -7
- package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
- package/Sources/SwiftUI/API/Sharing.swift +193 -0
- package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
- package/Sources/SwiftUI/API/State.swift +18 -1
- package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
- package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
- package/Sources/SwiftUI/API/TabContent.swift +841 -0
- package/Sources/SwiftUI/API/Table.swift +382 -0
- package/Sources/SwiftUI/API/Tabs.swift +148 -4
- package/Sources/SwiftUI/API/Tasks.swift +2 -2
- package/Sources/SwiftUI/API/Text.swift +386 -0
- package/Sources/SwiftUI/API/TextDates.swift +61 -0
- package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
- package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
- package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
- package/Sources/SwiftUI/API/Toolbar.swift +52 -16
- package/Sources/SwiftUI/API/Transfer.swift +145 -0
- package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
- package/Sources/SwiftUI/API/Video.swift +64 -0
- package/Sources/SwiftUI/API/View.swift +10 -2
- package/Sources/SwiftUI/API/ViewModifier.swift +4 -1
- package/Sources/SwiftUI/API/VisualEffect.swift +74 -1
- package/Sources/SwiftUI/API/Windows.swift +25 -0
- package/Sources/SwiftUI/Charts/Axis.swift +7 -1
- package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
- package/Sources/SwiftUI/Charts/Chart.swift +17 -3
- package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
- package/Sources/SwiftUI/Localization/Localization.swift +498 -0
- package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
- package/Sources/SwiftUI/Runtime/Executor.swift +2 -0
- package/Sources/SwiftUI/Runtime/Exports.swift +37 -1
- package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
- package/Sources/SwiftUI/Runtime/JSON.swift +76 -4
- package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
- package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
- package/Sources/SwiftUI/Runtime/Ops.swift +58 -12
- package/Sources/SwiftUI/Runtime/Reconciler.swift +10 -1
- package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
- package/Sources/SwiftUI/Runtime/Runtime.swift +977 -198
- package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
- package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
- package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
- package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
- package/Sources/Symbols/Symbols.swift +25 -0
- package/Sources/Translation/Translation.swift +423 -0
- package/Sources/UIKit/Activity.swift +213 -0
- package/Sources/UIKit/Alerts.swift +69 -0
- package/Sources/UIKit/AppDelegate.swift +222 -0
- package/Sources/UIKit/Appearance.swift +84 -0
- package/Sources/UIKit/ColorConversions.swift +70 -0
- package/Sources/UIKit/Controls.swift +225 -0
- package/Sources/UIKit/Device.swift +200 -0
- package/Sources/UIKit/Feedback.swift +65 -0
- package/Sources/UIKit/Font.swift +307 -0
- package/Sources/UIKit/Graphics.swift +204 -0
- package/Sources/UIKit/HostingController.swift +185 -0
- package/Sources/UIKit/Identity.swift +24 -0
- package/Sources/UIKit/Introspectable.swift +510 -0
- package/Sources/UIKit/Pasteboard.swift +363 -0
- package/Sources/UIKit/PhotoAlbum.swift +81 -0
- package/Sources/UIKit/RemoteNotifications.swift +15 -0
- package/Sources/UIKit/Representable.swift +288 -0
- package/Sources/UIKit/SafeArea.swift +12 -0
- package/Sources/UIKit/SceneDelegates.swift +132 -0
- package/Sources/UIKit/Scenes.swift +40 -0
- package/Sources/UIKit/ScrollView.swift +157 -0
- package/Sources/UIKit/ShortcutItems.swift +67 -0
- package/Sources/UIKit/SymbolConfiguration.swift +124 -0
- package/Sources/UIKit/TargetAction.swift +123 -0
- package/Sources/UIKit/TextPaste.swift +161 -0
- package/Sources/UIKit/TextView.swift +538 -0
- package/Sources/UIKit/UIKit.swift +292 -0
- package/Sources/UIKit/UIView.swift +855 -0
- package/Sources/UIKit/ViewTranslation.swift +311 -0
- package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
- package/Sources/UserNotifications/Content.swift +370 -0
- package/Sources/UserNotifications/NotificationCenter.swift +309 -0
- package/Sources/WeatherKit/WeatherKit.swift +228 -0
- package/Sources/WebKit/WebKit.swift +245 -0
- package/Sources/os/os.swift +376 -0
- package/Sources/zlib/zlib.swift +6 -0
- package/index.d.ts +1 -1
- package/index.mjs +2 -2
- package/manifest.d.mts +2 -0
- package/manifest.mjs +39 -0
- package/package.json +5 -3
- package/sync-sources.mjs +21 -7
- package/Sources/FoundationLite/Common.swift +0 -3
- package/Sources/FoundationLite/FoundationLite.swift +0 -171
- package/Sources/FoundationLite/Interaction.swift +0 -146
- package/Sources/FoundationLite/Timer.swift +0 -48
- package/Sources/_FoundationCommon/_FoundationCommon.swift +0 -10
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
// `Path` and `CGAffineTransform`: the outline a custom `Shape` draws in
|
|
2
|
+
// `path(in:)` (Shape.swift), kept as SwiftUI's elements (moves, lines,
|
|
3
|
+
// quadratic and cubic curves, closes). Arcs, ellipses and rounded rectangles
|
|
4
|
+
// are added as cubic curves, as Core Graphics adds them. The page draws a
|
|
5
|
+
// path as SVG path data (`_svg`).
|
|
6
|
+
//
|
|
7
|
+
// `CGAffineTransform` lives here, not in the CoreGraphics module, so that a
|
|
8
|
+
// path can be transformed (`applying(_:)`, the `transform:` arguments);
|
|
9
|
+
// CoreGraphics re-exports it, as it does the geometry types.
|
|
10
|
+
|
|
11
|
+
#if canImport(WASILibc)
|
|
12
|
+
import WASILibc
|
|
13
|
+
#elseif canImport(Glibc)
|
|
14
|
+
import Glibc
|
|
15
|
+
#elseif canImport(Musl)
|
|
16
|
+
import Musl
|
|
17
|
+
#elseif canImport(Darwin)
|
|
18
|
+
import Darwin
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
// MARK: - Transforms
|
|
22
|
+
|
|
23
|
+
public struct CGAffineTransform: Equatable, Hashable, Sendable {
|
|
24
|
+
public var a, b, c, d, tx, ty: CGFloat
|
|
25
|
+
|
|
26
|
+
public init(a: CGFloat, b: CGFloat, c: CGFloat, d: CGFloat, tx: CGFloat, ty: CGFloat) {
|
|
27
|
+
(self.a, self.b, self.c, self.d, self.tx, self.ty) = (a, b, c, d, tx, ty)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public init(_ a: CGFloat, _ b: CGFloat, _ c: CGFloat, _ d: CGFloat, _ tx: CGFloat, _ ty: CGFloat) {
|
|
31
|
+
self.init(a: a, b: b, c: c, d: d, tx: tx, ty: ty)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public init() { self.init(a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0) }
|
|
35
|
+
public init(translationX tx: CGFloat, y ty: CGFloat) { self.init(a: 1, b: 0, c: 0, d: 1, tx: tx, ty: ty) }
|
|
36
|
+
public init(scaleX sx: CGFloat, y sy: CGFloat) { self.init(a: sx, b: 0, c: 0, d: sy, tx: 0, ty: 0) }
|
|
37
|
+
public init(rotationAngle angle: CGFloat) {
|
|
38
|
+
let (s, c) = (sin(angle), cos(angle))
|
|
39
|
+
self.init(a: c, b: s, c: -s, d: c, tx: 0, ty: 0)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public static let identity = CGAffineTransform()
|
|
43
|
+
public var isIdentity: Bool { self == .identity }
|
|
44
|
+
|
|
45
|
+
public func concatenating(_ t: CGAffineTransform) -> CGAffineTransform {
|
|
46
|
+
CGAffineTransform(a: a * t.a + b * t.c, b: a * t.b + b * t.d,
|
|
47
|
+
c: c * t.a + d * t.c, d: c * t.b + d * t.d,
|
|
48
|
+
tx: tx * t.a + ty * t.c + t.tx, ty: tx * t.b + ty * t.d + t.ty)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public func translatedBy(x: CGFloat, y: CGFloat) -> CGAffineTransform { CGAffineTransform(translationX: x, y: y).concatenating(self) }
|
|
52
|
+
public func scaledBy(x: CGFloat, y: CGFloat) -> CGAffineTransform { CGAffineTransform(scaleX: x, y: y).concatenating(self) }
|
|
53
|
+
public func rotated(by angle: CGFloat) -> CGAffineTransform { CGAffineTransform(rotationAngle: angle).concatenating(self) }
|
|
54
|
+
|
|
55
|
+
public func inverted() -> CGAffineTransform {
|
|
56
|
+
let det = a * d - b * c
|
|
57
|
+
guard det != 0 else { return self }
|
|
58
|
+
return CGAffineTransform(a: d / det, b: -b / det, c: -c / det, d: a / det,
|
|
59
|
+
tx: (c * ty - d * tx) / det, ty: (b * tx - a * ty) / det)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
extension CGPoint {
|
|
64
|
+
public func applying(_ t: CGAffineTransform) -> CGPoint {
|
|
65
|
+
CGPoint(x: t.a * x + t.c * y + t.tx, y: t.b * x + t.d * y + t.ty)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
extension CGSize {
|
|
70
|
+
public func applying(_ t: CGAffineTransform) -> CGSize {
|
|
71
|
+
CGSize(width: t.a * width + t.c * height, height: t.b * width + t.d * height)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
extension CGRect {
|
|
76
|
+
/// The bounding box of the transformed corners.
|
|
77
|
+
public func applying(_ t: CGAffineTransform) -> CGRect {
|
|
78
|
+
let corners = [CGPoint(x: minX, y: minY), CGPoint(x: maxX, y: minY), CGPoint(x: minX, y: maxY), CGPoint(x: maxX, y: maxY)].map { $0.applying(t) }
|
|
79
|
+
let xs = corners.map(\.x), ys = corners.map(\.y)
|
|
80
|
+
return CGRect(x: xs.min()!, y: ys.min()!, width: xs.max()! - xs.min()!, height: ys.max()! - ys.min()!)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// MARK: - Path
|
|
85
|
+
|
|
86
|
+
/// An outline: subpaths of lines and curves.
|
|
87
|
+
public struct Path: Equatable, Sendable {
|
|
88
|
+
/// One step of a path.
|
|
89
|
+
public enum Element: Equatable, Sendable {
|
|
90
|
+
case move(to: CGPoint)
|
|
91
|
+
case line(to: CGPoint)
|
|
92
|
+
case quadCurve(to: CGPoint, control: CGPoint)
|
|
93
|
+
case curve(to: CGPoint, control1: CGPoint, control2: CGPoint)
|
|
94
|
+
case closeSubpath
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private(set) var elements: [Element] = []
|
|
98
|
+
/// Where the current subpath started (a close returns there).
|
|
99
|
+
private var subpathStart: CGPoint?
|
|
100
|
+
|
|
101
|
+
public init() {}
|
|
102
|
+
|
|
103
|
+
public init(_ rect: CGRect) {
|
|
104
|
+
addRect(rect)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public init(roundedRect rect: CGRect, cornerRadius: CGFloat, style: RoundedCornerStyle = .continuous) {
|
|
108
|
+
addRoundedRect(in: rect, cornerSize: CGSize(width: cornerRadius, height: cornerRadius), style: style)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public init(roundedRect rect: CGRect, cornerSize: CGSize, style: RoundedCornerStyle = .continuous) {
|
|
112
|
+
addRoundedRect(in: rect, cornerSize: cornerSize, style: style)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public init(roundedRect rect: CGRect, cornerRadii: RectangleCornerRadii, style: RoundedCornerStyle = .continuous) {
|
|
116
|
+
addRoundedRect(in: rect, cornerRadii: cornerRadii, style: style)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public init(ellipseIn rect: CGRect) {
|
|
120
|
+
addEllipse(in: rect)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public init(_ callback: (inout Path) -> Void) {
|
|
124
|
+
var path = Path()
|
|
125
|
+
callback(&path)
|
|
126
|
+
self = path
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public var isEmpty: Bool { elements.isEmpty }
|
|
130
|
+
|
|
131
|
+
/// The last point of the path; nil for an empty one.
|
|
132
|
+
public var currentPoint: CGPoint? {
|
|
133
|
+
switch elements.last {
|
|
134
|
+
case .move(let p)?, .line(let p)?, .quadCurve(let p, _)?, .curve(let p, _, _)?: p
|
|
135
|
+
case .closeSubpath?: subpathStart
|
|
136
|
+
case nil: nil
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// MARK: Building
|
|
141
|
+
|
|
142
|
+
public mutating func move(to point: CGPoint) {
|
|
143
|
+
elements.append(.move(to: point))
|
|
144
|
+
subpathStart = point
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public mutating func addLine(to point: CGPoint) {
|
|
148
|
+
guard currentPoint != nil else { move(to: point); return }
|
|
149
|
+
elements.append(.line(to: point))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public mutating func addLines(_ points: [CGPoint]) {
|
|
153
|
+
guard let first = points.first else { return }
|
|
154
|
+
move(to: first)
|
|
155
|
+
for point in points.dropFirst() { addLine(to: point) }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
public mutating func addQuadCurve(to point: CGPoint, control: CGPoint) {
|
|
159
|
+
guard currentPoint != nil else { move(to: point); return }
|
|
160
|
+
elements.append(.quadCurve(to: point, control: control))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public mutating func addCurve(to point: CGPoint, control1: CGPoint, control2: CGPoint) {
|
|
164
|
+
guard currentPoint != nil else { move(to: point); return }
|
|
165
|
+
elements.append(.curve(to: point, control1: control1, control2: control2))
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public mutating func closeSubpath() {
|
|
169
|
+
guard let last = elements.last, last != .closeSubpath else { return }
|
|
170
|
+
elements.append(.closeSubpath)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public mutating func addRect(_ rect: CGRect, transform: CGAffineTransform = .identity) {
|
|
174
|
+
let r = rect.standardized
|
|
175
|
+
var path = Path()
|
|
176
|
+
path.move(to: CGPoint(x: r.minX, y: r.minY))
|
|
177
|
+
path.addLine(to: CGPoint(x: r.maxX, y: r.minY))
|
|
178
|
+
path.addLine(to: CGPoint(x: r.maxX, y: r.maxY))
|
|
179
|
+
path.addLine(to: CGPoint(x: r.minX, y: r.maxY))
|
|
180
|
+
path.closeSubpath()
|
|
181
|
+
addPath(path, transform: transform)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public mutating func addRects(_ rects: [CGRect], transform: CGAffineTransform = .identity) {
|
|
185
|
+
for rect in rects { addRect(rect, transform: transform) }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
public mutating func addRoundedRect(in rect: CGRect, cornerSize: CGSize, style: RoundedCornerStyle = .continuous,
|
|
189
|
+
transform: CGAffineTransform = .identity) {
|
|
190
|
+
let r = rect.standardized
|
|
191
|
+
let rx = max(0, min(cornerSize.width, r.width / 2))
|
|
192
|
+
let ry = max(0, min(cornerSize.height, r.height / 2))
|
|
193
|
+
addRoundedRect(r, radii: [(rx, ry), (rx, ry), (rx, ry), (rx, ry)], transform: transform)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
public mutating func addRoundedRect(in rect: CGRect, cornerRadii: RectangleCornerRadii, style: RoundedCornerStyle = .continuous,
|
|
197
|
+
transform: CGAffineTransform = .identity) {
|
|
198
|
+
let r = rect.standardized
|
|
199
|
+
let limit = min(r.width, r.height) / 2
|
|
200
|
+
func clamp(_ v: CGFloat) -> (CGFloat, CGFloat) { let v = max(0, min(v, limit)); return (v, v) }
|
|
201
|
+
// Clockwise from the top leading corner.
|
|
202
|
+
addRoundedRect(r, radii: [clamp(cornerRadii.topLeading), clamp(cornerRadii.topTrailing),
|
|
203
|
+
clamp(cornerRadii.bottomTrailing), clamp(cornerRadii.bottomLeading)], transform: transform)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// A rectangle with elliptical corners (top leading, top trailing, bottom
|
|
207
|
+
/// trailing, bottom leading), clockwise from the end of the top leading one.
|
|
208
|
+
private mutating func addRoundedRect(_ r: CGRect, radii: [(CGFloat, CGFloat)], transform: CGAffineTransform) {
|
|
209
|
+
let k = Path.kappa
|
|
210
|
+
let (tl, tr, br, bl) = (radii[0], radii[1], radii[2], radii[3])
|
|
211
|
+
var path = Path()
|
|
212
|
+
path.move(to: CGPoint(x: r.minX + tl.0, y: r.minY))
|
|
213
|
+
path.addLine(to: CGPoint(x: r.maxX - tr.0, y: r.minY))
|
|
214
|
+
if tr.0 > 0 || tr.1 > 0 {
|
|
215
|
+
path.addCurve(to: CGPoint(x: r.maxX, y: r.minY + tr.1),
|
|
216
|
+
control1: CGPoint(x: r.maxX - tr.0 + tr.0 * k, y: r.minY),
|
|
217
|
+
control2: CGPoint(x: r.maxX, y: r.minY + tr.1 - tr.1 * k))
|
|
218
|
+
}
|
|
219
|
+
path.addLine(to: CGPoint(x: r.maxX, y: r.maxY - br.1))
|
|
220
|
+
if br.0 > 0 || br.1 > 0 {
|
|
221
|
+
path.addCurve(to: CGPoint(x: r.maxX - br.0, y: r.maxY),
|
|
222
|
+
control1: CGPoint(x: r.maxX, y: r.maxY - br.1 + br.1 * k),
|
|
223
|
+
control2: CGPoint(x: r.maxX - br.0 + br.0 * k, y: r.maxY))
|
|
224
|
+
}
|
|
225
|
+
path.addLine(to: CGPoint(x: r.minX + bl.0, y: r.maxY))
|
|
226
|
+
if bl.0 > 0 || bl.1 > 0 {
|
|
227
|
+
path.addCurve(to: CGPoint(x: r.minX, y: r.maxY - bl.1),
|
|
228
|
+
control1: CGPoint(x: r.minX + bl.0 - bl.0 * k, y: r.maxY),
|
|
229
|
+
control2: CGPoint(x: r.minX, y: r.maxY - bl.1 + bl.1 * k))
|
|
230
|
+
}
|
|
231
|
+
path.addLine(to: CGPoint(x: r.minX, y: r.minY + tl.1))
|
|
232
|
+
if tl.0 > 0 || tl.1 > 0 {
|
|
233
|
+
path.addCurve(to: CGPoint(x: r.minX + tl.0, y: r.minY),
|
|
234
|
+
control1: CGPoint(x: r.minX, y: r.minY + tl.1 - tl.1 * k),
|
|
235
|
+
control2: CGPoint(x: r.minX + tl.0 - tl.0 * k, y: r.minY))
|
|
236
|
+
}
|
|
237
|
+
path.closeSubpath()
|
|
238
|
+
addPath(path, transform: transform)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/// An ellipse, clockwise on screen from its trailing point (3 o'clock).
|
|
242
|
+
public mutating func addEllipse(in rect: CGRect, transform: CGAffineTransform = .identity) {
|
|
243
|
+
let r = rect.standardized
|
|
244
|
+
let (rx, ry) = (r.width / 2, r.height / 2)
|
|
245
|
+
let (cx, cy) = (r.midX, r.midY)
|
|
246
|
+
let (ox, oy) = (rx * Path.kappa, ry * Path.kappa)
|
|
247
|
+
var path = Path()
|
|
248
|
+
path.move(to: CGPoint(x: r.maxX, y: cy))
|
|
249
|
+
path.addCurve(to: CGPoint(x: cx, y: r.maxY), control1: CGPoint(x: r.maxX, y: cy + oy), control2: CGPoint(x: cx + ox, y: r.maxY))
|
|
250
|
+
path.addCurve(to: CGPoint(x: r.minX, y: cy), control1: CGPoint(x: cx - ox, y: r.maxY), control2: CGPoint(x: r.minX, y: cy + oy))
|
|
251
|
+
path.addCurve(to: CGPoint(x: cx, y: r.minY), control1: CGPoint(x: r.minX, y: cy - oy), control2: CGPoint(x: cx - ox, y: r.minY))
|
|
252
|
+
path.addCurve(to: CGPoint(x: r.maxX, y: cy), control1: CGPoint(x: cx + ox, y: r.minY), control2: CGPoint(x: r.maxX, y: cy - oy))
|
|
253
|
+
path.closeSubpath()
|
|
254
|
+
addPath(path, transform: transform)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/// An arc of the circle around `center`, from `startAngle` to
|
|
258
|
+
/// `endAngle`. Angles turn from the x axis towards the y axis, which is
|
|
259
|
+
/// down on screen; `clockwise` is as Core Graphics means it in a y-up
|
|
260
|
+
/// space, so on screen `clockwise: false` turns clockwise (SwiftUI's
|
|
261
|
+
/// well-known inversion). A line joins the current point to the start.
|
|
262
|
+
public mutating func addArc(center: CGPoint, radius: CGFloat, startAngle: Angle, endAngle: Angle, clockwise: Bool,
|
|
263
|
+
transform: CGAffineTransform = .identity) {
|
|
264
|
+
let full = 2 * CGFloat.pi
|
|
265
|
+
var delta = endAngle.radians - startAngle.radians
|
|
266
|
+
if clockwise {
|
|
267
|
+
if delta <= -full { delta = -full } else if delta > 0 {
|
|
268
|
+
delta = delta.truncatingRemainder(dividingBy: full)
|
|
269
|
+
if delta > 0 { delta -= full }
|
|
270
|
+
}
|
|
271
|
+
} else {
|
|
272
|
+
if delta >= full { delta = full } else if delta < 0 {
|
|
273
|
+
delta = delta.truncatingRemainder(dividingBy: full)
|
|
274
|
+
if delta < 0 { delta += full }
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
addRelativeArc(center: center, radius: radius, startAngle: startAngle, delta: Angle(radians: delta), transform: transform)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/// An arc of `delta` from `startAngle` (positive: clockwise on screen).
|
|
281
|
+
public mutating func addRelativeArc(center: CGPoint, radius: CGFloat, startAngle: Angle, delta: Angle,
|
|
282
|
+
transform: CGAffineTransform = .identity) {
|
|
283
|
+
let start = startAngle.radians
|
|
284
|
+
let sweep = delta.radians
|
|
285
|
+
func point(_ angle: CGFloat) -> CGPoint {
|
|
286
|
+
CGPoint(x: center.x + radius * cos(angle), y: center.y + radius * sin(angle)).applying(transform)
|
|
287
|
+
}
|
|
288
|
+
let first = point(start)
|
|
289
|
+
if currentPoint == nil { move(to: first) } else { addLine(to: first) }
|
|
290
|
+
guard sweep != 0, radius > 0 else { return }
|
|
291
|
+
let segments = max(1, Int((abs(sweep) / (CGFloat.pi / 2)).rounded(.up)))
|
|
292
|
+
let step = sweep / CGFloat(segments)
|
|
293
|
+
let k = 4 / 3 * tan(step / 4)
|
|
294
|
+
var angle = start
|
|
295
|
+
for _ in 0..<segments {
|
|
296
|
+
let next = angle + step
|
|
297
|
+
let (c0, s0, c1, s1) = (cos(angle), sin(angle), cos(next), sin(next))
|
|
298
|
+
let control1 = CGPoint(x: center.x + radius * (c0 - k * s0), y: center.y + radius * (s0 + k * c0))
|
|
299
|
+
let control2 = CGPoint(x: center.x + radius * (c1 + k * s1), y: center.y + radius * (s1 - k * c1))
|
|
300
|
+
elements.append(.curve(to: point(next), control1: control1.applying(transform), control2: control2.applying(transform)))
|
|
301
|
+
angle = next
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/// The arc of `radius` tangent to the lines from the current point to
|
|
306
|
+
/// `tangent1End` and from there to `tangent2End`.
|
|
307
|
+
public mutating func addArc(tangent1End: CGPoint, tangent2End: CGPoint, radius: CGFloat,
|
|
308
|
+
transform: CGAffineTransform = .identity) {
|
|
309
|
+
guard let current = currentPoint?.applying(transform.inverted()) else {
|
|
310
|
+
move(to: tangent1End.applying(transform))
|
|
311
|
+
return
|
|
312
|
+
}
|
|
313
|
+
let (p0, p1, p2) = (current, tangent1End, tangent2End)
|
|
314
|
+
let v1 = CGPoint(x: p0.x - p1.x, y: p0.y - p1.y), v2 = CGPoint(x: p2.x - p1.x, y: p2.y - p1.y)
|
|
315
|
+
let l1 = (v1.x * v1.x + v1.y * v1.y).squareRoot(), l2 = (v2.x * v2.x + v2.y * v2.y).squareRoot()
|
|
316
|
+
let cross = v1.x * v2.y - v1.y * v2.x
|
|
317
|
+
guard l1 > 0, l2 > 0, abs(cross) > 1e-9, radius > 0 else {
|
|
318
|
+
addLine(to: p1.applying(transform))
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
let angle = acos(max(-1, min(1, (v1.x * v2.x + v1.y * v2.y) / (l1 * l2))))
|
|
322
|
+
let distance = radius / tan(angle / 2)
|
|
323
|
+
let t1 = CGPoint(x: p1.x + v1.x / l1 * distance, y: p1.y + v1.y / l1 * distance)
|
|
324
|
+
let t2 = CGPoint(x: p1.x + v2.x / l2 * distance, y: p1.y + v2.y / l2 * distance)
|
|
325
|
+
// The center lies along the bisector, `radius` from both tangent points.
|
|
326
|
+
let bisector = CGPoint(x: v1.x / l1 + v2.x / l2, y: v1.y / l1 + v2.y / l2)
|
|
327
|
+
let bl = (bisector.x * bisector.x + bisector.y * bisector.y).squareRoot()
|
|
328
|
+
let centerDistance = (distance * distance + radius * radius).squareRoot()
|
|
329
|
+
let center = CGPoint(x: p1.x + bisector.x / bl * centerDistance, y: p1.y + bisector.y / bl * centerDistance)
|
|
330
|
+
let a1 = atan2(t1.y - center.y, t1.x - center.x)
|
|
331
|
+
let a2 = atan2(t2.y - center.y, t2.x - center.x)
|
|
332
|
+
var sweep = a2 - a1
|
|
333
|
+
while sweep > CGFloat.pi { sweep -= 2 * CGFloat.pi }
|
|
334
|
+
while sweep < -CGFloat.pi { sweep += 2 * CGFloat.pi }
|
|
335
|
+
addLine(to: t1.applying(transform))
|
|
336
|
+
addRelativeArc(center: center, radius: radius, startAngle: Angle(radians: a1), delta: Angle(radians: sweep), transform: transform)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
public mutating func addPath(_ path: Path, transform: CGAffineTransform = .identity) {
|
|
340
|
+
for element in path.applying(transform).elements {
|
|
341
|
+
switch element {
|
|
342
|
+
case .move(let p): move(to: p)
|
|
343
|
+
case .line(let p): elements.append(.line(to: p))
|
|
344
|
+
case .quadCurve(let p, let c): elements.append(.quadCurve(to: p, control: c))
|
|
345
|
+
case .curve(let p, let c1, let c2): elements.append(.curve(to: p, control1: c1, control2: c2))
|
|
346
|
+
case .closeSubpath: closeSubpath()
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// MARK: Reading
|
|
352
|
+
|
|
353
|
+
public func forEach(_ body: (Element) -> Void) {
|
|
354
|
+
elements.forEach(body)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
public func applying(_ transform: CGAffineTransform) -> Path {
|
|
358
|
+
guard !transform.isIdentity else { return self }
|
|
359
|
+
var path = Path()
|
|
360
|
+
path.elements = elements.map { element in
|
|
361
|
+
switch element {
|
|
362
|
+
case .move(let p): .move(to: p.applying(transform))
|
|
363
|
+
case .line(let p): .line(to: p.applying(transform))
|
|
364
|
+
case .quadCurve(let p, let c): .quadCurve(to: p.applying(transform), control: c.applying(transform))
|
|
365
|
+
case .curve(let p, let c1, let c2): .curve(to: p.applying(transform), control1: c1.applying(transform), control2: c2.applying(transform))
|
|
366
|
+
case .closeSubpath: .closeSubpath
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
path.subpathStart = subpathStart?.applying(transform)
|
|
370
|
+
return path
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
public func offsetBy(dx: CGFloat, dy: CGFloat) -> Path {
|
|
374
|
+
applying(CGAffineTransform(translationX: dx, y: dy))
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/// The smallest rectangle around the path's outline (curves included,
|
|
378
|
+
/// their control points not).
|
|
379
|
+
public var boundingRect: CGRect {
|
|
380
|
+
let points = polylines().flatMap(\.points)
|
|
381
|
+
guard let first = points.first else { return .zero }
|
|
382
|
+
var (minX, minY, maxX, maxY) = (first.x, first.y, first.x, first.y)
|
|
383
|
+
for p in points {
|
|
384
|
+
minX = min(minX, p.x); minY = min(minY, p.y)
|
|
385
|
+
maxX = max(maxX, p.x); maxY = max(maxY, p.y)
|
|
386
|
+
}
|
|
387
|
+
return CGRect(x: minX, y: minY, width: maxX - minX, height: maxY - minY)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/// Whether `point` is inside the path filled with the non-zero winding
|
|
391
|
+
/// rule, or the even-odd rule with `eoFill`.
|
|
392
|
+
public func contains(_ point: CGPoint, eoFill: Bool = false) -> Bool {
|
|
393
|
+
var winding = 0
|
|
394
|
+
for line in polylines() {
|
|
395
|
+
var points = line.points
|
|
396
|
+
if let first = points.first, points.last != first { points.append(first) }
|
|
397
|
+
for (a, b) in zip(points, points.dropFirst()) where (a.y <= point.y) != (b.y <= point.y) {
|
|
398
|
+
let x = a.x + (point.y - a.y) / (b.y - a.y) * (b.x - a.x)
|
|
399
|
+
if x > point.x { winding += b.y > a.y ? 1 : -1 }
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return eoFill ? winding % 2 != 0 : winding != 0
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/// The part of the outline between two fractions of its length (curves
|
|
406
|
+
/// are kept as the short lines they flatten to).
|
|
407
|
+
public func trimmedPath(from: CGFloat, to: CGFloat) -> Path {
|
|
408
|
+
let from = max(0, min(1, from)), to = max(0, min(1, to))
|
|
409
|
+
guard to > from else { return Path() }
|
|
410
|
+
if from == 0 && to == 1 { return self }
|
|
411
|
+
let lines = polylines().map { line -> [CGPoint] in
|
|
412
|
+
line.closed && line.points.first != line.points.last ? line.points + [line.points[0]] : line.points
|
|
413
|
+
}
|
|
414
|
+
var total: CGFloat = 0
|
|
415
|
+
for points in lines { for (a, b) in zip(points, points.dropFirst()) { total += a.distance(to: b) } }
|
|
416
|
+
guard total > 0 else { return Path() }
|
|
417
|
+
let (start, end) = (from * total, to * total)
|
|
418
|
+
var result = Path()
|
|
419
|
+
var travelled: CGFloat = 0
|
|
420
|
+
for points in lines {
|
|
421
|
+
var drawing = false
|
|
422
|
+
for (a, b) in zip(points, points.dropFirst()) {
|
|
423
|
+
let length = a.distance(to: b)
|
|
424
|
+
let (s, e) = (travelled, travelled + length)
|
|
425
|
+
travelled = e
|
|
426
|
+
guard e > start, s < end, length > 0 else { continue }
|
|
427
|
+
let p = a.interpolated(to: b, amount: max(0, (start - s) / length))
|
|
428
|
+
let q = b == a ? b : a.interpolated(to: b, amount: min(1, (end - s) / length))
|
|
429
|
+
if !drawing { result.move(to: p); drawing = true }
|
|
430
|
+
result.addLine(to: q)
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return result
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/// The subpaths flattened to points (curves in short lines).
|
|
437
|
+
private func polylines() -> [(points: [CGPoint], closed: Bool)] {
|
|
438
|
+
var lines: [(points: [CGPoint], closed: Bool)] = []
|
|
439
|
+
var points: [CGPoint] = []
|
|
440
|
+
func finish(closed: Bool) {
|
|
441
|
+
if !points.isEmpty { lines.append((points, closed)) }
|
|
442
|
+
points = []
|
|
443
|
+
}
|
|
444
|
+
for element in elements {
|
|
445
|
+
switch element {
|
|
446
|
+
case .move(let p):
|
|
447
|
+
finish(closed: false)
|
|
448
|
+
points = [p]
|
|
449
|
+
case .line(let p):
|
|
450
|
+
points.append(p)
|
|
451
|
+
case .quadCurve(let p, let c):
|
|
452
|
+
let p0 = points.last ?? p
|
|
453
|
+
for i in 1...16 {
|
|
454
|
+
let t = CGFloat(i) / 16, u = 1 - t
|
|
455
|
+
points.append(CGPoint(x: u * u * p0.x + 2 * u * t * c.x + t * t * p.x,
|
|
456
|
+
y: u * u * p0.y + 2 * u * t * c.y + t * t * p.y))
|
|
457
|
+
}
|
|
458
|
+
case .curve(let p, let c1, let c2):
|
|
459
|
+
let p0 = points.last ?? p
|
|
460
|
+
for i in 1...16 {
|
|
461
|
+
let t = CGFloat(i) / 16, u = 1 - t
|
|
462
|
+
let (a, b, c, d) = (u * u * u, 3 * u * u * t, 3 * u * t * t, t * t * t)
|
|
463
|
+
points.append(CGPoint(x: a * p0.x + b * c1.x + c * c2.x + d * p.x,
|
|
464
|
+
y: a * p0.y + b * c1.y + c * c2.y + d * p.y))
|
|
465
|
+
}
|
|
466
|
+
case .closeSubpath:
|
|
467
|
+
let start = points.first
|
|
468
|
+
finish(closed: true)
|
|
469
|
+
if let start { points = [start] }
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
finish(closed: false)
|
|
473
|
+
return lines.filter { $0.points.count > 1 || $0.closed }
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/// The control point distance of a quarter circle drawn as a cubic curve.
|
|
477
|
+
static let kappa: CGFloat = 0.5522847498307936
|
|
478
|
+
|
|
479
|
+
/// The path as SVG path data, in points rounded to hundredths.
|
|
480
|
+
var _svg: String {
|
|
481
|
+
var out = ""
|
|
482
|
+
func add(_ command: Character, _ points: CGPoint...) {
|
|
483
|
+
out.append(command)
|
|
484
|
+
var first = true
|
|
485
|
+
for p in points {
|
|
486
|
+
if !first { out.append(" ") }
|
|
487
|
+
out += Path.number(p.x) + " " + Path.number(p.y)
|
|
488
|
+
first = false
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
for element in elements {
|
|
492
|
+
switch element {
|
|
493
|
+
case .move(let p): add("M", p)
|
|
494
|
+
case .line(let p): add("L", p)
|
|
495
|
+
case .quadCurve(let p, let c): add("Q", c, p)
|
|
496
|
+
case .curve(let p, let c1, let c2): add("C", c1, c2, p)
|
|
497
|
+
case .closeSubpath: out.append("Z")
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return out
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
static func number(_ value: CGFloat) -> String {
|
|
504
|
+
guard value.isFinite else { return "0" }
|
|
505
|
+
let rounded = (value * 100).rounded() / 100
|
|
506
|
+
if rounded == 0 { return "0" }
|
|
507
|
+
if rounded == rounded.rounded() { return String(Int(rounded)) }
|
|
508
|
+
return String(rounded)
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
extension Path: CustomStringConvertible {
|
|
513
|
+
/// Core Graphics' textual form (`x y m`, `x y l`, `cx cy x y q`, `c1 c2 p c`, `h`).
|
|
514
|
+
public var description: String {
|
|
515
|
+
elements.map { element in
|
|
516
|
+
func n(_ p: CGPoint) -> String { Path.number(p.x) + " " + Path.number(p.y) }
|
|
517
|
+
switch element {
|
|
518
|
+
case .move(let p): return n(p) + " m"
|
|
519
|
+
case .line(let p): return n(p) + " l"
|
|
520
|
+
case .quadCurve(let p, let c): return n(c) + " " + n(p) + " q"
|
|
521
|
+
case .curve(let p, let c1, let c2): return n(c1) + " " + n(c2) + " " + n(p) + " c"
|
|
522
|
+
case .closeSubpath: return "h"
|
|
523
|
+
}
|
|
524
|
+
}.joined(separator: " ")
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
extension CGRect {
|
|
529
|
+
/// The rectangle with a positive width and height.
|
|
530
|
+
public var standardized: CGRect {
|
|
531
|
+
CGRect(x: min(minX, maxX), y: min(minY, maxY), width: abs(width), height: abs(height))
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
extension CGPoint {
|
|
536
|
+
fileprivate func distance(to other: CGPoint) -> CGFloat {
|
|
537
|
+
((other.x - x) * (other.x - x) + (other.y - y) * (other.y - y)).squareRoot()
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
fileprivate func interpolated(to other: CGPoint, amount: CGFloat) -> CGPoint {
|
|
541
|
+
CGPoint(x: x + (other.x - x) * amount, y: y + (other.y - y) * amount)
|
|
542
|
+
}
|
|
543
|
+
}
|