Is there a way for hit-testing text? That is for example if I draw text "Hello graph!"" on the screen, within a bounding box, how can I tell the dimension and position of these blank rectangles (blank spaces):
The blank rectangle above the letter "e"
The blank rectangle that spans from above the letter "o" up to above the letter "p"
The blank rectangle below the letter "H" up to the space before "g"
etc, you get the idea.
In other words how to find out which areas occupied by actual text and which areas that are really blank.
The platform (graphics library) is Cocoa on Mac OS X, the character set is Unicode (which probably rules out raw CoreGraphics API?), and the font can be anything that Cocoa can use.
Thanks in advance
You can get the rect of a character in a NSTextView like this:
//Get the range of characters, which may be different than the range of glyphs
NSRange range = [[textView layoutManager]glyphRangeForCharacterRange:NSMakeRange(charIndex, 0) actualCharacterRange:NULL]
//Get the rect of the character
NSRect rect = [[textView layoutManager]boundingRectForGlyphRange:range inTextContainer:[textView textContainer]];
Then, get the NSGlyph that you want:
NSGlyph glyph = [[textView layoutManager]glyphAtIndex:range.location];
And draw it in an NSBezierPath:
NSBezierPath *path = [NSBezierPath bezierPath];
[path appendBezierPathWithGlyph:glyph inFont:myFavoriteFont];
Next, query the path for its bounds:
NSRect actualRect = [path bounds];
You can then compare those two rectangles.
Have a look at the NSLayoutManager Class Reference, the Text System Overview, and the Text Layout Programming Guide.
You could draw the text over fully-transparent bitmap (via CGBitmapContext), then check that bitmap if a particular point is transparent or not.
If you need a list of rectangles (that is called region in 2d graphics), you'll have to implement that yourself or google for a library, as CoreGraphics and Cocoa don't have regions (at least documented).
Related
I cannot seem to find this and hope it is a FAQ somewhere.
How can I get the minimum NSRect needed to draw an NSAttributed string on OS X?
I am doing an overlay borderless window, but I want to constrain the size based on what is needed to display the string.
use NSTextContainer and NSLayoutManager.
More from Apple here:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html
Is it possible to convert an NSGradient to an NSColor
- (void) viewWillDraw {
NSGradient *grad = [[NSGradient alloc] initWithStartingColor:[NSColor lightGrayColor] endingColor:[NSColor darkGrayColor]];
[super setBackgroundColor:*gradient*;
}
This is my method, I want to be able to pass the NSGradient in as an NSColor, which obviously i cant, is there any way to convert it to one?
On 10.8, you can create, in the following order:
A block that draws the gradient however you like.
An image that is backed by the block.
A color that repeats the image as a pattern.
In this way, you can create a color that looks like anything, including a gradient.
That said, this may not work correctly with window resizing if you try to have the gradient adapt to the size of the background (by using the rect passed to the block) and the background is of a text view in a scroll view. (When I tried it awhile back, the pattern didn't redraw the block; it simply tiled, which looked weird in at least one dimension.) If either your gradient or your window is fixed in size, then you will not have that problem.
NSGradient is not Convertible to NSColor.
The NSGradient class provides support for drawing gradient fill
colors, also known as shadings in Quartz. This class provides
convenience methods for drawing radial or linear (axial) gradients for
rectangles and NSBezierPath objects.
As you want to set the viewBackground to to an effect (Gradient effect) you need to do as:
[grad drawInRect:<the rect of your view> angle:270]; //angle is upto your requirement,
I have an app that currently has this line:
[myView setWantsLayer:YES];
In order to draw a GUI element via NSBezierPath. This line is required, otherwise when the user types in an adjacent (and overlapping) NSTextField, the contents of myView shudders.
I discovered that calling CoreAnimation loads the OpenGL framework, but does not unload it. See this question.
I think I can get around this by drawing the NSBezierPath to NSImage and then to display the NSImage in lieu of the NSBezierPath, but I haven't found a single source that shows me how to go about this.
Edit:
I should note that I want to save this BEFORE The NSBezierPath is displayed - so solutions that draw an existing view to an NSImage are not useful.
Question:
Can someone point me in the right direction for converting NSBezierPath to an NSImage?
You can draw anything directly into an NSImage, and you can create a blank NSImage. So, create an image whose size is the size of the bounds of the path, translate the path so that it's at the origin of the image, and then lock focus on the image, draw the path, and unlock focus.
I am trying to construct a graph using cocoa.To display the points on x -axis and y- axis i used methods called drawATPoint and drawinRect which allows to draw apoint inside rect not out side .
So please mention if there is any solution to display the points.I am using the following code.
NSTextStorage *textStorage = [[NsTextStorage alloc]initWithString:#"0.0"];
[textStorage drawAtPoint:NSMakePoint(0,0)];
Maybe you need to create a RECT big enough to draw inside and then draw the graph inside the rect say -20 on all axis so that you give the impression the rect is smaller?
Your question doesn't make sense. You want to tell the string to draw “anywhere but in this rect”? Where should it draw, then?
You need to tell it where to draw. This means you need to give it either a point to start from or a rect to draw within.
If you have a rect and you want to draw the text somewhere outside of that rect, then decide where outside of that rect, and then tell the string to draw there.
Is this possible to get the coordinates of where the text drawn in standard (not custom) Cocoa controls? Actually, I need a baseline of the text, the y-axis offset value (relative to the y-origin of the view’s frame rectangle).
This is what the Interface Builder shows on design pane when Layout->Show Layout Rectangles selected.
Unfortunately, there isn't a single solution that works for all controls and cells. You should be able to get a good approximation of this information with these methods:
-[NSCell titleRectForBounds:]
-[NSCell font]
-[NSFont ascender]
Here's some code that works for NSButton/NSButtonCell
NSRect titleRect = [[button cell] titleRectForBounds:[button bounds]];
CGFloat baseline = ceil(NSMinY(titleRect) + [[[button cell] font] ascender]);
At this point, baseline is in the button's (bounds) coordinate space. You might want to convert it to some other space with -[NSView convertPoint:toView:];
Also, that "ceil" in there is an approximation. Not all controls will do that. Some might floor, or use some other rounding function. Or they might layout their title's completely differently, and this approximation won't work.