美文网首页
Windows编译skia

Windows编译skia

作者: 豪爵吸金ing | 来源:发表于2021-06-15 10:58 被阅读0次

    Win10(VS2019/2017,python2.7,翻墙):

    1. depot_tools:
    1. ninja:
    • 下载至任意位置并添加至环境变量PATH:git clone git://github.com/ninja-build/ninja.git
    • 进入ninja文件夹,执行python configure.py --bootstrap (确保python执行python2.7)
    1. skia:
    • skia目前貌似不能直接git clone https://skia.googlesource.com/skia.git 需要点开https://skia.googlesource.com/skia.git这个链接,手动点击左侧branches里的master进行下载
    • 上述下载中,如果翻墙了仍然有超时问题,考虑有可能是git没有走ss端口:
      • git config --global http.proxy socks5://127.0.0.1:1087
      • git config --global https.proxy socks5://127.0.0.1:1087
    1. 用gn工具构建工程:
    • 首先修改 skia\gn\BUILDCONFIG.gn文件 win_vc = "C:/Program Files (x86)/Microsoft Visual Studio/2017/Enterprise/VC",如果是vs2019则应该是"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC" 具体取决于安装路径
    • 然后进入skia文件夹,cmd中:
      • gn gen out/Static构建静态库
      • gn gen out/Debug构建Debug版本
      • gn gen out/Release --args="is_debug=false" 构建Release版本
      • 也可以gn gen out/sln --ide=vs,会构建出out/sln解决方案目录,但是有可能无法正确生成,尽量不要使用这个
    1. 用ninja工具生成可执行或库:
    • ninja -C out/Static
    • ninja -C out/Release
    • ninja -C out/Debug
    1. 在vs项目中使用skia:
    • 新建项目,配置选择为release x64,附加包含目录需要包括了skia的include和src文件夹,如项目下有myInclude作为附加包含目录,则将skia中的include和src文件夹平行复制进myInclude。附加依赖库主要需要skia.lib,在out/Static里,以及其他有可能需要的lib文件如icu.lib等
    • 由于skia不负责具体的渲染,需要有opengl等,因此简单地测试skia的绘制效果需要将其作为图片存下来看效果。实例代码如下:
    #include "include/core/SkBitmap.h"
    //#include "include/codec/SkDevice.h"
    #include "include/core/SkPaint.h"
    #include "include/core/SkRect.h"
    #include "include/core/SkImageEncoder.h"
    #include "include/core/SkTypeface.h"
    #include "include/core/SkCanvas.h"
    #include "include/core/SkTypeface.h"
    #include "include/core/SkFont.h"
    #include "include/core/SkTextBlob.h"
    #include "include/core/SkPath.h"
    
    const char* pText = "Hello world!";
    
    int main()
    {
            const int width = 1000;
            const int height = 1000;
    
            SkBitmap bitmap;
            SkImageInfo ii = SkImageInfo::Make(1000,1000, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
            bitmap.allocPixels(ii, ii.minRowBytes());
    
            SkPaint paint;
            paint.setStyle(SkPaint::kStroke_Style);
            paint.setColor(0xff1f78b4);
            paint.setStrokeWidth(8);
    
            bitmap.allocPixels();
            SkCanvas canvas(bitmap);
            canvas.clear(0x00000000);// 背景为透明色
    
            if(0){
                    SkRect rc;
                    rc.fLeft = 123;
                    rc.fTop = 0;
                    rc.fRight = 222;
                    rc.fBottom = 50;
                    canvas.drawOval(rc, paint);
            }
    
            if (0) {
                    //测试奇偶填充效果1
                    SkPath path;
    
                    path.addCircle(200, 200, 70);
                    path.addCircle(300, 200, 70);
                    path.addCircle(250, 250, 70);
    
                    paint.setAntiAlias(true);//抗锯齿
                    paint.setStyle(SkPaint::kFill_Style);
                    paint.setStrokeWidth(1);
                    paint.setColor(SK_ColorBLACK);
                    canvas.drawPath(path, paint);
            }
            if (0) {
                    //测试奇偶填充效果2
                    SkPath path, path1, path2, path3;
                    SkPoint pt[11];
                    pt[0] = SkPoint::Make(200, 400);
                    pt[1] = SkPoint::Make(400, 300);
                    pt[2] = SkPoint::Make(600, 300);
                    pt[3] = SkPoint::Make(800, 400);
                    pt[4] = SkPoint::Make(700, 800);
                    pt[5] = SkPoint::Make(600, 600);
                    pt[6] = SkPoint::Make(500, 600);
                    pt[7] = SkPoint::Make(500, 400);
                    pt[8] = SkPoint::Make(600, 300);
                    pt[9] = SkPoint::Make(800, 200);
    
                    
                    //一条完整path
                    if (0) {
                            path.moveTo(pt[0]);
                            path.cubicTo(pt[1], pt[2], pt[3]);
                            path.cubicTo(pt[4], pt[5], pt[6]);
                            path.cubicTo(pt[7], pt[8], pt[9]);
                            path.lineTo(pt[3]);
                    }
    
                    //三条path加进去
                    if (1) {
                            path1.moveTo(pt[0]).cubicTo(pt[1], pt[2], pt[3]);
                            path2.moveTo(pt[3]).cubicTo(pt[4], pt[5], pt[6]);
                            path3.moveTo(pt[6]).cubicTo(pt[7], pt[8], pt[9]);
                            path.addPath(path1).addPath(path2).addPath(path3);
                    }
    
                    paint.setAntiAlias(true);//抗锯齿
                    paint.setStyle(SkPaint::kStrokeAndFill_Style);
                    paint.setStrokeWidth(1);
                    paint.setColor(SK_ColorBLACK);
                    canvas.drawPath(path, paint);
            }
    
            if (0) {
                    //测试winding填充效果
                    //两个矩形,顺逆时针
                    SkPath path, path1, path2, path3;
                    SkPoint pt[8];
                    pt[0] = SkPoint::Make(200, 500);
                    pt[1] = SkPoint::Make(400, 300);
                    pt[2] = SkPoint::Make(600, 500);
                    pt[3] = SkPoint::Make(400, 700);
                    pt[4] = SkPoint::Make(400, 500);
                    pt[5] = SkPoint::Make(600, 300);
                    pt[6] = SkPoint::Make(800, 500);
                    pt[7] = SkPoint::Make(600, 700);
    
    
                    //顺时针path
                    path1.moveTo(pt[0]).lineTo(pt[1]).lineTo(pt[2]).lineTo(pt[3]).close();
    
                    //逆时针path
                    path2.moveTo(pt[4]).lineTo(pt[7]).lineTo(pt[6]).lineTo(pt[5]).close();
    
                    path.addPath(path1).addPath(path2);
    
                    path.setFillType(SkPathFillType::kWinding);
    
                    paint.setAntiAlias(true);//抗锯齿
                    paint.setStyle(SkPaint::kFill_Style);
                    //paint.setStyle(SkPaint::kStroke_Style);
                    paint.setStrokeWidth(1);
                    paint.setColor(SK_ColorBLACK);
                    canvas.drawPath(path, paint);
            }
    
            if (0) {
                    //测试不闭合path绘制问题
                    SkPath path, path1, path2, path3;
                    SkPoint pt[6];
                    pt[0] = SkPoint::Make(300, 200);
                    pt[1] = SkPoint::Make(500, 200);
                    pt[2] = SkPoint::Make(200, 500);
                    pt[3] = SkPoint::Make(600, 500);
                    pt[4] = SkPoint::Make(200, 700);
                    pt[5] = SkPoint::Make(600, 700);
    
    
                    path.moveTo(pt[0]).lineTo(pt[5]);
                    path.moveTo(pt[1]).lineTo(pt[4]); //path1.moveTo(pt[1]).lineTo(pt[4]);
                    path.moveTo(pt[2]).lineTo(pt[3]); //path2.moveTo(pt[1]).lineTo(pt[4]);
    
    
                    //path.addPath(path1).addPath(path2);
    
                    path.setFillType(SkPathFillType::kWinding);
    
                    paint.setAntiAlias(true);//抗锯齿
                    paint.setStyle(SkPaint::kStrokeAndFill_Style);
                    paint.setStrokeWidth(1);
                    paint.setColor(SK_ColorBLACK);
                    canvas.drawPath(path, paint);
            }
    
            if (1) {
                    //测试不闭合path绘制问题2
                    SkPath path, path1, path2, path3;
                    SkPoint pt[6];
                    pt[0] = SkPoint::Make(200, 200);
                    pt[1] = SkPoint::Make(400, 200);
                    pt[2] = SkPoint::Make(600, 200);
                    pt[3] = SkPoint::Make(200, 600);
                    pt[4] = SkPoint::Make(400, 600);
                    pt[5] = SkPoint::Make(600, 600);
    
                    path.moveTo(pt[0]).lineTo(pt[4]).lineTo(pt[2]);
                    path1.moveTo(pt[3]).lineTo(pt[1]).lineTo(pt[5]);
    
                    path.setFillType(SkPathFillType::kWinding);
                    path1.setFillType(SkPathFillType::kWinding);
    
                    paint.setAntiAlias(true);//抗锯齿
                    paint.setStyle(SkPaint::kStrokeAndFill_Style);
                    paint.setStrokeWidth(1);
                    paint.setColor(SK_ColorBLACK);
                    canvas.drawPath(path, paint);
                    canvas.drawPath(path1, paint);
            }
    
            if(0){
            //画贝塞尔曲线
                     SkPath path;
                     SkPoint pt[20];
     
                     pt[0].set(100, 100);
                     pt[1].set(200, 80);
                     pt[2].set(300, 80);
                     pt[3].set(400, 100);
    
                    pt[4].set(300, 200);
                    pt[5].set(200, 300);
                    pt[6].set(100, 300);
                    
    
                     path.moveTo(pt[0]);
                     //二次贝塞尔曲线
                     //path.quadTo(pt1, pt2);
                     //三次贝塞尔曲线
                     path.cubicTo(pt[1], pt[2], pt[3]);
                    path.cubicTo(pt[4], pt[5], pt[6]);
    
                    //path.moveTo(pt[0]);
                    //path.lineTo(pt[3]);
                    //path.close();
                     paint.setAntiAlias(true);//抗锯齿
                     paint.setStyle(SkPaint::kFill_Style);
                     paint.setStrokeWidth(1);
                     paint.setColor(SK_ColorBLACK);
                     canvas.drawPath(path, paint);
                     //贝塞尔点
                     paint.setColor(SK_ColorRED);
                     canvas.drawCircle(pt[0].x(), pt[0].y(), 4, paint);
                     canvas.drawCircle(pt[1].x(), pt[1].y(), 4, paint);
                     canvas.drawCircle(pt[2].x(), pt[2].y(), 4, paint);
                     canvas.drawCircle(pt[3].x(), pt[3].y(), 4, paint);
            }
    
            if(0){
                    //画弧线
                    SkPath path;
                    SkPoint pt1, pt2, pt_ctrl;
                    SkPaint paint;
                    pt1.set(100, 100);
                    pt_ctrl.set(180, 250);
                    pt2.set(300, 300);
                    for (float i = 1; i < 20; i += 1) {
                            SkPath tmp;
                            tmp.moveTo(pt1);
                            tmp.conicTo(pt_ctrl, pt2, i);
                            path.addPath(tmp);
                    }
                    path.close();
                    paint.setAntiAlias(true);//抗锯齿
                    paint.setStyle(SkPaint::kStroke_Style);
                    paint.setStrokeWidth(1);
                    paint.setColor(SK_ColorBLACK);
                    canvas.drawPath(path, paint);
            }
    
            SkFILEWStream stream("./test.jpg");
            SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100);
    
    
            return 0;
    }
    
    

    Linux&MacOS:

    1.安装dev_tools

    skia库编译需要依赖google发布的dev_tools编译环境

    下载地址: git clone 'https://chromium.googlesource.com/chromium/tools/depot_tools.git'

    (目前git已经无法直接clone下来,需要点开https://chromium.googlesource.com/chromium/tools/depot_tools这个链接,手动点击左侧branches里的master进行下载)

    环境变量: export PATH={PWD}/depot_tools:{PATH}

    配置好环境变量后输入gn 和ninja,测试是否效

    2.下载源码并编译

    skia源码下载:git clone https://skia.googlesource.com/skia.git

    (skia目前貌似不能直接git clone 需要点开https://skia.googlesource.com/skia.git这个链接,手动点击左侧branches里的master进行下载)

    安装编译依赖:cd skia && python2 tools/git-sync-deps (注:需要python2.7环境)

    编译安装skia

    使用 gn工具生成输出目录及编译配置参数

    如:bin/gn gen out/Debug (使用默认配置输出到out/Debug目录)

    bin/gn gen out/Release --args='is_debug=false'(禁用Debug模式输出到out/Release目录)

    还可以通过设置编译器版本等,具体参见help指令和官方wiki

    bin/gn args out/Debug --list (可以查看配置所有的参数)

    执行编译 ninja -C out/Debug (过程比较漫长,可以喝杯咖啡或去做下面事情) (此过程会直接调用python命令,通过软链接或者重命名方式确保python命令调用python2)

    输出结果:

    image

    上面会输出编译后所有生成的目标库及sample程序, 尝试运行HelloWorld

    image

    3. 添加扩展模块

    我们根据samle程序里面提供的HelloWorld修改一个我们自己的HelloWorld程序

    1. 打开根目录下BUILD.gn找到test_app("HelloWorld"),拷贝复制HelloWorld程序
    image image
    1. 在example目录下copy HelloWorld.h HelloWorld.cpp到HelloWorld.h HelloWorld.cpp
    2. 重新执行bin/gn gen out/Debug生成编译配置
    3. 执行ninja -C out/Debug HelloWorld 指定编译HelloWorld模块, 生成并运行./out/Debug/HelloWorld
    image image
    1. 可以根据自己的需求封装自己的工程模块或修改skia提供的modules

    2. Flatbuffers类库(https://google.github.io/flatbuffers/

    2.1 安装编译工具cmake

    mac平台可使用brew install cmake安装

    ubuntu环境可以使用sudo apt-get install cmake

    或者去https://cmake.org/下载安装

    2.2 下载源码并编译

    源码下载:https://github.com/google/flatbuffers.git

    编译安装:cmake . 生成makefile,后执行make 编译

    编译后生成flac和libflatbuffers.a

    2.3 简单sample程序

    编写MyGame.fbs文件

    // Example IDL file for our monster's schema.
    
    namespace MyGame.Sample;
    
    enum Color:byte { Red = 0, Green, Blue = 2 }
    
    union Equipment { Weapon } // Optionally add more tables.
    
    struct Vec3 {
    
    x:float;
    
    y:float;
    
    z:float;
    
    }
    
    table Monster {
    
    pos:Vec3; // Struct.
    
    mana:short = 150;
    
    hp:short = 100;
    
    name:string;
    
    friendly:bool = false (deprecated);
    
    inventory:[ubyte]; // Vector of scalars.
    
    color:Color = Blue; // Enum.
    
    weapons:[Weapon]; // Vector of tables.
    
    equipped:Equipment; // Union.
    
    path:[Vec3]; // Vector of structs.
    
    }
    
    table Weapon {
    
    name:string;
    
    damage:short;
    
    }
    
    root_type Monster;
    

    使用2.2生成的flatc生成目标代码 flatc --cpp MyGame.fbs生成MyGame_generated.h

    编写C++代码来使用fb

    #include <iostream>
    
    #include <fstream>
    
    #include <vector>
    
    #include "MyGame_generated.h"
    
    #include "flatbuffers/flatbuffers.h"
    
    using namespace MyGame::Sample;
    
    int main(/*int argc, char* argv[]*/)
    
    {
    
    flatbuffers::FlatBufferBuilder builder;
    
    auto weapon_one_name = builder.CreateString("Sword");
    
    short weapon_one_damage = 3;
    
    auto weapon_two_name = builder.CreateString("Axe");
    
    short weapon_two_damage = 5;
    
    auto sword = CreateWeapon(builder, weapon_one_name, weapon_one_damage);
    
    auto axe = CreateWeapon(builder, weapon_two_name, weapon_two_damage);
    
    std::vector<flatbuffers::Offset<Weapon>> weapons_vector;
    
    weapons_vector.push_back(sword);
    
    weapons_vector.push_back(axe);
    
    auto weapons = builder.CreateVector(weapons_vector);
    
    auto position = Vec3(1.0f, 2.0f, 3.0f);
    
    auto name = builder.CreateString("MyMonster");
    
    unsigned char inv_data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    auto inventory = builder.CreateVector(inv_data, 10);
    
    auto orc = CreateMonster(builder, &position, 150, 80, name, inventory,
    
    Color_Red, weapons, Equipment_Weapon, axe.Union());
    
    builder.Finish(orc); // Serialize the root of the object.
    
    auto monster = GetMonster(builder.GetBufferPointer());
    
    assert(monster->hp() == 80);
    
    assert(monster->mana() == 150); // default
    
    assert(monster->name()->str() == "MyMonster");
    
    auto pos = monster->pos();
    
    assert(pos);
    
    assert(pos->z() == 3.0f);
    
    (void)pos;
    
    auto inv = monster->inventory();
    
    assert(inv);
    
    assert(inv->Get(9) == 9);
    
    (void)inv;
    
    std::string expected_weapon_names[] = {"Sword", "Axe"};
    
    short expected_weapon_damages[] = {3, 5};
    
    auto weps = monster->weapons();
    
    for (unsigned int i = 0; i < weps->size(); i++)
    
    {
    
    assert(weps->Get(i)->name()->str() == expected_weapon_names[i]);
    
    assert(weps->Get(i)->damage() == expected_weapon_damages[i]);
    
    }
    
    (void)expected_weapon_names;
    
    (void)expected_weapon_damages;
    
    assert(monster->equipped_type() == Equipment_Weapon);
    
    auto equipped = static_cast<const Weapon *>(monster->equipped());
    
    assert(equipped->name()->str() == "Axe");
    
    assert(equipped->damage() == 5);
    
    (void)equipped;
    
    printf("The FlatBuffer was successfully created and verified!\n");
    
    return 0;
    
    }
    
    1. TouchVG库库(https://github.com/rhcad/TouchVG

    3.1 下载源码并编译

    git clone https://github.com/rhcad/TouchVG.git

    执行cd core && make

    3.2sample程序

    待补充

    1. Emscripten编译环境(https://emscripten.org/index.html)

    4.1 下载编译

    *# Get the emsdk repo*
    
    git clone https:**//**github**.**com**/**emscripten**-**core**/**emsdk**.**git
    
    cd emsdk
    
    ./emsdk install latest
    
    ./emsdk activate latest
    
    source ./emsdk_env.sh
    

    相关文章

      网友评论

          本文标题:Windows编译skia

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