{"$schema": "https://raw.githubusercontent.com/guitaripod/wwdc-sessions/master/schema/transcript.schema.json", "id": "wwdc2026-372", "language": "eng", "source": "https://developer.apple.com/videos/play/wwdc2026/372", "wordCount": 1053, "segments": [{"start": 7.0, "text": "Hi, I'm Matt, an engineer on the Pencil and Paper team."}, {"start": 12.0, "text": "Apps that give users a canvas to create whatever they want,"}, {"start": 15.0, "text": "have been some of the most iconic and empowering experiences on Apple platforms."}, {"start": 19.0, "text": "And PaperKit is what powers the canvas experience"}, {"start": 22.0, "text": "across many of Apple's own applications."}, {"start": 25.0, "text": "When you sketch an idea, drop in an image,"}, {"start": 27.0, "text": "or mark up a document in Notes, that's PaperKit."}, {"start": 31.0, "text": "It's the full canvas experience, pencil, shapes, text, images,"}, {"start": 37.0, "text": "all working together."}, {"start": 39.0, "text": "When you open a PDF in Preview and add a signature, highlight a passage,"}, {"start": 44.0, "text": "or circle something important, that's PaperKit too."}, {"start": 49.0, "text": "And when you're ideating in Freeform on macOS, that's also PaperKit."}, {"start": 54.0, "text": "And in iOS, macOS and visionOS 27, PaperKit opens up."}, {"start": 59.0, "text": "Today I'll show you how to unwrap PaperKit,"}, {"start": 62.0, "text": "so you can take full control over your canvas experience."}, {"start": 66.0, "text": "I'll start with the data model,"}, {"start": 67.0, "text": "which gives you access to everything on the canvas."}, {"start": 71.0, "text": "Then, I'll show you how to work with elements like shapes and images."}, {"start": 76.0, "text": "And I'll finish with adornments,"}, {"start": 78.0, "text": "which let you add interactive overlays and controls."}, {"start": 82.0, "text": "Let's get going with the data model."}, {"start": 85.0, "text": "I've been building a comic book editor powered by PaperKit."}, {"start": 88.0, "text": "I've already set up some basic templates."}, {"start": 91.0, "text": "But that's as far as I got."}, {"start": 92.0, "text": "Now I need to turn those templates into PaperMarkup."}, {"start": 96.0, "text": "PaperMarkup has a new subelements property."}, {"start": 99.0, "text": "It gives you access to every element on the canvas as a MarkupOrderedSet,"}, {"start": 103.0, "text": "which is an ordered collection you can read from and write to."}, {"start": 107.0, "text": "This code snippet creates a shape element for each panel."}, {"start": 111.0, "text": "And then update's the markup."}, {"start": 114.0, "text": "That's it."}, {"start": 116.0, "text": "Let's try this on the iPad."}, {"start": 118.0, "text": "I'll add a three-page panel to my comic."}, {"start": 121.0, "text": "Great. It's showing up exactly how I wanted."}, {"start": 124.0, "text": "The canvas is fully interactive,"}, {"start": 125.0, "text": "which is a problem for my comic book editor."}, {"start": 128.0, "text": "I can select the panels, drag them around and even delete them."}, {"start": 135.0, "text": "That's not what I want."}, {"start": 137.0, "text": "The template elements should not be editable."}, {"start": 140.0, "text": "To fix this, I need to change how those shape elements behave."}, {"start": 144.0, "text": "Every element on the canvas conforms to the Markup protocol."}, {"start": 148.0, "text": "This gives you common properties like frame and rotation."}, {"start": 152.0, "text": "There is also a new allowedInteractions property,"}, {"start": 154.0, "text": "which is a MarkupInteractions option set."}, {"start": 157.0, "text": "It gives you fine-grained control over what can be modified on each element."}, {"start": 162.0, "text": "Markup interactions lets you control moving, resizing and rotating,"}, {"start": 167.0, "text": "deleting, styling, and selecting, individually or in any combination."}, {"start": 174.0, "text": "And if you want to lock down everything at once,"}, {"start": 177.0, "text": "read-only combines them all into a single flag,"}, {"start": 180.0, "text": "which is perfect for the comic template."}, {"start": 183.0, "text": "To limit interactions with panels in the comic book editor,"}, {"start": 186.0, "text": "I need to set .allowedInteractions to .readOnly."}, {"start": 190.0, "text": "I'll give it a try."}, {"start": 192.0, "text": "Now when I tap a panel border,"}, {"start": 195.0, "text": "nothing happens."}, {"start": 196.0, "text": "The template shapes are read-only."}, {"start": 198.0, "text": "I can add a speech bubble, move that around,"}, {"start": 203.0, "text": "and stylize it,"}, {"start": 207.0, "text": "but the panels stay fixed."}, {"start": 209.0, "text": "Perfect."}, {"start": 210.0, "text": "The app is starting to take shape, but the panels need to really pop,"}, {"start": 214.0, "text": "so I've added a color picker in the toolbar for styling our template."}, {"start": 221.0, "text": "To implement styling, I'm going to dive into elements."}, {"start": 225.0, "text": "Every element in PaperMarkup has a concrete type."}, {"start": 229.0, "text": "Shapes, images, links, loupes, and pencil strokes."}, {"start": 234.0, "text": "They are all part of the same Markup ordered set,"}, {"start": 237.0, "text": "and conform to the Markup protocol."}, {"start": 240.0, "text": "But each of these types have their own custom properties."}, {"start": 243.0, "text": "Let's take a deeper look at shapes."}, {"start": 246.0, "text": "PaperKit supports many shape types"}, {"start": 248.0, "text": "and each type has its own properties, like corner radius for rounded rectangles,"}, {"start": 253.0, "text": "or control points for curved lines."}, {"start": 256.0, "text": "I used rectangles for the comic panels."}, {"start": 259.0, "text": "They have a stroke color and that's what we're looking for."}, {"start": 262.0, "text": "To apply a color to our panels, I need to iterate over the subelements."}, {"start": 267.0, "text": "Then set their stroke and fill colors."}, {"start": 271.0, "text": "To give it that extra pop,"}, {"start": 273.0, "text": "I'm going to use the same color for the markup background."}, {"start": 276.0, "text": "And lastly I update the markup on the paperMarkupViewController."}, {"start": 281.0, "text": "Let me check the result on the iPad."}, {"start": 286.0, "text": "And just like that, the canvas transforms."}, {"start": 289.0, "text": "The page is styled with the color I chose,"}, {"start": 292.0, "text": "and it's starting to unwrap into something more personal."}, {"start": 295.0, "text": "PaperKit is built on top of PencilKit, so I can use the Apple Pencil to draw."}, {"start": 302.0, "text": "Each stroke becomes a markup element"}, {"start": 304.0, "text": "and I can use all of the PencilKit model APIs."}, {"start": 308.0, "text": "Those APIs now support character recognition"}, {"start": 310.0, "text": "and Bézier path conversion."}, {"start": 312.0, "text": "For all the details,"}, {"start": 313.0, "text": "check out \"Reading Between the strokes with PencilKit\"."}, {"start": 317.0, "text": "Now let's look at how to add custom controls with adornments."}, {"start": 322.0, "text": "I want to add a button to each panel that lets users create artwork."}, {"start": 325.0, "text": "But I don't want those controls to become part of the document."}, {"start": 329.0, "text": "They shouldn't be saved, printed, or exported."}, {"start": 332.0, "text": "I want them to exist on top of the canvas, only when I'm editing."}, {"start": 336.0, "text": "That's exactly what Markup adornments are,"}, {"start": 339.0, "text": "a visual overlay anchored to canvas coordinates."}, {"start": 342.0, "text": "This makes adornments ideal for buttons, annotations, and collaboration UI."}, {"start": 347.0, "text": "They automatically track zoom and scroll,"}, {"start": 350.0, "text": "and they're completely separate from the persisted markup."}, {"start": 353.0, "text": "For each panel, I create a MarkupAdornment."}, {"start": 356.0, "text": "I anchor it to the center of the panel,"}, {"start": 358.0, "text": "and I give it an SF Symbol icon through the imageConfiguration."}, {"start": 363.0, "text": "Then I assign the array to the controller's adornments property."}, {"start": 368.0, "text": "To handle taps,"}, {"start": 369.0, "text": "I implement the delegate method didTapAdornmentWithID."}, {"start": 374.0, "text": "When the user taps an adornment,"}, {"start": 376.0, "text": "I present the ImagePlaygroundViewController."}, {"start": 381.0, "text": "When an image comes back from Image Playground, I create an ImageMarkup."}, {"start": 385.0, "text": "Then, I insert it into the subelements and update the view controller's markup."}, {"start": 391.0, "text": "Let's give it another try."}, {"start": 394.0, "text": "I'll tap one of the panels to create some artwork."}, {"start": 399.0, "text": "My comic is going to be about a super hero dog"}, {"start": 401.0, "text": "fighting crime in the city."}, {"start": 409.0, "text": "And the generated image fills the panel."}, {"start": 413.0, "text": "To learn more about generating images in your app,"}, {"start": 416.0, "text": "watch \"Create high-quality images using Image Playground\"."}, {"start": 421.0, "text": "And now with just a couple more images, some text and fonts,"}, {"start": 424.0, "text": "I've got the first page of my comic."}, {"start": 428.0, "text": "Our super hero dog is going to save the day."}, {"start": 431.0, "text": "Now you can build a fully interactive,"}, {"start": 433.0, "text": "canvas-based experience in your app with PaperKit."}, {"start": 437.0, "text": "Use the data model to programmatically read and modify what's on the canvas."}, {"start": 442.0, "text": "And add adornments to create interactive overlays tailored to your app."}, {"start": 446.0, "text": "I can't wait to see how you will unwrap PaperKit."}, {"start": 449.0, "text": "Thanks for watching!"}]}