Apple - Text System Storage Layer Overview

本文翻译整理自:Text System Storage Layer Overview(更新日期:2012-09-19
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextStorageLayer/TextStorageLayer.html#//apple_ref/doc/uid/10000087i


文章目录

  • 一、文本系统存储层简介概述
    • 1、谁应该阅读此文档
    • 2、本文件的组织
    • 3、另见
  • 二、存储层:NSTextStorage类
  • 三、布局几何:NSTextContainer类
  • 四、创建文本存储
  • 五、更改文本存储
  • 六、显示文本容器
  • 七、计算区域、边界矩形和插图
  • 八、跟踪文本视图的大小
  • 九、创建NSTextStorage的子类


一、文本系统存储层简介概述

文本系统存储层概述讨论了Cocoa文本系统用于存储用于文本布局的文本和几何图形信息的工具。


1、谁应该阅读此文档

如果您需要直接使用文本存储层,您应该阅读本文档。
例如,您可能需要以编程方式更改文本存储对象中的文本或扩展其功能。

要理解本材料,您应该对Cocoa编程约定有一个大致的了解。
您还应该阅读文本系统概述。


2、本文件的组织

本文档包含以下文章:

  • 存储层:NSTextStorage类提供了文本存储对象功能的一般介绍。
  • 布局几何:NSTextContainer类解释了文本容器如何定义系统布局文本的区域以及它们如何与其他文本系统对象交互。
  • 创建文本存储说明如何创建和设置文本存储对象。
  • 更改文本存储描述了以编程方式编辑文本存储对象中的文本的过程。
  • 显示文本容器说明了如何在文本视图或其他NSView对象中显示文本存储对象中的文本。
  • 计算区域、边界矩形和插图讨论了如何定义文本容器的文本布局区域。
  • 跟踪文本视图的大小说明了如何设置文本容器,以便其几何形状与其关联的文本视图交互。
  • 创建NSTextStorage的子类讨论了NSTextStorage子类的要求。

3、另见

如需进一步阅读,请参阅以下文件:

  • 属性字符串编程指南 提供了有关构建NSTextStorage的属性字符串对象的信息。
    NSTextStorageNSMutableAttributedString的子类。
  • 文本布局编程指南 描述了涉及文本存储、文本容器、文本视图和布局管理器对象的布局过程。

二、存储层:NSTextStorage类

一个NSTextStorage对象 用作Cocoa文本系统的字符数据存储库。
该数据的格式是一个属性字符串,它是一个字符序列(在Unicode编码中)和应用于它们的属性(如字体、颜色和段落样式)。
表示属性字符串的类是NSAttributedStringNSMutableAttributedString,其中NSTextStorage是一个子类。
从概念上讲,文本块中的每个字符都有一个与之关联的键和值的字典。
键命名一个属性(如NSFontAttributeName),关联值指定该属性的特征(如Helvetica 12-point)。
有关属性字符串的更多信息,请参阅 属性字符串编程指南
图1说明了NSTextStorage类,显示了它的NSMutableAttributedString组件和附加功能。

图1 NSTextStorage的功能
在这里插入图片描述


通过NSTextStorage方法,您可以通过编程方式对NSTextView对象显示的文本的属性进行操作;例如,您的代码可以遍历文本,收紧或放宽特定字体和大小的所有字符的字距。
NSTextView对象使用户能够通过直接操作来影响字符属性;例如,用户选择一些文本,并通过选择Tighten菜单命令来减少字符之间的行间距。


三、布局几何:NSTextContainer类

一个NSTextContainer对象定义了Cocoa文本系统在页面上布置文本的区域。
默认情况下,文本容器定义一个简单的矩形区域,但是您可以创建子类来定义任何几何形状的区域,包括文本流动周围有孔的区域。

NSTextContainer中提供了四个主要文本对象之一。
文本容器与文本存储对象、布局管理器和文本视图一起工作,以存储、布局和显示属性化的文本字符串。
特别是,文本容器直接与布局管理器一起工作,布局管理器使用一个NSTypesetter对象来生成线片段矩形,在其中放置字形(字符形状),如线片段生成

当排字器生成行片段时,文本容器特别关注文本布局的前进方向。
布局方向有两个方面:行扫描和行移动。
行扫描是系统在行内布置字形的方向。
行移动是系统在页面上布置行的方向。
排字器对象确定这些参数,并将它们作为常量值传递给文本容器。
行扫描和行移动都可以从左到右、从右到左、从上到下和从下到上进行。
此外,排字器可以指定不移动行。

注意:内置排字器目前仅支持从上到下的行移动和从左到右的扫描。
这些排字器确实通过在行片段内以适当的显示顺序排列来处理双向文本(希伯来语和阿拉伯语),但它们不使用行扫描机制。

布局管理器维护一个文本容器数组。
它向它的委托发送一条消息,每当它填充一个文本容器时,委托就可以添加一个新的要填充的文本容器。
如果文本容器改变了大小,或者如果对容器中布局文本的更改使布局无效,那么系统将使布局管理器数组中所有后续容器中的布局无效。

您可以指定文本容器跟踪其文本视图的大小;也就是说,如果用户调整视图大小,文本容器将调整自身大小以匹配。
有关详细信息,请参阅跟踪文本视图的大小。

NSTextContainer实例具有初始化、管理与布局管理器和文本视图的连接、获取和设置容器大小、生成行片段和命中测试的方法。
此外,NSTextContainer具有获取和设置应用于行片段的填充量的方法。
行片段填充是行片段末尾包含的额外空间,因此布局的字形不会直接接触页面上的其他元素,例如图形。


四、创建文本存储

作为一个类集群的抽象类,分配和初始化一个NSTextStorage对象实际上会产生一个私有子类的实例,可以使用任何NSAttributedStringNSMutableAttributedString初始化方法来创建一个NSTextStorage对象。

创建文本存储对象后,使用addLayoutManager:NSLayoutManager对象添加到文本存储中。
单个文本存储对象可以有多个布局管理器(这就是为什么此方法名称以“add”而不是“set”开头)。

以这种方式创建文本存储对象并添加布局管理器是以编程方式组装文本系统过程的一部分,在 Cocoa文本体系结构指南 中的“创建文本系统对象”中有更详细的描述。
您还可以创建一个NSTextView对象并让它自动组装文本系统,在这种情况下文本视图创建(并稍后释放)文本存储对象。
有关详细信息,请参阅以编程方式创建NSTextView。


五、更改文本存储

一个NSTextStorage对象的行为最好的说明是按照您发送的消息来更改它的文本。
有三个阶段来编辑一个文本存储对象:

  1. 第一阶段是向它发送一个beginEditing消息来宣布一组更改。
  2. 在第二阶段,您向它发送一些编辑消息,例如deleteCharactersInRange:addAttributes:range:,以影响字符或属性的更改。
    每次发送此类消息时,文本存储对象都会调用edited:range:changeInLength:以跟踪自收到beginEditing消息以来受影响的字符范围。
  3. 对于第三阶段,当您完成对文本存储对象的更改后,您将向它发送endEditing消息。
    这将导致它调用自己的processEditing方法,在记录的更改字符范围内固定属性。
    (有关属性固定的信息,请参阅 文本属性编程主题 )。

修复属性后,文本存储对象向每个关联的布局管理器发送一条消息,指示文本存储对象中已更改的范围以及这些更改的性质。
布局管理器反过来使用此信息重新计算其字形位置,并在必要时重新显示。
NSTextStorage还保留一个委托,并在处理编辑前后向其发送消息。


六、显示文本容器

您通常使用NSTextView对象来显示NSTextContainer中的文本。
一个NSTextView只能有一个NSTextContainer;但是,因为这两个是独立的对象,您可以替换一个NSTextView的容器来更改它显示的文本的布局。
您还可以在任何NSView中显示NSTextContainer的文本,方法是用lockFocus锁定图形焦点并使用NSLayoutManager方法drawBackgroundForGlyphRange:atPoint:drawGlyphsForGlyphRange:atPoint:
如果您不需要实际显示文本——例如,如果您只计算换行符或行数或页数——您可以使用NSTextContainer而不需要NSTextView


七、计算区域、边界矩形和插图

一个NSTextContainer对象的区域是由一个边界矩形定义的其坐标系从左上角的(0,0)开始。
这个矩形的大小由containerSize方法返回,并使用setContainerSize:.您可以定义一个容器的区域,使其始终保持相同的形状,例如直径是边界矩形尺寸较窄的圆,或者您可以定义相对于边界矩形的区域,例如适合边界矩形内部的椭圆形区域(当边界矩形为正方形时,这是一个圆)。
无论文本容器的形状如何,它的NSTextView总是剪辑绘制到其边界矩形。
图1说明了文本容器的这些方面。

图1 文本容器区域、边框和插图

在这里插入图片描述


一个NSTextContainer的子类通过覆盖三个方法来定义其区域。
第一个方法,isSimpleRectangularTextContainer,指示该区域当前是否为非旋转矩形,从而允许NSLayoutManager优化文本布局(由于自定义文本容器通常定义更复杂的区域,因此您对该方法的实现可能会返回NO)。
第二种方法,containsPoint:,用于测试鼠标事件,并确定给定点是否位于该区域中。
第三种方法,lineFragmentRectForProposedRect:sweepDirection:movementDirection:remainingRect:,用于文本的实际布局,根据可用于放置文本的矩形定义区域。
此过程在线段生成

一个文本容器通常覆盖它的文本视图,但是它可以用setTextContainerInset:方法插入到视图框架中。
文本容器的边框从插入位置开始,然后建立文本容器区域的限制。
当文本容器跟踪其文本视图的高度或宽度时,插图还有助于确定边框的大小,如跟踪文本视图的大小中所述。

请注意,文本容器插页不能完全确定容器在文本视图中的位置。
文本视图计算文本容器在其中的位置,它试图保持文本容器插页给出的空间量,但是根据文本视图和文本容器的相对大小,这可能是不可能的。
还有可能分配的空间比文本容器插页指定的空间多。
如果您想确定文本容器的真实位置——例如,在容器和视图坐标之间进行转换——您应该使用textContainerOrigin方法,这是文本视图计算的实际值。


八、跟踪文本视图的大小

您可以设置NSTextContainer对象来跟踪其NSTextView对象的大小,并在文本视图大小更改时调整其自身的大小以匹配。
setHeightTracksTextView:setWidthTracksTextView:方法允许您控制任一维度的跟踪。

当文本容器调整其大小以匹配其文本视图时,它会考虑文本视图指定的插页,因此边界矩形会尽可能从每条边插入。
换句话说,跟踪其文本视图大小的文本容器总是比给定维度中的文本视图小两倍。
假设文本容器设置为跟踪宽度,其文本视图为其插页(10,10)。
现在,如果文本视图的宽度更改为138,则文本容器的左上角设置为位于(10,10),其宽度设置为118,因此其右边缘距文本视图右边缘10点。
它的高度保持不变。

无论是否跟踪其文本视图的大小,文本容器都不会随着文本的添加或删除而增长或缩小;相反,NSLayoutManager对象根据文本容器中实际填充文本的部分调整文本视图的大小。
要允许以这种方式调整文本视图的大小,请根据需要使用setVerticallyResizable:setHorizontallyResizable:方法(继承自NSText),将文本容器设置为不跟踪其文本视图的大小,并将文本容器的大小设置为足够大的尺寸,以容纳大量文本——例如,10,000,000点(这在处理或存储方面不会产生任何成本)。

请注意,文本视图可以根据其文本容器调整大小,文本容器可以根据其文本视图调整自身大小。
如果您将两个对象设置为在同一维度上自动调整大小,您的应用程序可能会陷入无限循环。
当文本添加到文本容器时,文本视图会调整大小以适应实际用于文本的区域;这会导致文本容器自行调整大小并中继其文本,这会导致文本视图再次调整大小,依此类推。
每种类型的大小跟踪都有其适当的用途;确保在任一维度上只使用一个。


九、创建NSTextStorage的子类

NSTextStorage不是一个完全具体的类;相反,它是一个类集群的抽象超类。
它定义了NSLayoutManager对象的存储并实现了一些方法,但不向子类提供原始的属性字符串方法。
子类必须定义其属性字符串的存储,通常是NSMutableAttributedString类型的实例变量,覆盖init并定义自己的初始化方法,并实现NSAttributedStringNSMutableAttributedString的原始方法是:

  • string
  • attributesAtIndex:effectiveRange:
  • replaceCharactersInRange:withString:
  • setAttributes:range:

除了这些要求之外,如果子类覆盖或添加任何直接更改其字符或属性的方法,这些方法必须在执行更改后调用edited:range:changeInLength:以使更改跟踪信息保持最新。
有关详细信息,请参阅方法描述。


2024-06-16(日)

把想做的做了,以后就没有那么多留恋了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/857618.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebSocket走私实践(附赠LiveGBS监控系统未授权管理员密码重置)

WebSocket走私实践(附赠LiveGBS监控系统未授权管理员密码重置) 对此,我特别感谢TryHackMe和HackTheBox academy,永远相信和追随英国TryHackMe所教导的网络安全知识,并保持学习 WebSocket走私相关的知识在这里 前段时间学习过htt…

小程序 UI 设计缔造独特魅力

小程序 UI 设计缔造独特魅力

qt 简单实验 一个可以向右侧拖拽缩放的矩形

1.概要 目的是设置一个可以拖拽缩放的矩形,这里仅用右侧的一个边模拟这个过程。就是为了抓住核心,这个便解决了,其他的边也是一样的。而这个更能体现原理。 2.代码 2.1 resizablerectangle.h #ifndef RESIZABLERECTANGLE_H #define RESIZ…

grafana 通过自定义API获取数据

一、安装插件 安装infinity插件 二、配置数据源 三、配置图表 1、数据 这边提供一个go的demo package mainimport ("math/rand""net/http""time""github.com/gin-gonic/gin" )func main() {router : gin.Default()rand.Seed(time.…

怎样去掉卷子上的答案并打印

当面对试卷答案的问题时,一个高效而简单的方法是利用图片编辑软件中的“消除笔”功能。这种方法要求我们首先将试卷拍摄成照片,然后利用该功能轻松擦除答案。尽管这一方法可能需要些许时间和耐心,但它确实为我们提供了一个可行的解决途径。 然…

【2024.6.22】今日科技时事:科技前沿大事件

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…

如何避免vue的url中使用hash符号?

目录 1. 安装 Vue Router 2. 配置 Vue Router 使用 history 模式 3. 更新 main.js 4. 配置服务器以支持 history 模式(此处需要仔细测试) a. Nginx 配置 b. Apache 配置 5. 部署并测试 总结 在 Vue.js 项目中,避免 URL 中出现 # 符号的…

宝塔部署GeoServer教程

前期准备:下载geoserver 直接用我上传的geoserver或者是去官网下https://geoserver.org/release/stable/ 压缩包的geoserver版本是:2.25.1 jdk要求版本是:jdk11以上 tomcat版本:可选8或者9,建议用9 windows选择Window…

视频监控统一管理平台LntonCVS安防视频监控系统视频汇聚方案

LntonCVS平台最初被设计为一个以视频汇聚为核心的平台。那么,什么是视频汇聚平台,以及它是如何处理视频资源的呢?简单来说,视频汇聚平台能够从不同的视频源(如直播和点播)收集、整合和展示视频内容。以下是…

Docker可视化web工具

docker run --restart always --name docker.ui -d -v /var/run/docker.sock:/var/run/docker.sock -p 8989:8999 joinsunsoft/docker.ui #--restart always:重启策略,只要关闭就会重启 http://192.168.10.51:8989 账号:ginghan 密码&#xf…

写代码必用字体

下载链接 字体下载链接 使用情况/截图 软件:DEV-CPP 系统:Win10专业版 自带判等、大于、小于等符号的专属字体

计算机组成原理网课笔记2

存储系统基本概念 CPU:运算器控制器。​ 作为计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。 ​ 主存储器的基本组成 半导体元件的原理 在电容上面的金属板加一个5V的高电平,产生电压差,电容里面的电荷就会开…

计算机系统基础实训五—CacheLab实验

实验目的与要求 1、让学生更好地应用程序性能的优化方法; 2、让学生更好地理解存储器层次结构在程序运行过程中所起的重要作用; 3、让学生更好地理解高速缓存对程序性能的影响; 实验原理与内容 本实验将帮助您了解缓存对C程序性能的影响…

【面向对象】复习(二)

内存对齐 class A{ static int a; } int main(){ A obj; cout<<sizeof(obj); } 在你的代码中&#xff0c;class A 包含一个静态成员变量 a。静态成员变量不属于类的任何特定实例&#xff0c;而是属于整个类。因此&#xff0c;在计算类的实例大小时&#xff0c;静态…

OpenXlab应用部署踩坑记录

参考博客&#xff1a; OpenXlab应用部署经验_xlabdemo-web-CSDN博客 书生浦语大模型实战营Day04OpenXLab 部署_openxlab.org.cn上传模型-CSDN博客 应用创建流程 | OpenXLab浦源 - 文档中心 1、已经在OpenXlab上上传好了模型 在上传好的模型查看一下如何使用模型 2、github…

基于肤色模型的人脸识别,基于野火FPGA ZYNQ开发板

使用芯片为ZYNQ—7020&#xff0c;基于野火FPGA ZYNQ开发板 肤色模型简介 YCrCb也称为YUV&#xff0c;主要用于优化彩色视频信号的传输。与RGB视频信号传输相比&#xff0c;它最大的优点在于只需占用极少的频宽&#xff08;RGB要求三个独立的视频信号同时传输&#xff09;。其…

pytets测试框架中如果需要运行多个测试套件时pytest.ini文件设置

pytets测试框架中如果需要运行多个测试套件时pytest.ini文件设置方法 testpaths testcases/fenmi testcases/weixin testcases/Zgen

MQTTfx连接阿里云(详细版)

1、介绍 作为物联网开放平台&#xff0c;阿里云可谓是吸引大多数嵌入式爱好者的平台。物联网MQTT协议火热的今天&#xff0c;你使用过阿里云吗&#xff1f;本篇文章带你接触阿里云&#xff0c;实现MQTT通信。 我们在测试MQTT之前先了解下什么是MQTT协议。大家都知道它是一种发…

STM32之二:时钟树

目录 1. 时钟 2. STM3时钟源&#xff08;哪些可以作为时钟信号&#xff09; 2.1 HSE时钟 2.1.1 高速外部时钟信号&#xff08;HSE&#xff09;来源 2.1.2 HSE外部晶体电路配置 2.2 HSI时钟 2.3 PLL时钟 2.4 LSE时钟 2.5 LSI时钟 3. STM32时钟&#xff08;哪些系统使用时…

css-Echarts图表柱状图,X轴横坐标值显示不完全问题

1.问题 在Echarts图表中当横坐标数值过多&#xff0c;或者数值过长时会导致部分横坐标不显示。数据量少或简单会默认显示完全&#xff0c;当放大时会导致部分横坐标隐藏。 更改第一个Mon字段名 会发现偶数横坐标显示隐藏&#xff1b; 2.解决方法 2.1 在x横坐标中添加interval…