我希望通过这项研究了解CoreFoundation CGColor对象的内部。我可以从免费的 quartz 项目中找到CGColor结构的示例定义,该定义似乎与IOS声明相匹配(根据我的研究)。
typedef struct CGColor {
CFRuntimeBase obj;
CFTypeID colorID;
CGColorSpaceRef colorSpace;
CGPatternRef pattern;
size_t numberOfComponents;
CGFloat *components;
} *CGColorRef;
(colorID字段由免费的 quartz 命名为nextID,但我认为IOS打算将其用作颜色的唯一标识符,因此它不是一种下一个标识符。)
全局线程安全唯一值被保持,对于每个创建并分配给colorID成员的CGColor对象,该值都会增加1。仅未记录的CGColorGetIdentifier()函数返回此值。
(我猜测单调增加id值可能会提高性能,同时在设备之间转换为校准的颜色查找,反之亦然。)
我已经检查了CoreGraphics及其资源库。我发现只有ripc_GetColor(libRIP.A.dylib)函数会调用CGColorGetIdentifier()函数。
CGColorGetIdentifier的调用堆栈;(希望有助于推断colorID)
0 com.apple.CoreGraphics CGColorGetIdentifier + 0
1 libRIP.A.dylib ripc_GetColor + 112
2 libRIP.A.dylib ripc_DrawGlyphs + 1740
3 com.apple.CoreGraphics CGContextDelegateDrawGlyphs + 108
4 com.apple.CoreGraphics drawGlyphs + 284
5 com.apple.CoreGraphics CGContextShowGlyphsWithAdvances + 208
对于当前的彩色图形上下文操作,ripc_GetColor()计算当前笔触/填充颜色的一些转换,并使用该颜色的引用和colorID缓存这些转换。
因此,对于下一个图形上下文操作,ripc_GetColor()比较先前缓存的和当前的reference和colorID值,以跳过为上一个图形上下文操作已经缓存的颜色转换。
我们知道在创建另一个对象时可以使用已释放对象的引用(内存地址)。因此,仅检查引用不足以确保相同颜色的对象有效,但我们需要比较内容或某种哈希值。因此,我们可以为此使用唯一标识符值。
但是,标识符可以用于单个对象及其引用,因此仅比较id就足够了。但是,引用和id都被使用。我认为工程师不会忽略这样一个简单而关键的事情。
因此,我尝试找出比较ID和refs的必要性,而仅比较IDs就足够了。
它是从以前的方法中遗留下来的,因此不能完全丢弃吗?
最佳答案
如果我理解正确,您是在问为什么有人可能将缓存实现为
void DoSomethingWith(CGColorRef c)
{
static CGColorRef cached_c = NULL;
static CFTypeID cached_colorID;
if (c == cached_c && c->colorID == cached_colorID) ...
而不只是
void DoSomethingWith(CGColorRef c)
{
static CFTypeID cached_colorID = 0;
if (c->colorID == cached_colorID) ...
?好吧,两个明显的原因是
c
可能是一个缓慢的操作(缓存未命中会浪费许多纳秒),因此,如果我们可以通过便宜的指针比较来节省90%的纳秒时间,那就开始吧。 cached_colorID
?在上面的第一个实现中,如果我们假设用户遵守API契约(Contract)并始终传递非null的c
,则一旦我们知道c
== cached_c
,那么我们也知道cached_c != NULL
,因此我们在cached_colorID
中具有有意义的值。在第二种实现中,如果用户传入的第一个c
恰好具有c->colorID == 0
,那么我们将错误地认为我们之前已经看过它,随后便出现了madcap hijinks。 我不知道这两个原因是否是Apple做到了您要看的东西的原因...但是它们似乎是可靠的可能性,不是吗?
关于ios - CGColor内部,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19607886/