Bad kerning when using -[NSString drawInRect: withAttributes:] - objective-c

When using -[NSString drawInRect:withAttributes:], mainly when using the built-in Helvetica Neue but also with other fonts, the kerning is really bad. However, when the same string is rendered in Text Edit (which uses NSTextView) the kerning is great. Consider these two strings:
For small point sizes, the first case (rendered in Cocoa) is nearly illegible, while the second case (from Text Edit) is much better. I don't think that kerning information is being used at all here. If I apply the NSKernAttribute with a value of 0.0 (which according to the documentation turns off kerning) I get the same result, the one at the top.
I also tried using Core Text with CTLineDraw, but still got the bad kerning. So my question is, is there anything special I need to do to enable kerning in the Cocoa text system? If not, how does NSTextView apply kerning?

The top example is 'tighter' and the bottom one is 'looser' see -[NSTextView tightenKerning], -[NSTextView loosenKerning]. Here Apple is confusingly referring to what everyone else calls 'Tracking' as 'Kerning' ie. a constant amount of additional space (positive or negative) uniformly applied between each glyph, after the 'character advance' specified in the font, to make text appear, well, tighter or looser.
The default 'tightness' or 'looseness' is a property of the rendering engine, not the font, and could easily be different between different OSX versions, apps or UI elements.
In a font, the kerning table is for adjustments to the character advance needed by specific pairs of glyphs, eg, in my hypothetical font: 'AV' is listed as a kerning pair - the 'A' should have a smaller advance when the character following it is a 'V'.
The OSX fonts Helvetica and HelveticaNeue (and many of the other fonts) have no kerning information at all, so you are right that no kerning information is being used in your examples.
If the font has no Kerning info, your question "How do i enable kerning in the Cocoa text system?" doesn't make sense or doesn't mean what you think it means (?).

Related

NSTextField get default margin dimensions

I`ve got several programmatically created NSTextField-s, used as static text controls. The algorithm that creates them sets their dimensions via setFrame: and assumes that they have zero padding between the text and the upper right corner of the control, which is not the case, so the text is getting clipped.
At first I began researching the topic of zero padding for NSTextField-s but quickly realized that this approach requires subclassing. It would be much easier for me than that if I could just use some method to obtain the padding dimensions and adjust the bounding rectangle accordingly.
My question is: what`s the name of that method?
[UPD:] Seems to be alignmentRectInsets, however it`s not available on macOS 10.6 — so I`d like to know if there is a similar method for 10.6.

What is PDF stroking, non-stroking and filling?

I've just started using Apache PDFBox and I'm completely baffled as to what is meant by stroking, non-stroking and filling when applied to text and lines.
Please can someone point me to a reference / guide which explains what these terms mean (for beginners) and what the difference is between them.
Its pretty simple. Consider a rectangle located at 0,0 and 50 units wide and high. That is described as a path with vertices at 0,0 0,50 50,50 and 50,0
Now, if you stroke the path (imagine drawing along the path using a pen) with black. What you get is a black square, the interior of the square is whatever was on the paper before you drew the border (probably nothing, so white).
If you fill the path, you get a filled in square, but no border drawn.
If you fill and stroke the path you get a filled in square with a border. Because the fill and stroke colours can be different you can have the square filled in one colour and the border drawn in another.
See the PDF Reference, section 4.4 "Path Construction and Painting"
Update (by -kp-)
I've copied the following table from the official PDF-1.7 specification:
This table shows the different text rendering modes. Here too, you can stroke or fill or do both to glyph shapes. You can even do neither stroke nor fill, but still define the shapes: that is, you get invisible text -- a very useful mode for placing OCR-ed text on top of a scanned image! It makes the text searchable, copy'n'paste-able and screen-reader aware.
I am currently writing a book The ABC of PDF with iText that introduces you to all these principles.
You are talking about the "Graphics State" and syntax that is used to define objects on a page. This syntax is stored in content streams.
Ignoring "Text State" (a subset of "Graphics State") for the moment, the idea is that you create paths and shapes (shapes are closed paths). These path and shapes can be drawn using stroke and fill operators. If you fill a path, you need to define whether you're using the non-zero winding rule or the even-odd rule (if you've studied geometry at college level, you've already encountered these rules).
Stroke and fill operators will use the colors of the current graphics state. Lines will be drawn using the stroking color. Shapes will be filled using the non-stroking color.
There's much more info in the free ebook you can download from Leanpub.

PDF Low-level: Invert colors within coordinates

Is it possible to invert the colors within a box (4 sets of coordinates) on a page from within the page's content object code?
My pages consist of simple B&W JBIG2 images and I wish to make the white black and the black white within a small box to highlight something.
As mkl suggests, you may extract the images and change their bits - this might prove to be a little bit of work however. There might be another useful approach here, specifically useful because it would work regardless of what the underlying objects are.
It is possible in PDF to add a transparent object (for example a rectangle) over all underlying objects. In your case you would create a rectangle that you put on top of the images you already have in the page stream.
If you paint this rectangle in white, set it to transparent and choose "Difference" as the transparency blending mode, the net effect should be that the colors underneath your rectangle are inverted.
From the PDF specification: "Painting with white inverts the backdrop colour; painting with black produces no change."
This may be the quickest and most painless way to accomplish what you are looking for...

Is it possible to remove the background of a text block in pdf using ghostscript

I am trying to convert a pdf into tif using ghost script. Is it possible to remove the background (grey color) of a text block (back font color) in a pdf using ghost script? I would like to replace the grey background to white.
Appreciate your help!!
I don't think you'll get a generic solution to your problem because there are many different ways such a background may be coded in your PDF and there is no sure way to distinguish such a background from a rectangular form of some vector image.
PDF essentially offers a set of tools for positioning glyphs and vector graphics in some rectangle (page) to display and some additional tools to add some interactivity (e.g. forms). Thus, a colored background in a PDF generally is created by drawing a line along the edge of the area of the background, fill this form with the desired color, and position glyphs and graphics (text and images) atop it. There are other operators, too, which can be used, though, and many variants of their use, and generally the form created is not marked as background.
In the answer Dingo refers to in his comment a rectangle covering the whole page, actually even a bit more (in case of a fairly common choice of a media box), is drawn (m: move to a corner; 4*l: draw the 4 edge lines; h: close the path; f fill the form).
Thus, please make the PDF in question available for inspection, maybe there is some specific solution for your file.

Calculating height of NSString with custom font

I'm trying to solve this problem for a week now and I have tested a lot of ideas that I had on my mind but I'm unable to properly calculate size of the NSString with custom font.
I have UITextView which contains text and one UIView on which I draw line numbers for the lines in UITextView. The problem is that NSString UIKit Additions are ignoring tab width in calculation of size of the NSString.
Here on picture you can see that clearly on line 7, which is line with line break when rendered in UITextView, and after that all lines are affected.
Font that I'm using is Adobe Source Code Pro.
I have tried all methods from NSString UIKit Additions without success.
sizeWithFont
sizeWithFont:forWidth:lineBreakMode:
sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:
I have also tried to replace all tabs in string with four spaces, it helps, but still it doesn't work all the time. For some lines it helps but for some it doesn't.
Any suggestions how to calculate NSString height properly? CoreText maybe?
One small note. I have tried to solve this also with using Geometry hit testing methods from UITextInput Protocol and while they are working, cpu load is 100% on simulator, so on real device it's going to kill the app, specially if I load file that is about 1500+ lines of code.
And here is the gist with code that I'm using for LineNumbersView.m.
Assuming UITextView and Core Text always exactly agree then the latter is definitely a solution, though it's not desperately straightforward for this problem.
You'd:
create an attributed string of the text in the main view, having set the appropriate font across the entire range;
create a suitable framesetter for the attributed string (using CTFramesetterCreateWithAttributedString);
create a CGPath that describes the drawing area that the string will be drawn to (either as a UIBezierPath and then getting the CGPath property or by creating one and using CGPathAddRect);
hence create a frame from the framesetter plus the path plus the subrange of the string you're interested in, which will likely be all of it (see CTFramesetterCreateFrame);
from the frame you can then obtain a CFArray of the individual lines it would output (using CTFrameGetLines), though these are the on-screen typeset lines rather than your source lines;
for each line you can get the range of the original string that it contains (using CTLineGetStringRange), allowing you to determine which begin immediately after your original newline characters rather than due to word wrap;
you can also get a C array of CGPoints where each represents the origin of an on-screen line (CTFrameGetLineOrigins); by using what you learn in (6) to look up positions in that you can get the on-screen origins of the relevant lines.
For added fun, the pixel output of Core Text is identical on OS X and on iOS. However OS X considers the screen's original to be the lower left corner, like graph paper. iOS considers it to the top left corner, like English reading order. The roughly worded net effect is that on iOS Core Text draws upside down. So you'll need to take that into account. In iOS terms you'll apparently see the first line as being at the very bottom of your frame, the second as being one line above that, etc. You'll need to flip those coordinates.
It'll probably end up being just a hundred or so lines of code even though you're jumping through so many hoops.