美文网首页DevSupport
在 iOS 中使用 Skia

在 iOS 中使用 Skia

作者: yehot | 来源:发表于2019-01-13 23:52 被阅读118次

    关于 Skia

    Skia 是一个 Google 开源的 C++ 二维图形库,提供各种常用的API,并可在多种软硬件平台上运行。
    谷歌 Chrome 浏览器、Chrome OS、Android 系统、火狐浏览器、火狐操作系统以及其它许多产品都使用它作为图形引擎。
    特别是近两年开始大火的跨平台 App 开发框架 Flutter,其图形引擎也是基于 Skia。Android 系统内置了 Skia,这也是 Flutter Android SDK 要比 Flutter iOS SDK 小一些的原因。

    Skia 在 Chrome 和 Android 上作为底层的图形引擎,可以类比为 iOS 上的 Core Graphic / Core Animation 一层的框架,可能 Google 并没有大力在上层推广这个框架,所以前端、移动端开发者关注 Skia 并不多。甚至一些做了多年 Android 开发的同事也不知道有这个东西,也可能跟 Android 系统并没有在 Java 层暴露 Skia 的 API 有关。

    关于本文

    Skia 的中英文资料比较少,Skia 官方给的 iOS Demo 也是完全抛弃了 iOS 原生的 Window、Application、View 体系,用 C++ 实现了一版。

    在 iOS 里使用 Skia,目前除了 Flutter,还没有发现其它案例。iOS 内置的 UI 框架已经足够好用,如果不是为了实现跨平台的能力,也不太用的到 Skia。

    如何将 C++ 的 Skia 元素,渲染到 iOS 原生的 UIView 体系上,Skia 本身没有提供解决方案,iOS 端就更没有接口可以用了。所以想在 iOS 平台跑一个 Skia 的 Demo还是比较麻烦的,我参考了 OpenGL 的绘制思路,这里实现了一个将 Skia 的视图元素 Canvas 的 Bitmap,绘制到 iOS 原生 UIView 体系上的一个 Demo。真正应用时不会这样用,可以借助 SDL 或 OpenGL ES 渲染到 Native 层。

    以下是在 iOS 中加载 Skia 的一个 Demo

    Demo

    import Skia ,需要将当前类名改为 .mm

    skia demo
    #import "ViewController.h"
    #import "SkCanvas.h"
    #import "SkGraphics.h"
    #import "SkSurface.h"
    #import "SkString.h"
    #import "SkRRect.h"
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.view.backgroundColor = [UIColor lightGrayColor];
        
        
        int width = 300;
        int height = 500;
        
        
        SkBitmap bitmap;
        bitmap.setInfo(SkImageInfo::Make(width, height, kRGBA_8888_SkColorType, kOpaque_SkAlphaType, nullptr));
        bitmap.allocPixels();
        
        SkCanvas canvas(bitmap);
        canvas.drawColor(SK_ColorWHITE);
        
        SkPaint paint;
        paint.setStyle(SkPaint::kFill_Style);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(4);
        paint.setColor(0xffFE938C);
        
        SkRect rect_sk = SkRect::MakeXYWH(10, 30, 100, 160);
        canvas.drawRect(rect_sk, paint);
        
        SkRRect oval;
        oval.setOval(rect_sk);
        oval.offset(40, 80);
        paint.setColor(0xffE6B89C);
        canvas.drawRRect(oval, paint);
        
        paint.setColor(0xff9CAFB7);
        canvas.drawCircle(180, 50, 25, paint);
        
        rect_sk.offset(80, 50);
        paint.setColor(0xff4281A4);
        paint.setStyle(SkPaint::kStroke_Style);
        canvas.drawRoundRect(rect_sk, 10, 10, paint);
        
        
        SkPaint p;
        p.setTextSize(20);
        p.setStrokeWidth(2.0);
        p.setAntiAlias(true);
        p.setColor(SK_ColorBLACK);
        const char* str = "hello world";
        canvas.drawText(str, strlen(str), 50, 300, p);
        
        
        void* data = bitmap.getPixels();
        
        NSUInteger dataLength = width * height * 4;
        CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
        CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
        CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace,
                                        kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
                                        ref, NULL, true, kCGRenderingIntentDefault);
        
        UIGraphicsBeginImageContext(CGSizeMake(width, height));
        CGContextRef cgcontext = UIGraphicsGetCurrentContext();
        CGContextTranslateCTM(cgcontext, 0, height);
        CGContextScaleCTM(cgcontext, 1.0, -1.0);
        CGContextSetBlendMode(cgcontext, kCGBlendModeCopy);
        CGContextDrawImage(cgcontext, CGRectMake(0.0, 0.0, width, height), iref);
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        CFRelease(ref);
        CFRelease(colorspace);
        CGImageRelease(iref);
        bitmap.reset();
        
        
        UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
        imageView.frame = CGRectMake(0, 0, width, height);
        
        [self.view addSubview:imageView];
    }
    
    @end
    

    Demo 里仅编译 x86_64 版本的静态库,编译方法参考 Skia 官方文档

    Demo 地址

    Skia in Chrome

    可以在 Chrome 里,体验一下 Skia 的 API:
    https://fiddle.skia.org/c/@shapes

    相关文章

      网友评论

        本文标题:在 iOS 中使用 Skia

        本文链接:https://www.haomeiwen.com/subject/hxhrdqtx.html