代码改变世界

转载4

2012-04-28 13:32  java环境变量  阅读(230)  评论(0编辑  收藏  举报
24、CoreText基础-字体必修课

转自:http://www.dreamingwish.com/dream-2011/coretext-ji-chu-font-basis.html

介绍一些字体的术语,以及对应的英文名称

字体(Font):是一系列字号、样式和磅值相同的字符(例如:10磅黑体Palatino)。现多被视为字样的同义词

字面(Face):是所有字号的磅值和格式的综合

字体集(Font family):是一组相关字体(例如:Franklin family包括Franklin Gothic、Fran-klinHeavy和Franklin Compressed)

磅值(Weight):用于描述字体粗度。典型的磅值,从最粗到最细,有极细、细、book、中等、半粗、粗、较粗、极粗

样式(Style):字形有三种形式:Roman type是直体;oblique type是斜体;utakuc type是斜体兼曲线(比Roman type更像书法体)。

x高度(X height):指小写字母的平均高度(以x为基准)。磅值相同的两字母,x高度越大的字母看起来比x高度小的字母要大

Cap高度(Cap height):与x高度相似。指大写字母的平均高度(以C为基准)

下行字母(Descender):例如在字母q中,基线以下的字母部分叫下伸部分

上行字母(Ascender):x高度以上的部分(比如字母b)叫做上伸部分

基线(Baseline):通常在x、v、b、m下的那条线

描边(Stroke):组成字符的线或曲线。可以加粗或改变字符形状

衬线(Serif):用来使字符更可视的一条水平线。如字母左上角和下部的水平线。

无衬线(Sans Serif):可以让排字员不使用衬线装饰。

方形字(Block):这种字体的笔画使字符看起来比无衬线字更显眼,但还不到常见的衬线字的程度。例如Lubalin Graph就是方形字,这种字看起来好像是木头块刻的一样

手写体脚本(Calligraphic script):是一种仿效手写体的字体。例如Murray Hill或者Fraktur字体

艺术字(Decorative):像绘画般的字体

Pi符号(Pisymbol):非标准的字母数字字符的特殊符号。例如Wingdings和Mathematical Pi

连写(Ligature):是一系列连写字母如fi、fl、ffi或ffl。由于字些字母形状的原因经常被连写,故排字员已习惯将它们连写。

25、准确计算CoreText高度的方法

- (int)getAttributedStringHeightWithString:(NSAttributedString *)  string  WidthValue:(int) width
{
   int total_height = 0;
   
   CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);    //string 为要计算高度的NSAttributedString
   CGRect drawingRect = CGRectMake(0, 0, width, 1000);  //这里的高要设置足够大
   CGMutablePathRef path = CGPathCreateMutable();
   CGPathAddRect(path, NULL, drawingRect);
   CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);
   CGPathRelease(path);
   CFRelease(framesetter);
   
   NSArray *linesArray = (NSArray *) CTFrameGetLines(textFrame);
   
   CGPoint origins[[linesArray count]];
   CTFrameGetLineOrigins(textFrame, CFRangeMake(0, 0), origins);
   
   int line_y = (int) origins[[linesArray count] -1].y;  //最后一行line的原点y坐标
   
   CGFloat ascent;
   CGFloat descent;
   CGFloat leading;
   
   CTLineRef line = (CTLineRef) [linesArray objectAtIndex:[linesArray count]-1];
   CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
   
   total_height = 1000 - line_y + (int) descent +1;    //+1为了纠正descent转换成int小数点后舍去的值
   
   CFRelease(textFrame);
   
   return total_height;
   
}

 

//关于line坐标位置y为下图黑线所在位置 descent为黑线下部分字体的高度

//关于字体各部分高度说明  http://ios-iphone.diandian.com/post/2012-03-29/18055023  

26、自定义拷贝、粘贴窗口

(1)、重写canBecomeFirstResponder方法

  - (BOOL)canBecomeFirstResponder{
  
  [super canBecomeFirstResponder];
  return YES;
}

(2)、创建自定义UIMenuController

  UIMenuItem *share = [[UIMenuItem alloc] initWithTitle:@"分享" action:@selector(share:)];
   UIMenuItem *email = [[UIMenuItem alloc] initWithTitle:@"邮件" action:@selector(email:)];
   UIMenuItem *print = [[UIMenuItem alloc] initWithTitle:@"打印" action:@selector(print:)];

   UIMenuController *menu = [UIMenuController sharedMenuController];
   [menu setMenuItems:[NSArray arrayWithObjects:share, email,print, nil]];
   [menu setTargetRect:self.frame inView:self.superview];
   [menu setMenuVisible:YES animated:YES];

(3)、判断显示哪个menu

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
  [super canPerformAction:action withSender:sender];
 
  if ( action == @selector(share:) || action == @selector(email:) || action == @selector(print:))
  {
      return YES;    
  }
  else
  {
      return NO;
  }
}

 

27、iOS本地推送通知方法

  
可在应用后台执行时,本地弹出推送通知,也可以定时触发推送。

- (void)applicationDidEnterBackground:(UIApplication *)application
{
   
   UIDevice* device = [UIDevice currentDevice];
   
   BOOL backgroundSupported = NO;
   
   if ([device respondsToSelector:@selector(isMultitaskingSupported)])
   {    
       backgroundSupported = device.multitaskingSupported;
   }
   if (backgroundSupported && _bgTask==UIBackgroundTaskInvalid)
   {
       UIApplication *app = [UIApplication sharedApplication];
       
       _bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
       }];  
       
       
       dispatch_async(dispatch_get_main_queue(), ^{
           
           while (app.applicationState==UIApplicationStateBackground && _bgTask!=UIBackgroundTaskInvalid  && [app backgroundTimeRemaining] > 10)  
           {
               [NSThread sleepForTimeInterval:1];
               NSLog(@"background task %d left left  time %d.", _bgTask, (int)[app backgroundTimeRemaining]);
                               
               if ([app backgroundTimeRemaining] < 580)
               {
                   UILocalNotification *localNotif = [[UILocalNotification alloc] init];
                   if (localNotif)
                   {
                       localNotif.alertBody = [NSString stringWithString:@"测试本地通知消息,后台提示功能。"];
                       localNotif.alertAction = NSLocalizedString(@"查看", nil);
                       localNotif.soundName = UILocalNotificationDefaultSoundName;
                       localNotif.applicationIconBadgeNumber = 1;            
                       [application presentLocalNotificationNow:localNotif];
                       [localNotif release];
                       break;
                   }
               }
           }
           
           NSLog(@"background task %d finished.", _bgTask);     
           [app endBackgroundTask:_bgTask];
           _bgTask = UIBackgroundTaskInvalid;   
              
       });      
   }

}

28、CoreText绘制文本出现行间距不等及解决办法

转自: http://willonboy.tk/?p=1163


 

最终在http://www.cocoanetics.com/2012/02/radar-coretext-line-spacing-bug/

找到了DTCoreText库

Radar: “CoreText Line Spacing Bug” b 05, 2012

I finally got around to report an annoying bug in CoreText that has been bugging us in DTCoreText until I wrote a method to correct line origins as a workaround. rdar://10810114

The annoying thing about this bug is that it adds visual noise to otherwise pristinely rendered text. Especially on larger font sizes you see that additional space appears before each CTLine that ends with a paragraph break (\n).

UPDATE: This is a duplicate of rdar://9931615.

CoreText Line Spacing BugSummary

CoreText inserts too much space before any line that ends with a \n. This extra space depends on the font and font size. On large print this causes visual noise by not being uniform.

Steps to Reproduce

Create a CTFrame from a CTFrameSetter with a string that is long enough to wrap and that contains paragraph breaks. Use a non-UI font, like for example AriaMT.

Expected Results

Line origins should be spaced by exactly the same distance for identical text and identical attributes.

Actual Results

Each line that ends with a paragraph break is shifted down. With the system UI font, size 54 baselines are spaced exactly 64 pixels apart. With ArialMT, size 54, baseline spacing differs between 62 and 65.

Regression

This has been a bug since before iOS 4.3.

Notes

This does not occur with all fonts, Using a system font the spacing is precisely correct. I have attached a project to demonstrate the issue. See TextView.m.

It appears that the text metrics for an (invisible) paragraph glyph are miscalculated. Since the glyph is not visible you’d expect neither and ascender nor descender value. But instead the descender is too large. If you walk through the entire line and get the maximum ascenders and descenders the value is correct if you omit the \n in this calculation.

In short: A trailing \n messes up the font metrics for the entire CTLine.

Attachment: CoreTextLineOrigins Demo Project