Quartz2D

Quartz2D

简介

Quartz2D是二维(平面)的绘图引擎(经包装的函数库,方便开发者使用。也就是说苹果帮我们封装了一套绘图的函数库)

同时支持iOS和Mac系统开发,用Quartz2D写的同一份代码,既可以运行在iphone上又可以运行在mac上,可以跨平台开发。

Quartz 2D能完成的工作

绘制图形 : 线条\三角形\矩形\圆\弧等

绘制文字

绘制\生成图片(图像)

读取\生成PDF

截图\裁剪图片

自定义UI控件

.....

Quartz2D在iOS开发中的价值

为了便于搭建美观的UI界面,iOS提供了UIKit框架,里面有各种各样的UI控件 UILabel:显示文字 UIImageView:显示图片 UIButton:同时显示图片和文字(能点击) … …

利用UIKit框架提供的控件,拼拼凑凑,能搭建和现实一些简单、常见的UI界面,但是,有些UI界面极其复杂、而且比较个性化,用普通的UI控件无法实现,这时可以利用Quartz2D技术将控件内部的结构画出来,自定义控件的样子,iOS中大部分控件的内容都是通过Quartz2D画出来的,因此,Quartz2D在iOS开发中很重要的一个价值是:自定义view(自定义UI控件)

自定义View

图形上下文(Graphics Context):是一个CGContextRef类型的数据

图形上下文的作用

保存绘图信息、绘图状态 -决定绘制的输出目标(绘制到什么地方去?) (输出目标可以是PDF文件、Bitmap或者显示器的窗口上) 相同的一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上

自定义view的步骤

新建一个类,继承自UIView

实现- (void)drawRect:(CGRect)rect方法,然后在这个方法中

取得跟当前view相关联的图形上下文

绘制相应的图形内容

利用图形上下文将绘制的所有内容渲染显示到view上面

drawRect:方法

实现drawRect:方法才能绘图到view,因为在drawRect:方法中才能取得跟view相关联的图形上下文,

drawRect:方法在调用时间 当view第一次显示到屏幕上时(被加到UIWindow上显示出来) 调用view的setNeedsDisplay或者setNeedsDisplayInRect:时

在drawRect:方法中取得上下文后,就可以绘制东西到view上

View内部有个layer(图层)属性,drawRect:方法中取得的是一个Layer Graphics Context,因此,绘制的东西其实是绘制到view的layer上去了,View之所以能显示东西,完全是因为它内部的layer

示例1画直线

1> 获取图形上下文 CG:表示这个类在CoreGraphics框架里 Ref:引用 目前学的上下文都跟UIGraphics有关,想获取图形上下文,首先敲UIGraphics。

2> 拼接路径:一般开发中用贝塞尔路径,里面封装了很多东西,可以帮我画一些基本的线段,矩形,圆等等。 创建贝塞尔路径 起点:moveToPoint 终点:addLineToPoint

3> 把路径添加到上下文 CGPath转换:UIKit框架转CoreGraphics直接CGPath就能转

4> 把上下文渲染到视图,图形上下文本身不具备显示功能。 PPT画图分析为什么要这样做?首先获取图形上下文,然后描述路径,把路径添加到上下文,渲染到视图,图形上下文相当于一个内存缓存区,在内存里面操作是最快的,比直接在界面操作快多了。

在添加一根线 直接addLineToPoint,因为路径是拼接的,默认下一条线的起点是上一条线的终点。

画两跟不连接的线 1> 第二次画的时候,重新设置起点,然后画线。一个路径可以包含多条线段。 2> 新创建一个路径,添加到上下文。开发中建议使用这种,比较容易控制每根线。

设置绘图状态 线段怎么加粗。 绘图状态调用顺序:只要在渲染之前就好了,在渲染的时候才会去看绘图的最终状态。

// 1.获取跟当前view想关联的上下文// 以后只要根上下文有关,直接敲UIGraphics,一般都是以UIGraphics开头// CG:CoreGraphics Ref:引用CGContextRefctx =UIGraphicsGetCurrentContext();// 2.绘制内容,拼接路径,绘制的内容统称为路径// 在开发中一般使用贝塞尔路径,UIKit框架UIBezierPath*path = [UIBezierPathbezierPath];// 设置起点,移动到某个位置[path moveToPoint:CGPointMake(50,50)];// 添加一根线到某个点[path addLineToPoint:CGPointMake(200,200)];// 一根路径对象可以包含很多线段[path moveToPoint:CGPointMake(50,200)];// 默认下一根线的起点在上一根线的终点[path addLineToPoint:CGPointMake(100,200)];// 3.把路径添加到上下文,给上下文添加路径以CGContextCGContextAddPath(ctx, path.CGPath);// 开发中,如果线段不连接,最好使用一根线对应一个路径对象// 描述第二根线//    path = [UIBezierPath bezierPath];////    // 设置起点,移动到某个位置//    [path moveToPoint:CGPointMake(200, 200)];////    // 添加一根线到某个点//    [path addLineToPoint:CGPointMake(100, 200)];////    CGContextAddPath(ctx, path.CGPath);// 4.把上下文内容渲染到viewCGContextStrokePath(ctx);

示例2画圆形

//Center:圆心//radius:半径.//startAngle:开始角度//endAngle:结束角度//clockwise:CGPointcenter =CGPointMake(self.bounds.size.width*0.5,self.bounds.size.height*0.5);CGFloatradius =100;CGFloatstartA =0;//圆的0度角在圆的最右侧.CGFloatendA = -M_PI_2;UIBezierPath*path =  [UIBezierPathbezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];    [UIColorredColor] set];    [path stroke];

示例3画文字,常见属性

//我们要画的文字NSString*str =@"我们要画的文字";//开始绘制文字//    AtPoint:画在哪个点上.//Attributes:文字的属性.颜色,字体大小...NSMutableDictionary*dict = [NSMutableDictionarydictionary];//设置文字的颜色dict[NSForegroundColorAttributeName] = [UIColorredColor];//设置字体大小dict[NSFontAttributeName] = [UIFontsystemFontOfSize:50];//设置描边的颜色dict[NSStrokeColorAttributeName] = [UIColorblueColor];//设置描边的宽度dict[NSStrokeWidthAttributeName] = @1;NSShadow*shadow = [[NSShadowalloc] init];//设置阴影的偏移量shadow.shadowOffset=CGSizeMake(-10,10);//设置阴影的颜色shadow.shadowColor= [UIColorgreenColor];//设置阴影的模糊shadow.shadowBlurRadius=2;    dict[NSShadowAttributeName] = shadow;//drawAtPoint不会自动换行//    [str drawAtPoint:CGPointZero withAttributes:dict];//drawInRect它会自动的换行.[str drawInRect:self.boundswithAttributes:dict];

图形上下文的矩阵操作

形变操作,必须得要在添加路径之前进行

计时器

CADisplayLink

//在绘图当中, 我们一般使用CADisplayLink.因为他和setNeedsDisplay调用时机是一样的,都是当下一次屏幕刷新的时候调用.

//CADisplayLink//它是当每次屏幕刷新的时候就会调用定时器方法.(每一秒种刷新60次)CADisplayLink*link = [CADisplayLinkdisplayLinkWithTarget:selfselector:@selector(update)];//想让定时器工作,必须得要把它添加到主运行循环.[link addToRunLoop:[NSRunLoopmainRunLoop] forMode:NSDefaultRunLoopMode];

NSTimer

[NSTimerscheduledTimerWithTimeInterval:0.01target:selfselector:@selector(update) userInfo:nilrepeats:YES];

注意,在实际开发中视情况选择使用

常用的拼接函数

新建一个起点voidCGContextMoveToPoint(CGContextRefc,CGFloatx,CGFloaty)添加新的线段到某个点voidCGContextAddLineToPoint(CGContextRefc,CGFloatx,CGFloaty)添加一个矩形voidCGContextAddRect(CGContextRefc,CGRectrect)添加一个椭圆voidCGContextAddEllipseInRect(CGContextRefcontext,CGRectrect)添加一个圆弧voidCGContextAddArc(CGContextRefc,CGFloatx,CGFloaty,CGFloatradius,CGFloatstartAngle,CGFloatendAngle,intclockwise)

常用绘制的函数

Mode参数决定绘制的模式

voidCGContextDrawPath(CGContextRefc,CGPathDrawingModemode)绘制空心路径voidCGContextStrokePath(CGContextRefc)绘制实心路径voidCGContextFillPath(CGContextRefc)提示:一般以CGContextDraw、CGContextStroke、CGContextFill开头的函数,都是用来绘制路径的

矩阵操作

利用矩阵操作,能让绘制到上下文中的所有路径一起发生变化缩放voidCGContextScaleCTM(CGContextRefc,CGFloatsx,CGFloatsy)旋转voidCGContextRotateCTM(CGContextRefc,CGFloatangle)平移voidCGContextTranslateCTM(CGContextRefc,CGFloattx,CGFloatty)

图片水印技术

需求:在手机客户端app中需要用到水印技术,用户拍完照片后,可以在照片上打个水印,标识这个图片是属于哪个用户的

实现方式:利用Quartz2D,将水印(文字、LOGO)画到图片的右下角

核心代码

开启一个基于位图的图形上下文UIGraphicsBeginImageContextWithOptions(CGSizesize,BOOLopaque,CGFloatscale)从上下文中取得图片(UIImage)UIImage*UIGraphicsGetImageFromCurrentImageContext();结束基于位图的图形上下文UIGraphicsEndImageContext();

水印PPT简介

图片水印作用:防止他人盗取图片,加一些Logo,生成一张新的图片。

和绘图一样的生成新的图片,需要拿到上下文做事情,这里也需要拿到上下文,生成一个新的图片。

位图上下文,在这个上下文画东西,就能输出到新的图片上。

之前用的都是图层上下文,系统会自动创建,但是我们位图上下文,需要我们手动创建

总结:只要不和view有关系的上下文,都需要我们手动创建。

在哪获取图像上下文,viewDidLoad, 不需要拿到系统创建的图层上下文,没必要在drawRect方法里写,直接viewDidLoad就行了。

UIGraphicsBeginImageContextWithOptions:(CGSize size, BOOL opaque, CGFloat scale)创建一个位图上下文,而且这种方法得到的图片最清晰。解释参数(size:新图片尺寸 opaque: YES:不透明 NO:透明 scale:0.0 不伸缩)

绘制内容(图片,文字)

获取图片:把位图上下文的内容生成一个图片给你。

关闭上下文,不关闭一直占用着内存。

显示UIImageView上

保存图片,写到文件,UIImage不能写,需要转换成NSData二进制数据

UIImageJPEGRepresentation:可以设置图片质量

UIImagePNGRepresentation:把图片转换成png格式的二进制数据,png格式默认是最高清的。

写到桌面

图片裁剪

图片裁剪

PPT分析思路:先设置裁剪区域,把图片画上去,超出裁剪区域的自动裁剪掉。

加载旧图片,根据旧图片,获取上下文尺寸。

上下文的尺寸 = 新图片的尺寸

开启一个多大的上下文?:和图片尺寸一样大,避免压缩图片。如果比图片尺寸小,会压缩图片。

设置裁剪区域:正切于图片的圆

绘制旧图片

获取新图片

关闭上下文

//1.加载要裁剪的图片UIImage*image = [UIImageimageNamed:@"阿狸头像"];

//2.开启一个跟图片尺寸一样大的位图上下文UIGraphicsBeginImageContextWithOptions(image.size,NO,0);

//3.设置一个裁剪(宽度和高度都是等于原始图片的宽高)UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, image.size.width, image.size.height)];//把路径设置成裁剪区域[path addClip];

//4.把要裁剪的图片绘制到上下文当中.[image drawAtPoint:CGPointZero];

//5.从上下文当中生成一张新的图片UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

//6.关闭上下文.UIGraphicsEndImageContext();self.imageV.image= newImage;

带圆环裁剪:在裁剪的图片外边加个小圆环。

先画一个大圆,在设置裁剪区域,把图片画上去,超出裁剪区域的自动裁剪掉。

加载旧图片,根据旧图片,获取上下文尺寸。

确定圆环宽度 borderW

上下文的尺寸 = 新图片的尺寸

确定新的上下文尺寸: newImageW : oldImageW + 2borderW newImageH : oldImageH + 2borderW,

绘制大圆: 1.获取上下文 2.添加路径到上下文 3.设置大圆的颜色 = 圆环的颜色 4.渲染

设置裁剪区域,和图片尺寸一样大,只不过,x,y不一样,x=borderW,y=borderW.

绘制旧图片

获取新图片

关闭上下文

抽分类,3个参数,图片名称,圆环宽度,圆环颜色

可以创建给UIImage添加一个分类提供方法直接使用

//0.设置一个边框宽度//1.加载图片//2.开启一个位图上下文CGSizesize =CGSizeMake(image.size.width+2* boderW, image.size.height+2* boderW);UIGraphicsBeginImageContextWithOptions(size,NO,0);

//3.设置一个大圆的一个填充区域UIBezierPath*path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, size.width, size.height)];//设置边框的颜色[color set];    [path fill];

//4.设置一个小圆裁剪区域path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(boderW, boderW, image.size.width, image.size.height)];//把小圆设置成裁剪区域[path addClip];

//5.把原始图片绘制到上下文当中[image drawInRect:CGRectMake(boderW, boderW, image.size.width, image.size.height)];

//6.生成一张新的图片UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

//7.关闭上下文.UIGraphicsEndImageContext();returnnewImage;

图片截屏

屏幕截图:把屏幕的内容截屏生成一张新的图片

通常开发中,都是把控制器的内容截屏,生成新的图片

控制器根据view显示

view根据layer图层显示

把layer渲染到位图上下文

注意:图层只能用渲染,图片和文字可以用draw

渲染在新的图片

开启图片上下文,和视图一样的尺寸

写入桌面

抽分

//懒加载,当使用才创建,可以节省内存-(UIView*)cover{if(_cover ==nil) {//创建一个遮盖UIView*cover = [[UIViewalloc] init];        cover.backgroundColor= [UIColorblackColor];        cover.alpha=0.7;        _cover = cover;        [self.viewaddSubview:cover];    }return_cover;}

- (void)viewDidLoad {    [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.}

//当手指拖动的时候调用- (IBAction)pan:(UIPanGestureRecognizer*)pan {//获取当前手指所在的点CGPointcurP = [pan locationInView:self.imageV];//起点if(pan.state==UIGestureRecognizerStateBegan){//添加遮盖,设置遮盖的起点.self.startP= curP;    }elseif(pan.state==UIGestureRecognizerStateChanged){//移动,确定遮盖的尺寸//x轴偏移量CGFloatoffsetX = curP.x-self.startP.x;//Y 轴的偏移量CGFloatoffsetY = curP.y-self.startP.y;//改变遮盖的尺寸self.cover.frame=CGRectMake(self.startP.x,self.startP.y, offsetX, offsetY);    }else if(pan.state==UIGestureRecognizerStateEnded){//松开//做裁剪

//开启一个上下文.(跟图片一样大的上下文.)UIGraphicsBeginImageContextWithOptions(self.imageV.bounds.size,NO,0);

//在上下文当中设置一个裁剪区域(就是当前遮盖的frame)UIBezierPath*path = [UIBezierPathbezierPathWithRect:self.cover.frame];

//设置裁剪区域[path addClip];//把UIImageView当中的图片绘制到上下文当中.

//获取当前上下文CGContextRefctx =UIGraphicsGetCurrentContext();      [self.imageV.layerrenderInContext:ctx];

//生成一张新的图片.UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

//把位图上下文关闭掉UIGraphicsEndImageContext();

//把UIImageView当中的图片重新赋值self.imageV.image= newImage;//移除遮盖[self.coverremoveFromSuperview];    }}

手势解锁

分析界面有几个控件:背景:UIImageView 白色圆圈:按钮(点击他,会出现另外一种图片,按钮可以设置不同状态下的图片。)单独视图:(画线是有范围的,当超出view就不能画线了)

HMLoadView:自定义视图,在视图一创建的时候,就添加9个按钮。

在initWithCoder,initWithFrame方法添加按钮。

九宫格布局:

tolcol =3计算row,col 按钮的x,y跟col,row有关系,col = i % tolcol row = i / tolcol  计算边距 margin = (view.bounds.size.width- tolcol * btnW) / (tolcol +1)  btnX = margin + (btnW + margin) * col  btnY = (btnW + margin) * row

圆的选中

点击按钮就为选中的图片怎么做?监听按钮点击。

不能addTarget: 不能及时显示选中图片。

监听touchBegin,判断点在不在按钮的frame上。

touchBegin不调用?原因:事件交给按钮处理,应该把事件交给解锁视图。让按钮不接收事件。

设置按钮不允许交互,2个用处:1.不接收事件 2.取消高亮效果 一举两得

遍历所有按钮,看触摸点在哪个按钮上,就选中谁,CGRectContainsPoint 传入的参数必须是同一个坐标系

实现touchMove方法:因为手指移动的时候,也需要判断点在不在按钮上。

抽方法,因为touchMove的方法里,也需要做同样的事情。

1>pointWithTouches根据touches集合取出触摸点2>buttonWithPoint根据触摸点,获取触摸按钮

圆的连线

被选中按钮之间都需要连线,还有一个多余的线

先把选中的按钮全部连线,因为多余的那根线是从最后一个按钮的圆心开始画,手指移动在哪就画哪。

搞个数组保存下所有选中按钮,在drawRect方法中遍历所有按钮,连线

UIBezierPath画线,不需要上下文。

需要多少个UIBezierPath对象?一个,路径都是连续的,不相连的,才需要创建新的UIBezierPath。

遍历数组,描述路径 1> 起点:第一个按钮的圆心 2> 添加一根线到其他按钮的圆心

设置路径的颜色和线宽

把所有路径都描述完就,渲染一次就够了。

[path stroke] 就能渲染到视图上了。

画多余的那根线,记住手指移动的位置。

setNeedDisplay 因为drawRect只会调用一次,需要每次手指移动的时候,都需要重绘。

touchBegin不调用setNeedDisplay,因为重绘也没用,只有起点。

lineJoinStyle:有尖尖的东西,线段连接样式的问题,设置为平的。

已经选中的按钮,不需要再次选中,和画线

手指抬起,取消所有选中按钮,并且清空数组,清空线条

drawRect判断下没有选中数组,不需要画线。

如何判断用户是否输入正确?给选中按钮绑定tag,遍历所有选中按钮,把tag拼接成一个字符串。

画板

分析控件:ToolBar(不需要管里面子控件的frame),画板view,自定义工具条(方便屏幕适配,能迅速固定里面子控件的位置)

自动布局,四个约束确定一个控件

蓝色按钮:左,右,下,高固定

橘色按钮:右,下固定,宽度和高度和蓝色按钮相等。

绿色按钮:右,下,宽度和高度和橘色按钮相等

绘图思路:先描述路径,在渲染,需要画很多线条,最好每个线条保存到一个路径里面。

绘图功能

touchBegin设置画线起点:开始触摸的点

创建UIBezierPath,贝塞尔路径才能设置起点

touchMove:手指移动到哪就画哪,addLine到移动的点

setNeedDisplay,路径描述完了,就渲染到视图就好了。

drawRect方法每次都会把之前的清掉,重新绘制

搞个数组保存上一次的,绘制多条线

设置线宽:每次滑动滑块,就改变下一次路径的宽度

监听滑块的值,把值传递给paintView,设置路径的线宽。

不能在drawRect写,会导致所有路径都是一个线宽,应该是每个路径都记录自己的线宽,而且线宽只需要设置一次,在路径一创建的时候就设置。

设置颜色:

自定义UIBezierPath,保存颜色,实现一条路径对应一个颜色 辅助功能:

清屏:清空所有路径数组

撤销:移除最后一条路径

橡皮擦:设置画笔为白色

保存:

1> 把画板内容截屏

2> 把图片保存到相册 UIImageWriteToSavedPhotosAlbum

3> 保存相册的回调方法不能乱写,必须按照规定 image:didFinishSavingWithError:contextInfo:

照片选择

1> 通常都是去相册里去照片

2> UIImagePickerController,就可以去手机相册了

3> 用Modal,没有导航控制器,不能push

4> 设置代理,获取图片

5> 把图片传递给paintView

6> 添加到路径,然后重绘。:画图片也需要顺序的

照片处理

1>搞一个和画板一样的透明view,里面搞个UIImageView来显示我们从照片库选择的图片,然后对UIImageView进行旋转,缩放等操作

2> UImageView不能放在layoutSubViews里面设置尺寸,因为要设置他的形变,默认会调用他父类的layoutSubViews,导致一些莫名其妙的原因

3> 在传图片的时候设置他的尺寸,和位置,让他和图片一样的尺寸,显示在中间

4> 长按操作:在长按结束的时候,做操作

1.默认高亮状态,先变浅在恢复,设置alpha

2.动画结束后,把自己截屏,传给控制器里,在交给paintView显示

3.需要移除父视图,使命完成了,而且不移除,不能绘制东西,永远添加到paintView上面

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • Quartz2D以及drawRect的重绘机制字数1487 阅读21 评论1 喜欢1一、什么是Quartz2D Q...
    PurpleWind阅读 766评论 0 3
  • Quartz2D 简介及用途 Quartz 2D 是一个二维绘图引擎,同时支持iOS和Mac系统,Quartz2D...
    45b645c5912e阅读 961评论 1 16
  • 什么是Quartz2D 是一个二维的绘图引擎,同时支持iOS和Mac系统 Quartz2D的API是纯C语言的,它...
    Mario_ZJ阅读 577评论 0 1
  • 什么是Quartz 2D 1>Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac OS X系统(跨平台,...
    青葱烈马阅读 743评论 0 3
  • 今天任曦来我家做客了,我还帮他洗了澡呢,洗完澡的时候,妈妈把饭做好了,炒了两个菜,第一个是豆角和肉,第...
    小王子WXN阅读 303评论 0 2