we have a problem displaying text with german umlaute with the function ShowTextAtPoint in CGBitmapContext. The umlaute characters are not displayed.
We tried to convert Code from XCode:
CGContextSelectFont(MyBitmapContext, FontName, 24, kCGEncodingMacRoman);
CGContextShowTextAtPoint(MyBitmapContext, x, y, [caption cStringUsingEncoding:
NSMacOSRomanStringEncoding], [caption length]);
to MonoTouch:
MyBitmapContext.SelectFont(FontName, 24, CGTextEncoding.MacRoman);
MyBitmapContext.ShowTextAtPoint(x, x, caption , caption.Length);
Thanks a lot for any help.
Frank
The problem is that CoreGraphics APIs for CGContext do not support rendering UTF8 code, it is limited to the text encoding in MacRoman (as you showed in your sample).
The fix is to use the UIKit functions instead, to do this, you can change your code to be like this:
UIGraphics.PushContext (mBmpContext);
mBmpContext.SetRGBFillColor(1f,1f,1f,1f);
var font = UIFont.FromName ("Arial", 30);
using (var nsstr = new NSString ("äöü ÜÖÄ")){
nsstr.DrawString (new PointF (10, 400), font);
}
UIGraphics.PopContext ()
Related
With the release of iOS 9.1, we got a lot of cool new emoji like taco (🌮)! I'm working on an application where I'd like to show the new emoji characters on devices where they are supported but keep them hidden on devices where they are not. Is there a way to determine if a given emoji character (contained in an NSString) can be rendered on the device the app is running on?
After quite a bit of digging on SO and experimenting I've come up with a solution which I will post as an answer below, but please let me know if there's a better way.
In response to the Swift question above, here's a Swift version based largely on an answer in this question:
Get surrogate pairs from an emoji
func isEmojiSupported(emoji: String) -> Bool {
let uniChars = Array(emoji.utf16)
let font = CTFontCreateWithName("AppleColorEmoji", 0.0, nil)
var glyphs: [CGGlyph] = [0, 0]
return CTFontGetGlyphsForCharacters(font, uniChars, &glyphs, uniChars.count)
}
// Determine if the emoji character provided in the string can be rendered on this OS version
+ (BOOL)isEmojiSupported:(NSString *)emoji
{
NSData *data = [string dataUsingEncoding:NSUTF32LittleEndianStringEncoding];
UTF32Char emojiValue;
[data getBytes:&emojiValue length:sizeof(emojiValue)];
// Convert UTF32Char to UniChar surrogate pair.
// Found here: http://stackoverflow.com/questions/13005091/how-to-tell-if-a-particular-font-has-a-specific-glyph-64k#
UniChar characters[2] = { };
CFIndex length = (CFStringGetSurrogatePairForLongCharacter(emojiValue, characters) ? 2 : 1);
CGGlyph glyphs[2] = { };
CTFontRef ctFont = CTFontCreateWithName((CFStringRef)#"AppleColorEmoji", 0.0, NULL);
// If we don't get back any glyphs for the characters array, it's not supported
BOOL ret = CTFontGetGlyphsForCharacters(ctFont, characters, glyphs, length);
CFRelease(ctFont);
return ret;
}
I am building a .NET/C#/MVC system that uses Bootstrap and iTextSharp.
I have two Glyph font icons that I would also like to use when generating a PDF document using iTextSharp.
The only way I know to include and image in a PDF, is to designate a stream to an image:
Stream imageStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Onlineeksamen.Web.Resources.ios7-phone1-icon.png");
Image image = Image.GetInstance(imageStream);
The Glyph icons are available in following files:
fonts\glyphicons-halflings-regular.eot
fonts\glyphicons-halflings-regular.svg
fonts\glyphicons-halflings-regular.ttf
fonts\glyphicons-halflings-regular.woff
I now have following sample based on the comment from jme but it doesnt work - I assume that the icons are characters in the font:
outputStream = new MemoryStream();
document = new Document(PageSize.A4, margin, margin, margin, margin);
pdfWriter = PdfWriter.GetInstance(document, outputStream);
document.Open();
pdfContentByte = pdfWriter.DirectContent;
PageHeight = document.PageSize.Height;
pdfContentByte.SetColorStroke(BaseColor.BLACK);
string fontFile = String.Format("{0}fonts\\glyphicons-halflings-regular.ttf", HostingEnvironment.ApplicationPhysicalPath);
BaseFont customfont = BaseFont.CreateFont(fontFile, BaseFont.CP1252, BaseFont.EMBEDDED);
pdfContentByte.SetFontAndSize(customfont, 12);
pdfContentByte.BeginText();
pdfContentByte.SetTextMatrix(100, PageHeight.Value - 100);
pdfContentByte.ShowText("This should be glyphs");
pdfContentByte.EndText();
document.Close();
return outputStream.ToArray();
Thank you in advance
Soeren D.
In my game I use cclabelttf to display the score the player made. It was working fine back in the end of July, I've changed nothing in my code, but there was a:
- IOS upgraded (6.1 to 7.0)
- OSX updated
- cocos2d-x
- Xcode update
I'm not using helvetica fonts.
I have a floating text to show the score, if I kill a terrorist a "+10" string floats up and than disappears, if I write " +10 " then it's visible, otherwise it's not.
I've tried to change the text alignment in ccimage.mm, from UITextAlignmentLeft to the same with NS,
uncomment these lines:
if( [font isKindOfClass:[UIFont class] ] )
{
[str drawInRect:CGRectMake(0, startH, dim.width, dim.height) withFont:font lineBreakMode:(UILineBreakMode)UILineBreakModeWordWrap alignment:align];
}
I've read these modifications on the cococs2d-x forum, there was a bug back than, and these was the solution. No luck for me.
Weird part is on my gameScene one of the labels is visible, but only on iPhone simulator, but starting from this, I think it must be an alignment/wrapping problem.
Met the same issue, found a solution works for me, try this.
Modify _initWithString in CCImage.mm, at line:
CGContextRef context = CGBitmapContextCreate(data, dim.width, dim.height, 8, dim.width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
change it to:
CGContextRef context = CGBitmapContextCreate(data, (int)dim.width, (int)dim.height, 8, (int)dim.width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
Just three (int) casts.
maybe you can try it like this:
CCLabelTTF* YouClassName::stringNewLine(string orgStr,CCSize sizeTable,const char* fontName,float fontSize){
CCLabelTTF *m_label_content = CCLabelTTF::create( "hello", fontName, fontSize ,sizeTable, kCCTextAlignmentCenter, kCCVerticalTextAlignmentCenter);
m_label_content->setString(orgStr.c_str());
return m_label_content;
}
and use it like this
CCLabelTTF * ttf = stringNewLine("test",CCSizeMake(200,200), "Arial", 28);
I'm just trying to overlay a text in a UIImage (using CGContext) but it doesn't show the text I specified. In this code I'm giving as the text argument "Hello" but it shows "eÉääc". I don't know what's happening I think the characters are displaced but I don't know how to solve it.
This is my code:
UIGraphicsBeginImageContextWithOptions(image.size, YES, 0);
CGContextRef c = UIGraphicsGetCurrentContext();
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
CGContextSetTextMatrix(c, CGAffineTransformMake(1.0, 0, 0, -1.0, 0, 0));
CGContextSelectFont(c, "ArialMT", 50, kCGEncodingFontSpecific);
CGContextSetRGBStrokeColor(c, 255, 0, 0, 1);
CGContextSetRGBFillColor(c, 255, 0, 0, 1);
CGContextSetCharacterSpacing(c, 2);
CGContextShowTextAtPoint(c,100,100, "Hello", 5);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I'm using the Spanish Keyboard (I don't know if this matters) and the iPad (where I'm testing the application) is in Catalan.
CGContextShowTextAtPoint() interprets the given text according to the specified encoding parameter of CGContextSelectFont. You have chosen kCGEncodingFontSpecific, which is the font built-in encoding (whatever that might be).
The only other choice is kCGEncodingMacRoman:
CGContextSelectFont(c, "ArialMT", 50, kCGEncodingMacRoman);
Then your text should display correctly, as long as you use only characters from the ASCII character set.
For non-ASCII characters, you have to convert the string to the MacRoman encoding, see e.g. https://stackoverflow.com/a/13743834/1187415 for an example.
Note that CGContextShowTextAtPoint cannot display general Unicode strings, and even has problems with the Euro (€) character. The drawAtPoint:withFont: method of NSString does not have these limitations.
Several posts have noted difficulties with getting an exact height out of CTFramesetterSuggestFrameSizeWithConstraints, and here, (framesetter post), #Chris DeSalvo gives what looks like the definitive fix: add a paragraph style setting with the correct line spacing adjustment.
DeSalvo gets his “leading” by removing UIFont’s ascender and descender from its lineHeight. I wondered how that would compare to CTFontGetLeading.
I worked with fonts created like this:
CTFontRef fontr = CTFontCreateWithName((CFStringRef)#"Helvetica Neue", 16.0f, NULL);
UIFont *font = [UIFont fontWithName:#"Helvetica Neue" size:16.0f];
The values were quite different:
0.448 CTFontGetLeading
2.360 DeSalvo’s formula: UIFont lineHeight - ascender + descender
Here are some other UIFont values:
21.000 UIFont’s lineHeight
15.232 UIFont’s ascender (Y coord from baseline)
-3.408 UIFont’s descender (Y coord from baseline)
08.368 UIFont’s xHeight
And here are the CTFont values that Ken Thomases inquired about:
11.568001 CTFontGetCapHeight
08.368 CTFontGetXHeight
-15.216001, -7.696001, 38.352001, 24.928001 CTFontGetBoundingBox
15.232 CTFontGetAscent
03.408 CTFontGetDescent (class ref says "scaled font-descent metric scaled according to the point size and matrix of the font reference" -- which apparently means that it is the absolute value of the Y coordinate from the baseline?)
I note that UIFont previously had a property specifically for “leading,” but it has been deprecated and we are advised to use lineHeight instead. So UIFont considers leading to be 21 and CTFontRef .448 for the same font? Something’s not right.
Three questions:
Is “leading” really what is meant by kCTParagraphStyleSpecifierLineSpacingAdjustment?
If so, which method/formula should I use to get it?
If not, what should I use for the line spacing adjustment?
I too ran into this and here is the code that worked in a real project:
// When you create an attributed string the default paragraph style has a leading
// of 0.0. Create a paragraph style that will set the line adjustment equal to
// the leading value of the font. This logic will ensure that the measured
// height for a given paragraph of attributed text will be accurate wrt the font.
- (void) applyParagraphAttributes:(CFMutableAttributedStringRef)mAttributedString
{
CGFloat leading = CTFontGetLeading(self.plainTextFont);
CTParagraphStyleSetting paragraphSettings[1] = {
kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof (CGFloat), &leading
};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(paragraphSettings, 1);
CFRange textRange = CFRangeMake(0, [self length]);
CFStringRef keys[] = { kCTParagraphStyleAttributeName };
CFTypeRef values[] = { paragraphStyle };
CFDictionaryRef attrValues = CFDictionaryCreate(kCFAllocatorDefault,
(const void**)&keys,
(const void**)&values,
sizeof(keys) / sizeof(keys[0]),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
BOOL clearOtherAttributes = FALSE;
CFAttributedStringSetAttributes(mAttributedString, textRange, attrValues, (Boolean)clearOtherAttributes);
CFRelease(attrValues);
CFRelease(paragraphStyle);
self.stringRange = textRange;
return;
}
Answers to the 3 questions I had above:
Yes, “leading” really what is meant by kCTParagraphStyleSpecifierLineSpacingAdjustment. Or at any rate, it works as expected.
Use CTFontGetLeading(fontRef) to get the font's normal leading, or plug in whatever value (as a CGFloat) you choose.
N/A.
Answers 1 and 2 work: Specifying a leading value in a paragraphStyle attribute of your attributed string will enable the Core-Text framesetter to calculate its height exactly.
There are two caveats:
If you try to calculate heights incrementally, one string at a time, each string containing an initial line break, framesetter will consider that line break to represent an entire line, not just the leading. If you want the height of the concatenated strings, you have to feed that concatenation to the framesetter. Of course, you could keep track of the incremental height differences, but there's no way to avoid having framesetter recalculate the earlier string dimensions.
CATextLayer ignores spacing adjustments (and other attributes). If framing per exact string height is an issue, you must draw direct to a CALayer.
And there is one mystery: What is going on with UIFont's deprecated leading? Leading and lineHeight are two distinct things.