引言

学习CoreText,最初的想法是写一个杂志类的应用,因为对网易和zarca应用一些技术的疑问,所以,自己有了很强的兴趣欲和钻研欲,开始这段有点不顺的学习过程。

难题

1、对CGContextRef的CTM不理解,观念导致很多东西没有正确的理解。
2、对NS的了解不多,一些文字绘制方面的座标系问题让自己很迷惑。
3、对CoreText麻烦的API严重不适应。

关于CTM

CTM,Context Translate Matrix。 它是把要绘制的上下文以一个叫做Matrix的东西来表示,可以简单地想作,绘制的上下文的每一个点都映射在Matrix上,你在Matrix上的操作都会使得上下文上的点产生相应的变动。如放大、旋转、移动。

在一般的教程里面,为了达到旋转或放大缩小的目的,一般都会先改变这个上下文,如:

1
2
3
4
5
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0f, -1.0f); // some draw code
// ....

然后进行绘图操作。那么这个绘图操作是怎么做的呢?这个对Matrix的操作,为什么是放在前面而不是放在后面,为什么放在后面又没有效果呢?不是说改变Matrix就会改变上面的映射的所有点呢?这些常规的逻辑思维使得问题越发无法理解和解决。那么我们先从context来了解。

一般情况也,我们总是认为context就是画布,所有的matrix旋转都是针对画布的旋转,虽然这样的理解是错误的,但是得到的结果却是正确的,但是如果在一些稍复杂的坐标系转换时,或者更改matrix时在之前或之后的理解时,这样理解就会得到难得理解的结果。

其实context说的是绘画人所处的角度上下文。如下图,默认的情况下,绘画人的角度是正对着画布的:

画布是白色的,而我则是在左上角用一个黄色的三角形来标识它的左上角,使用left top来标识context的左上角,而绘画人是黄色的圆形。

要记着!!画布无论怎么样都是正对着屏幕的,它不会旋转,或者放大缩小,或者移动。

那么为什么又看起来我放大了或者移动了呢?其实移动的是你的context,也就是你所处的context视角,我举个例子,比方说我要旋转180度在左上角写一个“abcdefg”。

首先,我要先旋转180度:

然后,我在左上角写上“abcdefg”:

然后重置context:

可以看到,我们改变context只是改变了自己面对画布的角度,而画布仍然是正对着屏幕的,自己始终以context的左上角为自己角度的左上角,而不是以画布的左上角为左上角,也就是说,这时绘画时的座标(0,0)是你旋转后context的left top,而不是画布 的左上角,记着这一点很重要。

所以,在绘画的时候,其实是倒着画在了画布的右下角上。而重置context,则是把自己正对着画布而已。这也就说清了为什么是在使用matrix更改context之后进行绘图有效(把自己面对画布的角度先调整了),而不是在画了之后再调整(因为你都画完了,再调整自己的角度还有什么用?)。

正确理解使用matrix更改context的方式很重要,因为这涉及到坐标系的问题,之后的CoreText相当讨论会讲到一个例子。

关于NS座标系

NS坐标系是以左下角为(0,0),与iOS的坐标系在Y上是相反的,所以,在iOS进行CoreText进行绘图或文字的时候,X方向是一致的,但是Y则是倒过来的。如下图:

那么怎么办呢?想想,仔细看上面这张图,貌似像是正常方向的倒影,但是水平线却在最上面。嗯,挪下来,然后再反过来,看一下效果。如下图:

效果:

效果果然如图所示,好!!

可是是不是就这样完了呢?不是,还有一个更为重要的问题,这个时候,进行了两次的转换matrix,context的left top在哪里呢?

根据之前的理论,那得让自己先把自己向下移,然后把头倒过来,OK,这下明白了,这下画布的左下角变成了context的左上角,别的都没变。这时,当你在(20, 20)画一个长方形,其实就是画布的(20, canvas.height - 20 + rect.size.height)的位置上画了个长方形,而且是倒过来的。

仔细想想这个,有趣的事情还有很多,因为按照自己看过本文之前的理论,可能会非常惊讶为什么得到的结果和自己想的不一样,一直以为是在(20, 20)处画一个长方形,结果却刚好相反,这就是没有理解context及matrix的正确含义所致。

CoreText中坐标转换的一些理解的更多相关文章

  1. SQL SERVER 2005/2008 中关于架构的理解(二)

    本文上接SQL SERVER 2005/2008 中关于架构的理解(一)      架构的作用与示例 用户与架构(schema)分开,让数据库内各对象不再绑在某个用户账号上,可以解决SQL SERVE ...

  2. SQL SERVER 2005/2008 中关于架构的理解(一)

    SQL SERVER 2005/2008 中关于架构的理解(一) 在一次的实际工作中碰到以下情况,在 SQL SERVER 2008中,新建了一个新用户去访问几张由其他用户创建的表,但是无法进行查询, ...

  3. C++中 类的构造函数理解(一)

    C++中 类的构造函数理解(一) 写在前面 这段时间完成三个方面的事情: 1.继续巩固基础知识(主要是C++ 方面的知识) 2.尝试实现一个iOS的app,通过完成app,学习iOS开发中要用到的知识 ...

  4. ECshop中的session机制理解

    ECshop中的session机制理解     在网上找了发现都是来之一人之手,也没有用自己的话去解释,这里我就抛砖引玉,发表一下自己的意见,还希望能得到各界人士的指导批评! 此session机制不需 ...

  5. [开发技巧]·Numpy中对axis的理解与应用

    [开发技巧]·Numpy中对axis的理解与应用 1.问题描述 在使用Numpy时我们经常要对Array进行操作,如果需要针对Array的某一个纬度进行操作时,就会用到axis参数. 一般的教程都是针 ...

  6. 【C++】类中this指针的理解

    转自 苦涩的茶https://www.cnblogs.com/liushui-sky/p/5802981.html C++类中this指针的理解 先要理解class的意思.class应该理解为一种类型 ...

  7. Java中线程同步的理解 - 其实应该叫做Java线程排队

    Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可 ...

  8. OpenGL中的像素包装理解

    OpenGL中的像素包装理解 像素包装 位图和像素图很少会被紧密包装到内存中.在许多硬件平台上,考虑到性能的原因位图和像素图的每一行的数据会从特殊的字节对齐地址开始.绝大多数编译 器会自动把变量和缓冲 ...

  9. tomcat的配置文件server.conf中的元素的理解

    tomcat的配置文件server.conf中的元素的理解 tomcat作为一个servlet服务器本身的配置文件是tomcat_home/conf/server.conf,这个配置文件中有很多元素, ...

随机推荐

  1. redis cluster 集群搭建步骤和注意事项

    1.安装Ubuntu ,修改root的密码. sudo passwd  (apt-get update 更新系统) 2.安装 Gcc 和G++  sudo apt-get install build- ...

  2. (转)JSON对象长度和遍历方法

    最近在修改一个HTML页面的JS的时候遍历JSON对象,却怎么也调试不通过.怪这个HTML网页不知道用了什么方法禁止了js错误提示,刚开始的时候不知道有这个问题,用chrome的开发人员工具都没发现错 ...

  3. Android Activity 分类

    在安卓系统中,Activity 按照优先级可以分为三种: 1. 前台Activity,是指正在和用户进行交互的Activity,优先级最高: 2.可见但非前台Activity,是指可见但无法与用户进行 ...

  4. Oracle 大数据处理(一)

    数据量:  日数据 2000万   月数据 8000万 处理方式:建立父子分区,采用Range+list模式分区,日期作为主分区,地域作为子分区 索引选择: 由于应用于查询比较多,故建立位图索引,效率 ...

  5. polya定理小结

    polya的精髓就在与对循环节的寻找,其中常遇到的问题就是项链染色类问题. 当项链旋转时有n种置换,循环节的个数分别是gcd(n, i); 当项链翻转时有n种置换,其中当项链珠子数位奇数时,循环节的个 ...

  6. ECSTORE1.2 重启开启信任登陆模块(删除KEY)

    1).若启用Mongodb 需要删除KEY分别为 1 2 3 be90a668d9f2eb1950bae1bf6b0835ce 939e64939c3f65cfb646e7948c5b80df 58d ...

  7. windows下配置lamp环境(5)---配置MySQL5.6

    开始配置mysql 1.创建配置文件my.ini   1.进入C:\wamp\MySQL   2.把my-default.ini 另存一份:my.ini   3.开始编辑mysql的配置文件,打开my ...

  8. Python新手学习基础之条件语句——elif语句

    elif语句 (相当于C语言的else if) 在Python中,当我们需要有更多的判断条件时,我们往往会使用另外一种语法表达,即使用elif: if 判断条件1: 执行语句1 elif 判断条件2: ...

  9. [Python 3.x 官方文档翻译]Whetting Your Appetite 欢迎您的使用

    If you do much work on computers, eventually you find that there’s some task you’d like to automate. ...

  10. canvas个人总结

    今天做了大量的canvas作业,发现很多的步奏都是一样的,我自己就封装了一个画直线形2D图形函数.功能不是很强大. function drawModule(Json,strokeStyle,fillS ...