Note: It appears that as of macOS Big Sur/11.6.4, this bug has been fixed. The test script now produces the second image instead of the third image when using paragraphSpacingBefore
.
I’m writing a command-line script on macOS that creates an image from text. I want to give some paragraphs extra space above to set them off from the previous paragraph. Due to the way the script works, it will be easier to set attributes on a paragraph that put extra space above it, rather than change the attributes on the previous paragraph. I thought this was what paragraphSpacingBefore on NSMutableParagraphStyle
is for.
However, while I can get paragraphSpacing to provide space after the first paragraph, paragraphSpacingBefore appears to add space after the second paragraph.
This very simplified test script will create an image with three paragraphs in it.
With both the paragraphSpacing
line and the paragraphSpacingBefore
line commented out, there is no extra spacing added between or around the paragraphs:
If the paragraphSpacing
line is uncommented, there is space between the three paragraphs:
But if the paragraphSpacing
line is commented out and the paragraphSpacingBefore
line is uncommented, there is no space between the three paragraphs but there is space added after the third paragraph:
It appears that the spacing at the end is twice the paragraphSpacingBefore value; if I comment out the cheers +=
line to make it only have two paragraphs, the space after the final paragraph looks to be about halved:
This doesn’t make sense to me. I would expect the third image (using paragraphSpacingBefore
to be very similar to the second image. I am misunderstanding what paragraphSpacingBefore
means, and/or I am doing something wrong.
#!/usr/bin/swift
//test paragraphSpacingBefore
import AppKit
//set up text
var cheers = "“What do you say, Norm?”\nAny cheap, tawdry thing that’ll get me a beer."
cheers += "\n—Cheers"
var paragraphStyle = NSMutableParagraphStyle()
//paragraphStyle.paragraphSpacing = 32
paragraphStyle.paragraphSpacingBefore = 32
var textAttributes = [NSAttributedString.Key.paragraphStyle:paragraphStyle]
let textLines = NSAttributedString(string:cheers, attributes:textAttributes)
//create image of text
let outputSize = textLines.size()
let textRect = NSRect(x: 0, y: 0, width: outputSize.width, height: outputSize.height)
let background = NSColor(red:0, green:1, blue:1, alpha:1)
let outputImage = NSImage(size:outputSize, flipped: false) { (outputRect) -> Bool in
//set a background color
background.setFill()
outputRect.fill()
//draw the text
textLines.draw(in: textRect)
return true
}
//save image to file
var imageData = outputImage.tiffRepresentation
let bitmappedText = NSBitmapImageRep(data: imageData!)
imageData = bitmappedText!.representation(using: NSBitmapImageRep.FileType.png, properties:[:])
do {
try imageData!.write(to: NSURL.fileURL(withPath: "norm.png"))
} catch {
print("Unable to save file.")
}
If paragraphSpacingBefore
should put space above the second and third paragraphs, what am I doing wrong?
From what I observed, this behaviour only appears when you use the swift
command:
swift YourScript.swift
If you instead run the code in an Xcode "Command Line Tool" project, or run the code in an Xcode playground, or compile the code with swiftc
, then run it,
swiftc YourScript.swift && ./YourScript
paragraphSpacingBefore
correctly puts the spacing in the right places.
I suspect that you might need to specify an option to swift
for this to work, but I couldn't find a relevant option that is unique to swift
.
So a workaround now is simply to write a new bash/zsh script that runs:
swiftc YourScript.swift && ./YourScript