CoreText使用學(xué)習(xí)

CoreText 框架中最常用的幾個(gè)類

CTFont
CTFontCollection
CTFontDescriptor
CTFrame
CTFramesetter
CTGlyphInfo
CTLine
CTParagraphStyle
CTRun
CTTextTab
CTTypesetter

CoreText坐標(biāo)系

image

CoreText坐標(biāo)系 和 UIKit坐標(biāo)系 的不同役电,從圖中可看出 CoreText坐標(biāo)系是以左下角為坐標(biāo)原點(diǎn) 蜀踏,而我們常使用的 UIKit是以左上角為坐標(biāo)原點(diǎn) ,因此在CoreText中的布局完成后需要對(duì)其坐標(biāo)系進(jìn)行轉(zhuǎn)換吠架,否則直接繪制出現(xiàn)位置反轉(zhuǎn)的鏡像情況。在通常情況下我們一般做法是直接獲取當(dāng)前上下文蜡豹。并將當(dāng)前上下文的坐標(biāo)系轉(zhuǎn)換為CoreText坐標(biāo)系爷耀,再將布局好的CoreText繪制到當(dāng)前上下文中即可。

// 獲取當(dāng)前上下文
CGContextRef context = UIGraphicsGetCurrentContext();

// 1.設(shè)置當(dāng)前文本矩陣
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
// 2.文本沿y軸移動(dòng)
CGContextTranslateCTM(context, 0, self.bounds.size.height);
// 3.文本翻轉(zhuǎn)成為CoreText坐標(biāo)系
CGContextScaleCTM(context, 1.0, -1.0);

繪制CoreText大致思路

整體視窗組合圖
  • CTFrame 作為一個(gè)整體的畫布(Canvas)绘证,其中由行(CTLine)組成,而每行可以分為一個(gè)或多個(gè)小方塊(CTRun)独柑。不需要自己創(chuàng)建CTRun迈窟,Core Text將根據(jù)NSAttributedString的屬性來(lái)自動(dòng)創(chuàng)建CTRun。每個(gè)CTRun對(duì)象對(duì)應(yīng)不同的屬性忌栅,正因此车酣,你可以自由的控制字體、顏色索绪、字間距等等信息湖员。

  • 使用CoreText文本布局步聚:

    1、首先要確定布局時(shí) 繪制的區(qū)域 瑞驱,其對(duì)應(yīng)的類為 CG(Mutable)PathRef娘摔。

    2、設(shè)置 文本內(nèi)容 唤反,其對(duì)應(yīng)的類為 NS(Mutable)AttributedString凳寺。

    3鸭津、根據(jù)文本內(nèi)容配置其 CTFramesetterRef。

    4肠缨、利用CTFramesetterRef 得到CTFrame逆趋。

image
// 1.創(chuàng)建繪制區(qū)域,顯示的區(qū)域可以用CGMUtablePathRef生成任意的形狀
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(20, 50, self.bounds.size.width - 40, self.bounds.size.height - 100));   
// 2.創(chuàng)建需要繪制的文字
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@"文本內(nèi)容文本內(nèi)容"];
// 3.根據(jù)AttString生成CTFramesetterRef
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString);
// 4.利用CTFramesetterRef得到CTFrame
CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, [attString length]), path, NULL);
  • 添加點(diǎn)擊事件:CTFrame 包含了多個(gè)CTLine,并且可以得到各個(gè)line的其實(shí)位置與大小。判斷點(diǎn)擊處在不在某個(gè)line上晒奕。CTLine 又可以判斷這個(gè)點(diǎn)(相對(duì)于ctline的坐標(biāo))處的文字范圍闻书。然后遍歷這個(gè)string的所有NSTextCheckingResult,根據(jù)result的rang判斷點(diǎn)擊處在不在這個(gè)rang上脑慧,從而得到點(diǎn)擊的鏈接與位置魄眉。

  • 說(shuō)明:CTFramesetter是由CFAttributedString(NSAttributedString)初始化而來(lái),可以認(rèn)為它是CTFrame的一個(gè)Factory闷袒,通過(guò)傳入CGPath生成相應(yīng)的CTFrame并使用它進(jìn)行渲染:直接以CTFrame為參數(shù)使用CTFrameDraw繪制或者從CTFrame中獲取CTLine進(jìn)行微調(diào)后使用CTLineDraw進(jìn)行繪制坑律。

  • CoreText實(shí)際上并沒(méi)有相應(yīng)API直接將一個(gè)圖片轉(zhuǎn)換為CTRun并進(jìn)行繪制,它所能做的只是為圖片預(yù)留相應(yīng)的空白區(qū)域囊骤,而真正的繪制則是交由CoreGraphics完成脾歇。

  • 在CoreText中提供了CTRunDelegate這么個(gè)Core Foundation類,顧名思義它可以對(duì)CTRun進(jìn)行拓展:AttributedString某個(gè)段設(shè)置kCTRunDelegateAttributeName屬性之后淘捡,CoreText使用它生成CTRun是通過(guò)當(dāng)前Delegate的回調(diào)來(lái)獲取自己的ascent,descent和width池摧,而不是根據(jù)字體信息焦除。這樣就給我們留下了可操作的空間:用一個(gè)空白字符作為圖片的占位符,設(shè)好Delegate作彤,占好位置膘魄,然后用CoreGraphics進(jìn)行圖片的繪制。

  • 具體繪制參考:https://github.com/xiangwangfeng/M80AttributedLabel/

字體基本知識(shí)

  • 字體(Font):計(jì)算機(jī)意義上的字體表示的是同一大小竭讳,同一樣式(Style)字形的集合创葡。從這個(gè)意義上來(lái)說(shuō),當(dāng)我們?yōu)槲淖衷O(shè)置粗體绢慢,斜體時(shí)其實(shí)是使用了另外一種字體(下劃線不算)灿渴。而平時(shí)我們所說(shuō)的字體只是具有相同設(shè)計(jì)屬性的字體集合,即Font Family或typeface胰舆。
  • 字符(Character)和字形(Glyphs):排版過(guò)程中一個(gè)重要的步驟就是從字符到字形的轉(zhuǎn)換骚露,字符表示信息本身,而字形是它的圖形表現(xiàn)形式缚窿。字符一般就是指某種編碼棘幸,如Unicode編碼,而字形則是這些編碼對(duì)應(yīng)的圖片倦零。但是他們之間不是一一對(duì)應(yīng)關(guān)系误续,同個(gè)字符的不同字體族吨悍,不同字體大小,不同字體樣式都對(duì)應(yīng)了不同的字形蹋嵌。
  • 字形的各個(gè)參數(shù)
image
image
image
image
image

紅框高度既為當(dāng)前行的行高育瓜,綠線為baseline,綠色到紅框上部分為當(dāng)前行的最大Ascent欣尼,綠線到黃線為當(dāng)前行的最大Desent爆雹,而黃框的高即為行間距。由此可以得出:lineHeight = Ascent + |Decent| + Leading(行間距)愕鼓。

常用屬性介紹

// 字體形狀屬性:必須是CFNumberRef對(duì)象默認(rèn)為0钙态,非0則對(duì)應(yīng)相應(yīng)的字符形狀定義,如1表示傳統(tǒng)字符形狀
const CFStringRef kCTCharacterShapeAttributeName;              

// 字體屬性:必須是CTFont對(duì)象
const CFStringRef kCTFontAttributeName;                        

// 字符間隔屬性:必須是CFNumberRef對(duì)象
const CFStringRef kCTKernAttributeName;                        

// 設(shè)置是否使用連字屬性:設(shè)置為0菇晃,表示不使用連字屬性册倒。標(biāo)準(zhǔn)的英文連字有FI,FL.默認(rèn)值為1,既是使用標(biāo)準(zhǔn)連字磺送。也就是當(dāng)搜索到f時(shí)候驻子,會(huì)把fl當(dāng)成一個(gè)文字。必須是CFNumberRef 默認(rèn)為1,可取0,1,2
const CFStringRef kCTLigatureAttributeName;                 

// 字體顏色屬性:必須是CGColor對(duì)象估灿,默認(rèn)為black
const CFStringRef kCTForegroundColorAttributeName;             

 // 上下文的字體顏色屬性:必須為CFBooleanRef 默認(rèn)為False
const CFStringRef kCTForegroundColorFromContextAttributeName; 

 // 段落樣式屬性:必須是CTParagraphStyle對(duì)象 默認(rèn)為NIL
const CFStringRef kCTParagraphStyleAttributeName;              

// 筆畫線條寬度:必須是CFNumberRef對(duì)象崇呵,默為0.0f,標(biāo)準(zhǔn)為3.0f
const CFStringRef kCTStrokeWidthAttributeName;              

// 筆畫的顏色屬性:必須是CGColorRef 對(duì)象馅袁,默認(rèn)為前景色
const CFStringRef kCTStrokeColorAttributeName;              

// 設(shè)置字體的上下標(biāo)屬性:必須是CFNumberRef對(duì)象 默認(rèn)為0,可為-1為下標(biāo),1為上標(biāo)域慷,需要字體支持才行。如排列組合的樣式Cn1
const CFStringRef kCTSuperscriptAttributeName;              

// 字體下劃線顏色屬性:必須是CGColorRef對(duì)象汗销,默認(rèn)為前景色
const CFStringRef kCTUnderlineColorAttributeName;           

// 字體下劃線樣式屬性:必須是CFNumberRef對(duì)象,默為kCTUnderlineStyleNone 可以通過(guò)CTUnderlineStypleModifiers 進(jìn)行修改下劃線風(fēng)格
const CFStringRef kCTUnderlineStyleAttributeName;           

// 文字的字形方向?qū)傩裕罕仨毷荂FBooleanRef 默認(rèn)為false犹褒,false表示水平方向,true表示豎直方向
const CFStringRef kCTVerticalFormsAttributeName;

// 字體信息屬性:必須是CTGlyphInfo對(duì)象
const CFStringRef kCTGlyphInfoAttributeName;

// CTRun 委托屬性:必須是CTRunDelegate對(duì)象
const CFStringRef kCTRunDelegateAttributeName

文本屬性設(shè)置:

// 設(shè)置繪制的文本內(nèi)容
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"];

// 設(shè)置文本內(nèi)容的屬性
// 1.設(shè)置部分文字顏色
[attString addAttribute:(id)kCTForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0 , 27)];

// 2.設(shè)置部分文字字體
CGFloat fontSize = 20;
CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", fontSize, NULL);
[attString addAttribute:(id)kCTFontAttributeName value:(__bridge id)fontRef range:NSMakeRange(0, 27)];

// 3.設(shè)置斜體
CTFontRef italicFontRef = CTFontCreateWithName((CFStringRef)[UIFont italicSystemFontOfSize:20].fontName, 16, NULL);
[attString addAttribute:(id)kCTFontAttributeName value:(__bridge id)italicFontRef range:NSMakeRange(27, 9)];

// 4.設(shè)置下劃線
[attString addAttribute:(id)kCTUnderlineStyleAttributeName value:(id)[NSNumber numberWithInteger:kCTUnderlineStyleDouble] range:NSMakeRange(36, 10)];

// 5.設(shè)置下劃線顏色
[attString addAttribute:(id)kCTUnderlineColorAttributeName value:(id)[UIColor greenColor].CGColor range:NSMakeRange(36, 10)];

// 6.設(shè)置空心字
long number1 = 2;
CFNumberRef numRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &number1);
[attString addAttribute:(id)kCTStrokeWidthAttributeName value:(__bridge id)numRef range:NSMakeRange(56, 10)];

// 7.設(shè)置字體間距
long number = 10;
CFNumberRef num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt8Type, &number);
[attString addAttribute:(id)kCTKernAttributeName value:(__bridge id)num range:NSMakeRange(40, 10)];

// 8.設(shè)置行間距
CGFloat lineSpacing = 10;
const CFIndex kNumberOfSettings = 3;
CTParagraphStyleSetting theSettings[kNumberOfSettings] = {
    {kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof(CGFloat), &lineSpacing},
    {kCTParagraphStyleSpecifierMaximumLineHeight, sizeof(CGFloat), &lineSpacing},
    {kCTParagraphStyleSpecifierMinimumLineHeight, sizeof(CGFloat), &lineSpacing}
    };
CTParagraphStyleRef theParagraphRef = CTParagraphStyleCreate(theSettings, kNumberOfSettings);
[attString addAttribute:(id)kCTParagraphStyleAttributeName value:(__bridge id)theParagraphRef range:NSMakeRange(0, [attString length])];

繪制圖片

Core Text本身并不支持圖片繪制弛针,圖片的繪制你還得通過(guò)Core Graphics來(lái)進(jìn)行叠骑。Core Text可以通過(guò)CTRun的設(shè)置為你的圖片在文本繪制的過(guò)程中留出適當(dāng)?shù)目臻g。這個(gè)設(shè)置就使用到CTRunDelegate削茁。CTRunDelegate作為CTRun相關(guān)屬性或操作擴(kuò)展的一個(gè)入口宙枷,使得我們可以對(duì)CTRun做一些自定義的行為。為圖片留位置的方法就是加入一個(gè)空白的CTRun茧跋,自定義其ascent朦拖,descent,width等參數(shù)厌衔,使得繪制文本的時(shí)候留下空白位置給相應(yīng)的圖片璧帝。然后圖片在相應(yīng)的空白位置上使用Core Graphics接口進(jìn)行繪制。

圖片寬高需要加載后才知道富寿,而在文本繪制中需要直接留出其位置再進(jìn)行繪制睬隶,所以圖片的寬高都是在數(shù)據(jù)中保存好的锣夹。為了留出其位置我們需要用空白的字符來(lái)做占位符使用。為了知道其圖片繪制的位置(即空白占位符位置)我們需要設(shè)置代理才能夠得知圖片繪制位置苏潜。

使用CTRunDelegateCreate可以創(chuàng)建一個(gè)CTRunDelegate银萍,它接收兩個(gè)參數(shù),一個(gè)是callbacks結(jié)構(gòu)體恤左,一個(gè)是所有callback調(diào)用的時(shí)候需要傳入的對(duì)象贴唇。 callbacks的結(jié)構(gòu)體為CTRunDelegateCallbacks,主要是包含一些回調(diào)函數(shù)飞袋,比如有返回當(dāng)前run的ascent戳气,descent,width這些值的回調(diào)函數(shù)巧鸭,至于函數(shù)中如何鑒別當(dāng)前是哪個(gè)run瓶您,可以在CTRunDelegateCreate的第二個(gè)參數(shù)來(lái)達(dá)到目的,因?yàn)镃TRunDelegateCreate的第二個(gè)參數(shù)會(huì)作為每一個(gè)回調(diào)調(diào)用時(shí)的入?yún)ⅰ?/p>

  • 具體步驟:

    1纲仍、創(chuàng)建 CTRunDelegateCallbacks 回調(diào)函數(shù) :通過(guò)回調(diào)函數(shù)來(lái)確定圖片繪制的寬高呀袱。

    2、創(chuàng)建 空白占位字符郑叠。

    3夜赵、設(shè)置 CTRunDeleagte :通過(guò)代理來(lái)找到該字符串,并確定圖片繪制的原點(diǎn)乡革。

具體實(shí)現(xiàn):

#pragma mark - CTRunDelegateCallbacks Method
static CGFloat ascentCallback(void *ref) {
    return [(NSNumber *)[(__bridge NSDictionary *)ref objectForKey:@"height"] floatValue];
}

static CGFloat descentCallback(void *ref) {
    return 0;
}

static CGFloat widthCallback(void *ref) {
    return [(NSNumber *)[(__bridge NSDictionary *)ref objectForKey:@"width"] floatValue];
}

#pragma mark - 空白占位符及代理設(shè)置
+ (NSAttributedString *)parseImageDataFromNSDictionary:(NSDictionary *)dict config:(CTFrameParserConfig *)config {
    // CTRunDelegateCallBacks:用于保存指針的結(jié)構(gòu)體油吭,由CTRun delegate進(jìn)行回調(diào)
    CTRunDelegateCallbacks callbacks;
    memset(&callbacks, 0, sizeof(CTRunDelegateCallbacks));
    callbacks.version = kCTRunDelegateVersion1;
    callbacks.getAscent = ascentCallback;
    callbacks.getDescent = descentCallback;
    callbacks.getWidth = widthCallback;
    // 字典中含有圖片的寬高信息
    // 創(chuàng)建CTRunDelegate的代理
    CTRunDelegateRef delegate = CTRunDelegateCreate(&callbacks, (__bridge void *)(dict));

    // 使用0xFFFC作為空白的占位符
    unichar objectReplacementChar = 0xFFFC;
    NSString *content = [NSString stringWithCharacters:&objectReplacementChar length:1];
    NSDictionary *attributes = [self attributesWithConfig:config];
    NSMutableAttributedString *space = [[NSMutableAttributedString alloc] initWithString:content attributes:attributes];
    // 設(shè)置代理
    CFAttributedStringSetAttribute((CFMutableAttributedStringRef)space, CFRangeMake(0, 1), kCTRunDelegateAttributeName, delegate);
    CFRelease(delegate);

    return space;
}

#pragma mark - drawRect
- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    if (self.data == nil) {
        return;
    }

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    if (self.state == CTDisplayViewStateTouching || self.state == CTDisplayViewStateSelecting) {
        [self drawSelectionArea];
        [self drawAnchors];
    }

    CTFrameDraw(self.data.ctFrame, context);

    // 遍歷圖片數(shù)組,在適當(dāng)?shù)奈恢貌迦肜L制的圖片
    for (CTImageData *imageData in self.data.imageArray) {
        UIImage *image = [UIImage imageNamed:imageData.name];
        if (image) {
            CGContextDrawImage(context, imageData.imagePosition, image.CGImage);
        }
    }
}

CTRun delegate進(jìn)行回調(diào):

- (void)fillImagePosition {
    if (self.imageArray.count == 0) {
        return;
    }
    
    // 獲取CTLine數(shù)組
    NSArray *lines = (NSArray *)CTFrameGetLines(self.ctFrame);
    NSUInteger lineCount = [lines count];
    CGPoint lineOrigins[lineCount];
    CTFrameGetLineOrigins(self.ctFrame, CFRangeMake(0, 0), lineOrigins);

    int imgIndex = 0;
    CTImageData *imageData = self.imageArray[0];

    //遍歷CTline
    for (int i = 0; i < lineCount; ++i) {
        if (imageData == nil) {
            break;
        }
        CTLineRef line = (__bridge CTLineRef)lines[i];
        NSArray *runObjArray = (NSArray *)CTLineGetGlyphRuns(line);
        // 遍歷每個(gè)CTLine中的CTRun找到空白字符的delegate
        for (id runObj in runObjArray) {
            CTRunRef run = (__bridge CTRunRef)runObj;
            NSDictionary *runAttributes = (NSDictionary *)CTRunGetAttributes(run);
            CTRunDelegateRef delegate = (__bridge CTRunDelegateRef)[runAttributes valueForKey:(id)kCTRunDelegateAttributeName];
            if (delegate == nil) {
                continue;
            }

            NSDictionary *metaDic = CTRunDelegateGetRefCon(delegate);
            if (![metaDic isKindOfClass:[NSDictionary class]]) {
                continue;
            }
            
            // 找到代理后開始計(jì)算空白字符的位置
            CGRect runBounds;
            CGFloat ascent;
            CGFloat descent;
            runBounds.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, NULL);
            runBounds.size.height = ascent + descent;
            
            // 計(jì)算在行當(dāng)中的x偏移量
            CGFloat xOffset = CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL);
            runBounds.origin.x = lineOrigins[i].x + xOffset;
            runBounds.origin.y = lineOrigins[i].y;
            runBounds.origin.y -= descent;
            
            // 獲得ctframe的繪制區(qū)域
            CGPathRef pathRef = CTFrameGetPath(self.ctFrame);
            // 計(jì)算此繪制區(qū)域的范圍
            CGRect colRect = CGPathGetBoundingBox(pathRef);

            // 計(jì)算在此區(qū)域中空白字符的位置
            CGRect delegateBounds = CGRectOffset(runBounds, colRect.origin.x, colRect.origin.y);

            // 記錄空白字符位置
            imageData.imagePosition = delegateBounds;
            imgIndex++;
            if (imgIndex == self.imageArray.count) {
                imageData = nil;
                break;
            } else {
                imageData = self.imageArray[imgIndex];
            }
        }
    }
}
  • 幾個(gè)重要的方法:

    CTFrameGetLineOrigins:該方法是獲取每一行的原點(diǎn)署拟,這個(gè)在計(jì)算字體的坐標(biāo)的時(shí)候會(huì)用到。

    CTLineGetGlyphRuns:該方法獲取一行里面所有的CTRun了歌豺,因?yàn)镃TLine是由一個(gè)個(gè)CTRun組合而成的推穷。

    CTRunGetAttributes:該方法獲取CTRun的一些屬性。這個(gè)方法返回的是一個(gè)字典类咧,當(dāng)然字典里面除了一些系統(tǒng)屬性外馒铃,你之前設(shè)置的一些自定義屬性也能獲取到,正是這樣我們可以通過(guò)自定義的屬性來(lái)特殊處理個(gè)別的CTRun(比如圖片痕惋,鏈接等)区宇。

    CTLineGetOffsetForStringIndex:該方法是獲取具體的文字距離這行原點(diǎn)的距離,當(dāng)然也是算尺寸用的值戳。

    CTLineGetStringIndexForPosition:該方法是獲取點(diǎn)擊時(shí)我們點(diǎn)擊的是哪一個(gè)文字议谷,是給點(diǎn)擊鏈接時(shí)顯示點(diǎn)擊效果用的。因?yàn)殒溄颖容^長(zhǎng)堕虹,可能會(huì)超過(guò)一行卧晓,我們需要根據(jù)點(diǎn)擊的文字找出指定的鏈接芬首,然后在整個(gè)鏈接區(qū)域繪制背景色,這個(gè)是比較復(fù)雜的部分逼裆。

  • Demo示例下載:https://pan.baidu.com/s/1pLhpsyn

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末郁稍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子胜宇,更是在濱河造成了極大的恐慌耀怜,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桐愉,死亡現(xiàn)場(chǎng)離奇詭異财破,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)仅财,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門狈究,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人盏求,你說(shuō)我怎么就攤上這事抖锥。” “怎么了碎罚?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵磅废,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我荆烈,道長(zhǎng)拯勉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任憔购,我火速辦了婚禮宫峦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘玫鸟。我一直安慰自己导绷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布屎飘。 她就那樣靜靜地躺著妥曲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钦购。 梳的紋絲不亂的頭發(fā)上檐盟,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音押桃,去河邊找鬼葵萎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的陌宿。 我是一名探鬼主播锡足,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼壳坪!你這毒婦竟也來(lái)了舶得?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤爽蝴,失蹤者是張志新(化名)和其女友劉穎沐批,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蝎亚,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡九孩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了发框。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片躺彬。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖梅惯,靈堂內(nèi)的尸體忽然破棺而出宪拥,到底是詐尸還是另有隱情,我是刑警寧澤铣减,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布她君,位于F島的核電站,受9級(jí)特大地震影響葫哗,放射性物質(zhì)發(fā)生泄漏缔刹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一劣针、第九天 我趴在偏房一處隱蔽的房頂上張望校镐。 院中可真熱鬧,春花似錦捺典、人聲如沸鸟廓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至哄褒,卻和暖如春稀蟋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背呐赡。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工退客, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓萌狂,卻偏偏與公主長(zhǎng)得像档玻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子茫藏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 系列文章: CoreText實(shí)現(xiàn)圖文混排 CoreText實(shí)現(xiàn)圖文混排之點(diǎn)擊事件 CoreText實(shí)現(xiàn)圖文混排之文...
    老司機(jī)Wicky閱讀 40,167評(píng)論 221 432
  • 1.iOS中的round误趴、ceil、floor函數(shù)略解 round如果參數(shù)是小數(shù)务傲,則求本身的四舍五入.ceil如果...
    K_Gopher閱讀 1,186評(píng)論 1 0
  • CoreText是一個(gè)進(jìn)階的比較底層的布局文本和處理字體的技術(shù)凉当,CoreText API在OS X v10.5 和...
    smalldu閱讀 13,446評(píng)論 18 129
  • CoreText是iOS/OSX中文本顯示的一個(gè)底層框架,它是用C語(yǔ)言寫成的售葡,有快速簡(jiǎn)單的優(yōu)勢(shì)看杭。iOS中的Text...
    小貓仔閱讀 4,976評(píng)論 2 9
  • 一天,我到好朋友果果家玩挟伙,快到中午了楼雹,我們到外面吃飯,吃完飯走出餐廳尖阔,看到天空烏云密布贮缅,天黑的可怕,我們匆...
    唯愛(ài)胖迪dear閱讀 191評(píng)論 1 0