Same PDF renders differently when open in Chrome, Safari; Apple Preview, Acrobat.
on Apple Preview, Safari - the PDF appears correctly for a second or two and then appears washed out.
Our app uses Safari to render PDFs and our users are complaining that scanned PDFs are not rendering properly.
How do I fix this issue (Swift, Obj-C)?
Core Graphics
RSS for tagHarness the power of Quartz technology to perform lightweight 2D rendering with high-fidelity output using Core Graphics.
Posts under Core Graphics tag
51 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
using renderInContext fetch pixel faild if subviews contains WKWebView, the code is as follows:
self.contentView = [SimpleClearContentView alloc] initWithFrame:CGRectMake(0, 100, 100, 100)];
contentView.backgroundColor = [UIColor clearColor];
self.contentView.webView = [[WKWebView alloc] init];
self.contentView.webView.frame = CGRectMake(0, 0, 50, 100);
// make web view clear bg color
self.contentView.webView.backgroundColor = [UIColor clearColor];
self.contentView.webView.scrollView.backgroundColor = [UIColor clearColor];
// webView load clear background webpage
[self.contentView.webView loadRequest:***];
[self.view addSubView:contentView];
// this method still return 0.0f anywhere
-(CGFloat)getPixelAlphaAtPoint:(CGPoint)point {
unsigned char pixel[4] = {0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
CGContextTranslateCTM(context, -point.x, -point.y);
WKWebView *webView = self.contentView.webView;
[webView.layer renderInContext:context];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
CGFloat alpha = pixel[3]/255.0;
return alpha;
}
How does one know the fitting width of a UIDatePicker in a selector hooked up with UIControlEventValueChanged? By fitting width, I mean the width of the grey background rounded box displayed with the date -- I need to get the width of that whenever the date is changed.
Steps to Reproduce:
Connect a MacBook Pro (lid closed) to a large external monitor.
Run the SDL3 testwm test application.
git clone https://github.com/libsdl-org/SDL.git
cmake -S . -B build -DBUILD_SHARED_LIBS=OFF -DSDL_TESTS=ON
cmake --build build
The testwm binary will be located in the build/test directory.
Move the application window around the left edge of the external display.
Observed Result:
WindowServer crashes.
System Configuration:
MacBook Pro M3 Max, macOS Sequoia 15.6.1
LG GX9, 5120x2160 resolution, running at 165 Hz refresh rate
Lid closed, single external display
Panic Log:
panic(cpu 7 caller 0xfffffe0027f61d5c): "mismatched swapID's 6386399 vs 6386400\n" @UnifiedPipeline.cpp:14570
Debugger message: panic
Memory ID: 0xff
OS release type: User
OS version: 24G90
Kernel version: Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:55 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6031
Fileset Kernelcache UUID: 8AA69CD2038CD2BAE2ED364428F4DBEA
Kernel UUID: 75A21406-D046-3232-AA3F-085335D5C848
Boot session UUID: B949E839-683B-4DAF-BE42-4562758F976E
iBoot version: iBoot-11881.140.96
iBoot Stage 2 version: iBoot-11881.140.96
secure boot?: YES
roots installed: 0
Paniclog version: 14
KernelCache slide: 0x000000001e0ec000
KernelCache base: 0xfffffe00250f0000
Kernel slide: 0x000000001e0f4000
Kernel text base: 0xfffffe00250f8000
Kernel text exec slide: 0x000000001f870000
Kernel text exec base: 0xfffffe0026874000
mach_absolute_time: 0x64e7db3e6a9
Epoch Time: sec usec
Boot : 0x68b207f0 0x00082ee7
Sleep : 0x68c1a51c 0x00048c6c
Wake : 0x68c1a760 0x00039aa4
Calendar: 0x68c1b78d 0x0001776a
Zone info:
Zone map: 0xfffffe1018000000 - 0xfffffe3618000000
. VM : 0xfffffe1018000000 - 0xfffffe15e4000000
. RO : 0xfffffe15e4000000 - 0xfffffe187e000000
. GEN0 : 0xfffffe187e000000 - 0xfffffe1e4a000000
. GEN1 : 0xfffffe1e4a000000 - 0xfffffe2416000000
. GEN2 : 0xfffffe2416000000 - 0xfffffe29e2000000
. GEN3 : 0xfffffe29e2000000 - 0xfffffe2fae000000
. DATA : 0xfffffe2fae000000 - 0xfffffe3618000000
Metadata: 0xfffffe393c010000 - 0xfffffe3945810000
Bitmaps : 0xfffffe3945810000 - 0xfffffe394c104000
Extra : 0 - 0
CORE 0 recently retired instr at 0xfffffe0026a407a0
CORE 1 recently retired instr at 0xfffffe0026a40798
CORE 2 recently retired instr at 0xfffffe0026a407a0
CORE 3 recently retired instr at 0xfffffe0026a407a0
CORE 4 recently retired instr at 0xfffffe0026a407a0
CORE 5 recently retired instr at 0xfffffe0026a407a0
CORE 6 recently retired instr at 0xfffffe0026a407a0
CORE 7 recently retired instr at 0xfffffe0026a3eefc
CORE 8 recently retired instr at 0xfffffe0026a407a0
CORE 9 recently retired instr at 0xfffffe0026a407a0
CORE 10 recently retired instr at 0xfffffe0026a407a0
CORE 11 recently retired instr at 0xfffffe0026a407a0
CORE 12 recently retired instr at 0xfffffe0026a407a0
CORE 13 recently retired instr at 0xfffffe0026a407a0
TPIDRx_ELy = {1: 0xfffffe29e4ef5ee0 0: 0x0000000000001007 0ro: 0x000000016c59b0e0 }
CORE 0 PVH locks held: None
CORE 1 PVH locks held: None
CORE 2 PVH locks held: None
CORE 3 PVH locks held: None
CORE 4 PVH locks held: None
CORE 5 PVH locks held: None
CORE 6 PVH locks held: None
CORE 7 PVH locks held: None
CORE 8 PVH locks held: None
CORE 9 PVH locks held: None
CORE 10 PVH locks held: None
CORE 11 PVH locks held: None
CORE 12 PVH locks held: None
CORE 13 PVH locks held: None
CORE 0: PC=0xfffffe0026abfa40, LR=0xfffffe0026ae4fc8, FP=0xfffffe65b8703980
CORE 1: PC=0x0000000193ae2730, LR=0x000000019389d108, FP=0x000000016f43e590
CORE 2: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b850bed0
CORE 3: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b8ee7ed0
CORE 4: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b7eebed0
CORE 5: PC=0xfffffe0026a3ac1c, LR=0xfffffe0026a3ac18, FP=0xfffffe65b8c63e40
CORE 6: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b7033ed0
CORE 7 is the one that panicked. Check the full backtrace for details.
CORE 8: PC=0xfffffe0026a3ac1c, LR=0xfffffe0026a3ac18, FP=0xfffffe65b737be40
CORE 9: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b8f1fed0
CORE 10: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b7fe7ed0
CORE 11: PC=0xfffffe0026a3ac1c, LR=0xfffffe0026a3ac18, FP=0xfffffe65b870fe40
CORE 12: PC=0xfffffe0026911e84, LR=0xfffffe0026911e84, FP=0xfffffe65b80a7ed0
CORE 13: PC=0xfffffe0026a3ac1c, LR=0xfffffe0026a3ac18, FP=0xfffffe65b685fe40
Compressor Info: 6% of compressed pages limit (OK) and 16% of segments limit (OK) with 0 swapfiles and OK swap space
Panicked task 0xfffffe23153cb940: 10375 pages, 28 threads: pid 406: WindowServer
Panicked thread: 0xfffffe29e4ef5ee0, backtrace: 0xfffffe65b6f07210, tid: 5146
lr: 0xfffffe00268d53d4 fp: 0xfffffe65b6f072a0
lr: 0xfffffe0026a36da0 fp: 0xfffffe65b6f07310
lr: 0xfffffe0026a35114 fp: 0xfffffe65b6f073d0
lr: 0xfffffe002687f8b0 fp: 0xfffffe65b6f073e0
lr: 0xfffffe00268d5710 fp: 0xfffffe65b6f077b0
lr: 0xfffffe0027169290 fp: 0xfffffe65b6f077d0
lr: 0xfffffe0027f61d5c fp: 0xfffffe65b6f07850
lr: 0xfffffe0029186878 fp: 0xfffffe65b6f07880
lr: 0xfffffe00270bd2a0 fp: 0xfffffe65b6f078b0
lr: 0xfffffe00270bd5b0 fp: 0xfffffe65b6f07a40
lr: 0xfffffe0026a00194 fp: 0xfffffe65b6f07b60
lr: 0xfffffe00268dcd48 fp: 0xfffffe65b6f07c00
lr: 0xfffffe00268b2ed4 fp: 0xfffffe65b6f07c60
lr: 0xfffffe00268c6868 fp: 0xfffffe65b6f07cb0
lr: 0xfffffe00268c6c80 fp: 0xfffffe65b6f07da0
lr: 0xfffffe0026a29bbc fp: 0xfffffe65b6f07e50
lr: 0xfffffe0026a355a4 fp: 0xfffffe65b6f07f10
lr: 0xfffffe002687f8b0 fp: 0xfffffe65b6f07f20
lr: 0x000000018dc89c34 fp: 0x0000000000000000
Kernel Extensions in backtrace:
com.apple.iokit.IOMobileGraphicsFamily(343.0)[6C8CFA29-99CD-39D4-81BC-2B0F147BE64F]@0xfffffe002917d860->0xfffffe00291a024f
I have a PDF which contains geocoordinates. I'm extracting out that image with the following code (this is for an iOS application):
guard let cgDocument = CGPDFDocument(overlay.pdfUrl as CFURL) else { return }
guard let cgPage = cgDocument.page(at: 1) else { return }
var boundingRect = self.rect(for: overlay.boundingMapRect)
let pdfPageRect = cgPage.getBoxRect(.mediaBox)
let renderer = UIGraphicsImageRenderer(size: pdfPageRect.size)
var img = renderer.image { ctx in
UIColor.white.set()
ctx.fill(pdfPageRect)
ctx.cgContext.translateBy(x: 0.0, y: pdfPageRect.size.height)
ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
ctx.cgContext.drawPDFPage(cgPage)
}
Once I have that image, I then need to adjust it to fit the specific coordinate corners. For that, I'm doing the following using a perspectiveTransform:
let ciImg = CIImage(image: img)!
let perspectiveTransformFilter = CIFilter.perspectiveTransform()
perspectiveTransformFilter.inputImage = ciImg
perspectiveTransformFilter.topRight = cartesianForPoint(point: ur, extent: boundingRect)
perspectiveTransformFilter.topLeft = cartesianForPoint(point: ul, extent: boundingRect)
perspectiveTransformFilter.bottomRight = cartesianForPoint(point: lr, extent: boundingRect)
perspectiveTransformFilter.bottomLeft = cartesianForPoint(point: ll, extent: boundingRect)
let txImg = perspectiveTransformFilter.outputImage!
img = UIImage(ciImage: txImg)
The original image is 792 x 612 (a landscape PDF) but the boundingRect covering the coordinates is 25625 x 20030. Obviously when I try to draw the image into that bounding box the app runs out of memory (25625 x 20030 x 4 is around 2GB of memory).
What I'm struggling with is - how do I correctly scale this image to fit into the bounding box even though the bounding box is, oh, 10x the resolution of the actual device? There's some key CoreGraphics thing I'm sure I'm missing here.
Hi,
This can't be right. Is there really no replacement for Quartz Debug?!?
As the sole developer on a project who has an Intel Mac and Quartz Debug, I am basically a god now.
Everyone else has Apple Silicon and... I think they're randomly guessing at this point.
Because I have entire teams sending me Intel Mac builds of stuff just so I can test it in QD.
This is THE TOOL we used at NewTek to find performance issues, and THE TOOL I used for a dozen companies after that, to help them with similar issues.
If there's no replacement, is there a reason there's no replacement? This feels like a massive step backwards, having to guess at problems like this.
-Chilton
Some users reported that their images are not loading correctly in our app. After a lot of debugging we identified the following:
This only happens when the app is build for Mac Catalyst. Not on iOS, iPadOS, or “real” macOS (AppKit).
The images in question have unusual color spaces. We observed the issue for uRGB and eciRGB v2.
Those images are rendered correctly in Photos and Preview on all platforms.
When displaying the image inside of a UIImageView or in a SwiftUI Image, they render correctly.
The issue only occurs when loading the image via Core Image.
When comparing the different Core Image render graphs between AppKit (working) and Catalyst (faulty) builds, they look identical—except for the result.
Mac (AppKit):
Catalyst:
Something seems to be off when Core Image tries to load an image with foreign color space in Catalyst.
We identified a workaround: By using a CGImageDestination to transcode the image using the kCGImageDestinationOptimizeColorForSharing option, Image I/O will convert the image to sRGB (or similar) and Core Image is able to load the image correctly. However, one potentially loses fidelity this way.
Or might there be a better workaround?
Topic:
Media Technologies
SubTopic:
Photos & Camera
Tags:
Image I/O
Photos and Imaging
Core Image
Core Graphics
So I get JPEG data in my app. Previously I was using the higher level NSBitmapImageRep API and just feeding the JPEG data to it.
But now I've noticed on Sonoma If I get a JPEG in the CMYK color space the NSBitmapImageRep renders mostly black and is corrupted. So I'm trying to drop down to the lower level APIs. Specifically I grab a CGImageRef and and trying to use the Accelerate API to convert it to another format (to hopefully workaround the issue...
CGImageRef sourceCGImage = `CGImageCreateWithJPEGDataProvider(jpegDataProvider,`
NULL,
shouldInterpolate,
kCGRenderingIntentDefault);
Now I use vImageConverter_CreateWithCGImageFormat... with the following values for source and destination formats:
Source format: (derived from sourceCGImage)
bitsPerComponent = 8
bitsPerPixel = 32
colorSpace = (kCGColorSpaceICCBased; kCGColorSpaceModelCMYK; Generic CMYK Profile)
bitmapInfo = kCGBitmapByteOrderDefault
version = 0
decode = 0x000060000147f780
renderingIntent = kCGRenderingIntentDefault
Destination format:
bitsPerComponent = 8
bitsPerPixel = 24
colorSpace = (DeviceRBG)
bitmapInfo = 8197
version = 0
decode = 0x0000000000000000
renderingIntent = kCGRenderingIntentDefault
But vImageConverter_CreateWithCGImageFormat fails with kvImageInvalidImageFormat. Now if I change the destination format to use 32 bitsPerpixel and use alpha in the bitmap info the vImageConverter_CreateWithCGImageFormat does not return an error but I get a black image just like NSBitmapImageRep
For an app of mine I use CGSetDisplayTransferByTable to adjust the gamma table of the device. Since macOS Tahoe, these modifications are silently ignored. The display's actual gamma curve remains unchanged despite the API reporting successful completion.
I've filed a FB for it a few weeks ago, and would love to figure out what could be causing this.
FB18559786
Hello,
The application I'm working on must report new hardware connections. To retrieve connected displays information and monitor new connections, I'm using the "Core Graphics" framework (see recommendation https://developer.apple.com/forums/thread/779945).
The monitoring logic relies on a callback function which invokes when the local display configuration changes(kCGDisplayAddFlag/kCGDisplayRemoveFlag).
#import <Cocoa/Cocoa.h>
static void displayChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void *userInfo)
{
uint32_t vendor = CGDisplayVendorNumber(displayID);
if (flags & kCGDisplayAddFlag)
{
if (vendor == kDisplayVendorIDUnknown)
{
NSLog(@"I/O Kit cannot identify the monitor. kDisplayVendorIDUnknown. displayId = %u", displayID);
return;
}
NSLog(@"%u connected. vendor(%u)", displayID, vendor);
}
if (flags & kCGDisplayRemoveFlag)
{
NSLog(@"%u disconnected", displayID);
}
}
int main(int argc, const char * argv[])
{
@autoreleasepool
{
CGDisplayRegisterReconfigurationCallback(displayChanged, NULL);
NSApplicationLoad();
CFRunLoopRun();
}
return 0;
}
The test environment is a Mac mini with an external display connected via HDMI. Everything works correctly until the system enters sleep mode. Upon wakeup, the app reports two displays: the first with vendor ID kDisplayVendorIDUnknown and the second with the expected vendor ID.
Why does Core Graphics report two connections during wakeup? Is there any way to avoid this?
Thank you in advance.
Hi,
I want to detect if there is a fullscreen window on each screen.
_AXUIElementGetWindow and kAXFullscreenAttribute methods work, but I have to be in a non-sandbox environment to use them.
Is there any other way that also works? I don't think it's enough to judge if it's fullscreen by comparing the window size to the screen size, since it doesn't work on MacBook with notch, or the menu bar is set to 'auto-hide'.
Thanks.
Topic:
Accessibility & Inclusion
SubTopic:
General
Tags:
Accessibility
Mac App Store
Core Graphics
App Sandbox
I use the following code to keep the mouse cursor within the bounds of my application window. This causes the mouse cursor to become magnified while hugging the window's edges. Is there a way to prevent this?
My clients are building a game, board style with a large map viewed from a top camera. They want the map to pan automatically when the mouse reaches the edge of the window. And they want the mouse cursor to stay confined to the game window.
Thank you.
CGDisplayMoveCursorToPoint(CGMainDisplayID(), location);
// Removes a delay introduced by CGWarpMouseCursorPosition to keep mouse cursor motion fluid while hugging the screen edges
CGEventSourceRef eventSourceRef = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventSourceSetLocalEventsSuppressionInterval(eventSourceRef, 0);
WWDC25: Combine Metal 4 machine learning and graphics
Demonstrated a way to combine neural network in the graphics pipeline directly through the shaders, using an example of Texture Compression. However there is no mention of using which ML technique texture is compressed.
Can anyone point me to some well known model/s for this particular use case shown in WWDC25.
We are seeing crashes in Xcode organizer. So far we are not able to reproduce them locally. They affect multiple app releases (some older, built with Xcode 15.x and newer built with Xcode 16.0). They only affect iOS 18.5.
Is there anything that changed in latest iOS? It's hard to tell what exactly is causing this crash because setting symbolic breakpoint on CA::Render::Image::new_image(unsigned int, unsigned int, unsigned int, unsigned int, CGColorSpace*, void const*, unsigned long const*, void (*)(void const*, void*), void*) triggers this breakpoint all the time, but not necessarily with exactly the previous stack frames matching the crash report.
Is it a known issue?
crash.crash
Thank you.
My setup:
a UILabel with text in it
and then
let aBugRenderer = UIGraphicsImageRenderer(size: aBugLabel.bounds.size)
let aBugImage = aBugRenderer.image { context in
aBugLabel.drawHierarchy(in: aBugLabel.bounds, afterScreenUpdates: true)
}
The layout and everything is correct, the image is correct, but I used my colors in the displayP3 color space to configure the source UILabel.textColor
And unfortunately, the resulted image ends up being sRGB IEC61966-2.1 color space and the color appears way bleaker than when it's drawn natively.
Question: how can I set up the renderer so that it draws the same color.
Hello everyone,
I've encountered a fascinating and perplexing rendering anomaly when using UIBezierPath(roundedRect:cornerRadius:) to create a CGPath.
Summary of the Issue:
When the shortest side of the rectangle (min(width, height)) is just under a certain multiple of the cornerRadius (empirically, around 3x), the algorithm for generating the path seems to change entirely. This results in a path with visually different (and larger) corners than when the side is slightly longer, even with the same cornerRadius parameter.
How to Reproduce:
The issue is most clearly observed with a fixed cornerRadius while slightly adjusting the rectangle's height or width across a specific threshold.
Create a UIView (contentView) and another UIView (shadowView) behind it.
Set the shadowView.layer.shadowPath using UIBezierPath(roundedRect: contentView.bounds, cornerRadius: 16).cgPath.
Adjust the height of the contentView.
Observe the shadowPath at height 48 vs. height 49
Minimal Reproducible Example:
Here is a simple UIViewController to demonstrate the issue. You can drop this into a project. Tapping the "Toggle Height" button will switch between the two states and print the resulting CGPath to the console.
import UIKit
class PathTestViewController: UIViewController {
private let contentView = UIView()
private let shadowView = UIView()
private var heightConstraint: NSLayoutConstraint!
private let cornerRadius: CGFloat = 16.0
private let normalHeight: CGFloat = 49
private let anomalyHeight: CGFloat = 48
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemGray5
setupViews()
setupButton()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
updateShadowPath()
}
private func updateShadowPath() {
let newPath = UIBezierPath(roundedRect: contentView.bounds, cornerRadius: cornerRadius).cgPath
shadowView.layer.shadowPath = newPath
}
private func setupViews() {
// ContentView (the visible rect)
contentView.backgroundColor = .systemBlue
contentView.translatesAutoresizingMaskIntoConstraints = false
contentView.isHidden = true
// ShadowView (to render the path)
shadowView.layer.shadowColor = UIColor.black.cgColor
shadowView.layer.shadowOpacity = 1
shadowView.layer.shadowRadius = 2
shadowView.layer.shadowOffset = .zero
shadowView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(shadowView)
view.addSubview(contentView)
heightConstraint = contentView.heightAnchor.constraint(equalToConstant: normalHeight)
NSLayoutConstraint.activate([
contentView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
contentView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
contentView.widthAnchor.constraint(equalToConstant: 300),
heightConstraint,
shadowView.topAnchor.constraint(equalTo: contentView.topAnchor),
shadowView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
shadowView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
shadowView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
])
}
private func setupButton() {
let button = UIButton(type: .system, primaryAction: UIAction(title: "Toggle Height", handler: { [unowned self] _ in
let newHeight = self.heightConstraint.constant == self.normalHeight ? self.anomalyHeight : self.normalHeight
self.heightConstraint.constant = newHeight
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}))
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20)
])
}
}
Evidence: CGPath Analysis
Note: The CGPath data below is from my initial observation. At that time, height 48.7 produced a path with straight edges. Now, this "correct" path is only produced at height 49.0 or greater. The inconsistency now occurs at 48.7.*
The key difference lies in the raw CGPath data.
Path for Height = 48.7 (Expected Behavior)
The path is constructed with lineto commands for the straight edges between the curved corners.
// Path for Height 48.7
Path 0x60000300a0a0:
moveto (24.4586, 0)
lineto (24.5414, 0) // <-- Straight line on top edge
curveto (31.5841, 0) (35.1055, 0) (38.8961, 1.19858)
...
Path for Height = 48.6 (Anomalous Behavior)
The lineto commands for the short edges disappear. The path is composed of continuous curveto commands, as if the two corners have merged into a single, larger curve. This creates the visual discrepancy.
// Path for Height 48.6
Path 0x600003028630:
moveto (24.1667, 0)
lineto (24.1667, 0) // <-- Zero-length line
curveto (24.1667, 0) (24.1667, 0) (24.1667, 0)
lineto (25.375, 1.44329e-15)
curveto (34.8362, -2.77556e-16) (43.2871, 5.9174) (46.523, 14.808) // <-- First curve
curveto (48.3333, 20.5334) (48.3333, 25.8521) (48.3333, 36.4896) // <-- Second curve, no straight line in between
...
min.length == 48
min.length == 49
My Questions:
Is this change in the path-generation algorithm at this specific size/radius threshold an intended behavior, or is it a bug?
Is this behavior documented anywhere? The threshold doesn't seem to be a clean side/radius == 2.0, so it's hard to predict.
Is there a recommended workaround to ensure consistent corner rendering across these small size thresholds?
Any insight would be greatly appreciated. Thank you!
Environment:
Xcode: 16.4
iOS: 16.5.1(iPad), 18.4(iphone simulator)
let dic : [AnyHashable:Any] = [
kCGPDFXRegistryName: "http://www.color.org" as CFString,
kCGPDFXOutputConditionIdentifier: "FOGRA43" as CFString,
kCGPDFContextOutputIntent: "GTS_PDFX" as CFString,
kCGPDFXOutputIntentSubtype: "GTS_PDFX" as CFString,
kCGPDFContextCreateLinearizedPDF: "" as CFString,
kCGPDFContextCreatePDFA: "" as CFString,
kCGPDFContextAuthor: "Placeholder" as CFString,
kCGPDFContextCreator: "Placeholder" as CFString
]
Hello,
Now I would like to export my PDF's as PDF/A. In my opinion, there is also the right option for this under Core Graphics.
Unfortunately, the documentation does not show what is 'kCGPDFContextCreatePDFA' or 'kCGPDFContextLinearizedPDF' for
a stringvalue is required.
What I have already tried: GTS_PDFA1 , PDF/A-1, true as CFString.
(Above my CFDictionary. ...Author e.g are working perfectly.)
In the Finder you can see these two options, which I would also like to implement in my app.
Thank you in advance!
I have filed a bug report for this (FB17734946), but I'm posting it here verbatim in case others have the same issue and in hopes of getting attention from an Apple engineer sooner.
When calling setNeedsDisplayInRect on a CATiledLayer - or a UIView whose backing layer is CATiledLayer - one would expect to re-draw only a region identified by the rect passed to the method. This is even written in the documentation for the class:
"Regions of the layer may be invalidated using the setNeedsDisplayInRect: method however the update will be asynchronous. While the next display update will most likely not contain the updated content, a future update will."
However, upon calling this method, CATiledLayer redraws whole contents instead of just the tile at the specified rect, and it flashes when doing so. It behaves exactly the same as if one had called setNeedsDisplay without passing any rect; all contents are cleared and re-drawn again. I'm 100% sure I've passed in the correct rect of the exact tile that I need to redraw. I have even tried passing much smaller rects, but still the same. (And yes, the rect I've passed accounts for the current level of detail.)
I have found this GitHub repo https://github.com/frankus/NetPhotoScroller, which based on discussion from here https://forums.macrumors.com/threads/catiledlayer-blanks-out-tiles-when-redrawing.1333948/ aims at solving these issues by using two private methods on CATiledLayer class:
(void)setNeedsDisplayInRect:(CGRect)r levelOfDetail:(int)level;
(BOOL)canDrawRect:(CGRect)rect levelOfDetail:(int)level;
I have explored the repo in detail, however I wasn't able to test exactly this code from the GitHub repo. I have tried using those two private methods myself (through an Objective-C class that defines the methods in the header file and then a swift class which inherits it), but I couldn't solve the issue; the flashing and the full re-draw is still there.
After doing a lot of research, the conclusion seems to be that one cannot use CATiledLayer with contents that are downloaded remotely, on demand, as tiles are being requested.
I have, however, found one interesting thing which seems to work so far: before calling setNeedsDisplayInRect (or just setNeedsDisplay, as they behave the same for CATiledLayer in my testing), cache the current layer's contents, and after calling setNeedsDisplay (or setNeedsDisplayInRect), restore the contents back to the layer. This prevents flashing and preserves any tiles that were drawn at the time of the re-draw.
let c = tiledLayer.contents
tiledLayer.setNeedsDisplay(tileRect)
tiledLayer.contents = c
However! Docs clearly state the warning:
Do not attempt to directly modify the contents property of a CATiledLayer object. Doing so disables the ability of a tiled layer to asynchronously provide tiled content, effectively turning the layer into a regular CALayer object.
I believe this message implies modifying the contents property with some raw content, like image data, and that it may be safe to re-apply the existing contents (which are in my testing of type CAImageProvider) -- but I can't rely on an implementation detail in my production app.
I have tested this and confirmed that the bug appears on:
iPhone 14 Pro, iOS 18.5
iPhone 13 Pro, iOS 17.5.1
iPhone 5s, iOS 15.8.3
iPad Pro 1st gen, iPadOS 18.4.1
a couple simulator versions
I can also confirm that the fix (to re-apply contents property) is also working properly on all these versions.
Is this expected behavior, that tiled layer redraws itself entirely instead of redrawing specific tiles?
Is it safe to modify contents of a CATiledLayer by re-applying the existing contents?
If not, is there an alternative to avoid flashing?
I have a macOS app that captures screen images. The first time I run this application, a dialog is shown directing the user to give my app Screen Recording permission. Is there a way I can trigger this dialog earlier and detect whether the permission was granted?