This is an absolute pain, but it can be done.
You need to get all the lines in the frame using CTFrameGetLines() , check if their character range is in the range you are looking for using CTLineGetStringRange() , use CTLineGetTypographicBounds() to find out how big the render as line is and use CTLineGetOffsetForStringIndex() to determine the actual position of the start and end character of the range (if the string is just a sub-range of the desired range).
Combining all this and adding displacements and heights, and you can get what you want. Please note that CTLineGetImageBounds() does not work without a graphical context (and, from what I find, it is quite expensive), and this is not necessary to solve this problem.
Sean
source share