In general, the higher level your graphics API, the harder it is to get horizontal and vertical lines to draw on the physical pixels. At the frame buffer level it is trivial. Cocoa and UIKit it is possible with some effort. SwiftUI it is impossible (you will end up using the escape hatch to Cocoa or UIKit). HTML is hopeless.
When printing meant writing some Postscript it was a little work, but doable. Getting it onto a printer through a modern printer API is essentially impossible.
Fundamentally this is why most graphs you see online look like they were drawn with a worn out felt tip marker. It hides the sins at the expense of limiting data density and precision.