AttributedString boundingRectWithSize vs drawInRect
in HelpViewer NoteCells are drawn in attachments.
First, the cell is sized and using pseudo-infinity height, the best width is determined:
size.width -= leadingMargin*2;
size.height = 9999.0;
if (size.width <= 0)
size.width = [textView bounds].size.width;
noteSize = [_note boundingRectWithSize:size options:0].size;
then, later, it is drawn:
noteRect.origin = noteOrigin;
noteRect.size = noteSize;
[_note drawInRect: noteRect];
amazingly, this fails for certain strings. The issue was found with single-line strings where the string gets just truncated.
At a first glance, boundingRectWithSize returns a decent-wide enough size, it looks that drawInRect is not following it. Also, the error doesn't seem constant.
Attributed String:
<b>{NSFont = "<NSFont: 0x562750b36720> DejaVuSansMono 12.000 0.000 0.000 12.000 0.000 0.000 P 0"; }votre texte en gras{NSFont = "<NSFont: 0x562750a8a120> TrebuchetMS-Bold 12.000 0.000 0.000 12.000 0.000 0.000 P 0"; }</b>{NSFont = "<NSFont: 0x562750b36720> DejaVuSansMono 12.000 0.000 0.000 12.000 0.000 0.000 P 0"; }
Size:
resizeWithTextView size: {width = 336; height = 9999} noteSize: {width = 158; height = 15}
Debug shows us reasonable text with a width of 158, yet it clips:
empirically, I determined the error to be more than 10, less or equal to 15. Adding 15 to the width, makes the string (and others) draw. I suppose this is due to even off-by-one character causing a newline which is then clipped, since the height remained one-line.
We did some investigation and found out the issue has to do with magins. The code sets:
[paragraph setFirstLineHeadIndent: leadingMargin];
setting this - which affects the first line, makes the text be drawn right by the said margin (leading space) but somehow it appears that this amount is exact missing when boundingRectWithSize is called.
This is quite strange, since
drawInRect calls:
prepare_attributed_string(self);
c = cache_lookup(YES, rect.size, use_screen_fonts());
draw_in_rect(c, rect);
and boundingRect calls:
prepare_attributed_string(self);
c = cache_lookup(hasSize, size, YES);
result = c->usedRect;
Given that the size passed is later rect.size by NoteCell code and use_screen_fonts() should be true since text is horizontal and an identity transformation is supposed, the two should lead to identical results
The amound of "correction" to be added in this NoteCell example if the leadingMargin is set is 8. If also trailingMargin is set, then 12, which is exactly 8+4
This proves that both trailing and leading margins are ignored!