I'm using a series of CGContext commands to create text to be used for generating a pdf file:
CGContextSelectFont (pdfContext, "Helvetica", 14, kCGEncodingMacRoman);
CGContextSetTextDrawingMode (pdfContext, kCGTextFill);
CGContextSetRGBFillColor (pdfContext, 0, 0, 0, 1);
CGContextSetTextMatrix(pdfContext, CGAffineTransformMake(1.0,0.0, 0.0, -1.0, 0.0, 0.0));
I would like to right justify the text though. Any idea on how to do this? For example, is there a method that allows you to specify the origin as the top right corner of the text, not the top left?
CGContextShowTextAtPoint (pdfContext, x, y, text, strlen(text));
Thanks!
Right and center justifications are not supported. In order to draw right aligned text, you need to compute the text width, subtract the text width from the right aligned x and then draw the text at the computed position.
Related
I'm creating a mask based on DeviceGray color space based image.
What basically I want to do is to change all sorts of gray (beside black) pixels into white and leave black pixels as they are.
So I want my image to be consisted with black and white pixels.
Any idea how to achieve that using CoreGraphics means ?
Please dont offer running all over the pixels in the loop
Use CGImageCreateWithMaskingColors and CGContextSetRGBFillColor together like this:
CGImageRef myMaskedImage;
const CGFloat myMaskingColors[6] = { 0, 124, 0, 68, 0, 0 };
myColorMaskedImage = CGImageCreateWithMaskingColors (image,
myMaskingColors);
CGContextSetRGBFillColor (myContext, 0.6373,0.6373, 0, 1);
CGContextFillRect(context, rect);
CGContextDrawImage(context, rect, myColorMaskedImage);
By the way, the fill color is mentioned at the CGImageCreateWithMaskingColors discussion.
I'm trying to add a little red line on the bottom of my UIView.
I want the line to be a 1px line.
Can someone tell me why the following code:
- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetRGBFillColor(currentContext, 0.0f, 0.0f, 0.0f, 1.0f);
CGContextFillRect(currentContext, RECT(0, 0, rect.size.width, rect.size.height - 8));
CGContextSetLineWidth(currentContext, 1);
CGContextSetRGBStrokeColor(currentContext, 1.0f, 0.0f, 0.0f, 1.0f);
CGContextBeginPath(currentContext);
CGContextMoveToPoint(currentContext, 0, rect.size.height - 7);
CGContextAddLineToPoint(currentContext, rect.size.width, rect.size.height - 7);
CGContextStrokePath(currentContext);
CGContextRestoreGState(currentContext);
}
Draws a line that spans 2px in height?
The integral coordinates indicate places half-way between pixels; that is, (0,0) is in the upper-left corner, above and to the left of the upper-left pixel; similarly, (1,0) is between the first and second pixels; finally, (0.5,0.5) is at the center of the upper-left pixel.
According to the documentation for CGContextSetLineWidth, "when stroked, the line straddles the path, with half of the total width on either side." Thus, if the path is lying precisely in between the pixels, the line will be stroked half on one row of pixels, half on the other.
Hence, to get a sharp pixel line, you must offset your coordinates by half a pixel: for your x coordinate, use rect.size.height - 7.5 instead of - 7.
By the way, when drawing rectangles, it is handy to use CGRectInset(rect, 0.5, 0.5) to achieve this.
Do you use an iPhone 4? The iPhone 4 uses a coordinate system with a scale factor of 2. So you would need to set the line width to 0.5 in order to get what you want.
(The coordinate system is set up that way so the same code produces the same output on all models.)
Lines are by default drawn antialiased (unless you configure otherwise). Thus any line that's not strictly vertical or horizontal and starting and ending on a pixel will likely partially cover multiple pixels in some rows and/or columns, making it look like a wider grey line instead of a thin higher-contrast line.
I'm using CGImageCreateWithImageInRect to do a magnifying effect, and it works beautifully, except when I get close to the edges of my view. In that case, clipping causes the image to be distorted. Right now I grab a 72x72 chunk of the view, apply a round mask to it, and then draw the masked image, and a circle on top.
When the copied chunk is near the edge of the view, It winds up smaller than 72x72 because of clipping, and then when it's drawn in the magnifying glass it gets stretched out.
When the touch point is close to the left edge, for example, I would like to create an image where the left part is filled with a solid color, and the right half contains part of the view that's being magnified. Then apply the mask to that image and add the overlay on top.
Here's what I'm doing now. imageRef is the image being magnified, mask is a round mask, and overlay is a circle to mark the edges of the magnified region.
CGImageRef subImage = CGImageCreateWithImageInRect(imageRef, CGRectMake(touchPoint.x - 36, touchPoint.y - 36, 72, 72));
CGImageRef xMaskedImage = CGImageCreateWithMask(subImage, mask);
CGContextRef context = UIGraphicsGetCurrentContext();
CGAffineTransform xform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextConcatCTM(context, xform);
CGRect area = CGRectMake(touchPoint.x - 84, -touchPoint.y, 170, 170);
CGRect area2 = CGRectMake(touchPoint.x - 80, -touchPoint.y + 4, 160, 160);
CGContextDrawImage(context, area2, xMaskedImage);
CGContextDrawImage(context, area, overlay);
I solved this by using CGBitmapContextCreate() to create a bitmap context. Then I drew the captured area into a smaller area of this context, and created an image from it with CGBitmapContextCreateImage(). That was the missing piece of the puzzle.
How to draw a text in MKCircleview? i have to print a text on the overlay of MKMapview. is it possible?
Within this section of my overlay view subclass of MKOverlayView:
- (void)drawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)context
You should do /something/ like this:
CGContextSetTextMatrix(context, CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
// Setup text rendering stuff.
CGFloat fontHeight = rect.size.height/2.0f;
CGContextSelectFont(context, "Thonburi", fontHeight, kCGEncodingMacRoman);
CGContextSetRGBFillColor(context, 0, 0, 0, 1);
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
// Set string.
const char *text = [[NSString stringWithFormat:#"%d",clusters[i].count] UTF8String];
int len = strlen(text);
// Render text invisible.
CGContextSetTextDrawingMode(context, kCGTextInvisible);
CGContextShowTextAtPoint(context,
0,
0,
text,
strlen(text));
// Get actual point it was renderered.
CGPoint pt = CGContextGetTextPosition(context);
// Set text to visible.
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
// Actually render text.
CGContextShowTextAtPoint(context,
rect.origin.x + (0.5f * rect.size.width) - (0.5f * pt.x), // Origin + half the width - half the width of text == center aligned text?
rect.origin.y + (1.25f * fontHeight), // Hack. 1 1/4 font height (which is half rect height) == center vert. aligned text.
text,
len);
This will render the text centered in the middle of the circle.
A few warnings about the above code... it's actually taken from a subclass of MKOverlayPathView within which I draw many many circles on the overlay view in different locations and thus needed a fairly dynamic method of drawing the text in the right place. Thus the code will probably not be a drop in solution for you and a bit more complicated than you actually need. However it should point you in the right direction.
Please bear in mind that having more than a couple of overlay views on a mapkit is a path to insanity with random crashes and stack traces as the layers consume more and more ram. Thus if you have more than a small handful of overlays I would recommend you also go down the MKOverlayPathView route.
I banged my head on the desk for almost a month before I discovered why it was crashing so much at random times.
My code is for clustering, placing text in the middle of each circle with the number of items in that cluster.
I am attempting to fill some text with a gradient-fill, where by I set the text drawing mode to clipping, and then paint a gradient-fill.
The problem is, whenever I set the text drawing mode to clip, every character of the text string is placed on top of each other, rather than being painted in a sequence to form a word - it is most bizarre!
My code looks like this:
CGRect r = CGRectInset(self.frame, 55, 8);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat components[8] = {44/255, 54/255, 66/255, 1.0
,75/255, 92/255, 111/255, 1.0};
CGFloat locations[2] = {0, 1};
// draw the text's gradient fill
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 2);
CGContextSetTextDrawingMode(context, kCGTextClip);
[monthString drawInRect:r withFont:f lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentCenter];
CGContextFillRect(context, CGRectMake(0, 0, 320, 20));
It appears that the UIKit NSString additions that let you do drawInRect:withFont: and the like don't play well with the kCGTextClip drawing mode. I've seen the same behavior, and in this answer I provide code to fill text with a gradient using pure Quartz drawing calls. The downside to this approach is that you are limited to the MacRoman text encoding, which lacks support for many Unicode symbols.