Android 深色模式适配原理分析( 五 )


frameworks/base/libs/hwui/RecordingCanvas.cpp
void DisplayListData::applyColorTransform(ColorTransform transform) {// 使用transform作为参数执行color_transform_fns函数组this->map(color_transform_fns, transform);}template inline void DisplayListData::map(const Fn fns[], Args... args) const {auto end = fBytes.get() + fUsed;// 遍历需要绘制的元素op , 并调用对应类型的colorTransformForOp函数for (const uint8_t* ptr = fBytes.get(); ptr < end;) {auto op = (const Op*)ptr;auto type = op->type;auto skip = op->skip;if (auto fn = fns[type]) {// We replace no-op functions with nullptrsfn(op, args...);// to avoid the overhead of a pointless call.}ptr += skip;}}typedef void (*color_transform_fn)(const void*, ColorTransform);#define X(T) colorTransformForOp(),static const color_transform_fn color_transform_fns[] = {// 相当于 colorTransformForOp()X(Flush)X(Save)X(Restore)X(SaveLayer)X(SaveBehind)X(Concat44)X(Concat)X(SetMatrix)X(Scale)X(Translate)X(ClipPath)X(ClipRect)X(ClipRRect)X(ClipRegion)X(DrawPaint)X(DrawBehind)X(DrawPath)X(DrawRect)X(DrawRegion)X(DrawOval)X(DrawArc)X(DrawRRect)X(DrawDRRect)X(DrawAnnotation)X(DrawDrawable)X(DrawPicture)X(DrawImage)X(DrawImageNine)X(DrawImageRect)X(DrawImageLattice)X(DrawTextBlob)X(DrawPatch)X(DrawPoints)X(DrawVertices)X(DrawAtlas)X(DrawShadowRec)X(DrawVectorDrawable)X(DrawWebView)};#undef Xstruct DrawImage final : Op {static const auto kType = Type::DrawImage;DrawImage(sk_sp}}sk_sp image;SkScalar x, y;// 这里SK指代skia库对象SkPaint paint;BitmapPalette palette;void draw(SkCanvas* c, const SkMatrix }};template constexpr color_transform_fn colorTransformForOp() {if// 如果类型T有paint变量 , 并且有palette变量constexpr(has_painttransformPaint(transform, const_cast(};}else ifconstexpr(has_paint) {return [](const void* opRaw, ColorTransform transform) {// TODO: We should be const. Or not. Or just use a different map// Unclear, but this is the quick fix// 非Bitmap绘制const T* op = reinterpret_cast(opRaw);transformPaint(transform, const_cast(};}else {return nullptr;}}frameworks/base/libs/hwui/CanvasTransform.cpp
这里进行具体的颜色转换逻辑 , 我们首先关注非Bitmap绘制的颜色转换
// 非Bitmap绘制颜色模式转换bool transformPaint(ColorTransform transform, SkPaint* paint) {applyColorTransform(transform, *paint);return true;}// 非Bitmap绘制颜色模式转换static void applyColorTransform(ColorTransform transform, SkPaint// 具体绘制颜色转换逻辑SkColor newColor = transformColor(transform, paint.getColor());// 将画笔颜色修改为转换后的颜色paint.setColor(newColor);// 有渐变色情况if (paint.getShader()) {SkShader::GradientInfo info;std::array _colorStorage;std::array _offsetStorage;info.fColorCount = _colorStorage.size();info.fColors = _colorStorage.data();info.fColorOffsets = _offsetStorage.data();SkShader::GradientType type = paint.getShader()->asAGradient(if (info.fColorCount <= 10) {switch (type) {// 线性渐变并且渐变颜色少于等于10个的情况case SkShader::kLinear_GradientType:for (int i = 0; i < info.fColorCount; i++) {// 对渐变色颜色进行转换info.fColors[i] = transformColor(transform, info.fColors[i]);}paint.setShader(SkGradientShader::MakeLinear(info.fPoint, info.fColors,info.fColorOffsets, info.fColorCount,info.fTileMode, info.fGradientFlags, nullptr));break;default:break;}}}// 处理colorFilterif (paint.getColorFilter()) {SkBlendMode mode;SkColor color;// TODO: LRU this or something to avoid spamming new color mode filtersif (paint.getColorFilter()->asAColorMode(paint.setColorFilter(SkColorFilters::Blend(color, mode));}}}static SkColor transformColor(ColorTransform transform, SkColor color) {switch (transform) {case ColorTransform::Light:return makeLight(color);case ColorTransform::Dark:return makeDark(color);default:return color;}}// 前景色变亮static SkColor makeLight(SkColor color) {// 将sRGB色彩模式转换成Lab色彩模式Lab lab = sRGBToLab(color);// 对亮度L维度取反float invertedL = std::min(110 - lab.L, 100.0f);if (invertedL > lab.L) {// 若取反后亮度变亮 , 则替换原来亮度lab.L = invertedL;// 重新转换为sRGB模式return LabToSRGB(lab, SkColorGetA(color));} else {return color;}}// 后景色变暗static SkColor makeDark(SkColor color) {// 将sRGB色彩模式转换成Lab色彩模式Lab lab = sRGBToLab(color);// 对亮度L维度取反float invertedL = std::min(110 - lab.L, 100.0f);if (invertedL