目次
SkiaとC++でデスクトップアプリを作る(Windows) その1
SkiaとC++でデスクトップアプリを作る(Windows) その2
環境
- Windows 10 64bit 2004
- VisualStudio2019
- CMake version 3.17.20032601-MSVC_2
諸々のプロダクトは2020年8月時点の最新版です(多分)
VisualStudioのプロジェクト(CMake)でSkiaを使う
クロスプラットフォームも見据えてCMakeでプロジェクトを作ります。
VisualStudioを開き、[CMake プロジェクト]を選択して作成しましょう。この先プロジェクト名は[SkiaDesktopSample]として書きます。
GLFWの導入
Skia単体では画面出力ができないため、OpenGLのユーティリティライブラリであるGLFWの助けを借ります。
glfw.orgの右上のボタンからGLFWの最新版をダウンロードします。Zipファイルを解凍したら先程作ったプロジェクトの{ProjectRoot}/SkiaDesktopSample/third/glfw 辺りに入れておきましょう。
これによりCMakeで読み込めるようになります。
CMakeLists.txtの書き換え
CMakeListsを書いてskiaとglfwをリンクしましょう。
# CMakeList.txt : SkiaDesktopSample の CMake プロジェクト。ソースを含めて、次を定義します:
# プロジェクト専用ロジックはこちらです。
#
cmake_minimum_required (VERSION 3.8)
# ソースをこのプロジェクトの実行可能ファイルに追加します。
add_executable (SkiaDesktopSample "SkiaDesktopSample.cpp" "SkiaDesktopSample.h")
# TODO: テストを追加し、必要な場合は、ターゲットをインストールします。
include_directories("C:/src/skia")
include_directories("C:/src/skia/tools/sk_app")
link_directories("C:/src/skia/out/release")
target_link_libraries(SkiaDesktopSample opengl32)
target_link_libraries(SkiaDesktopSample "C:/src/skia/out/release/skia.lib")
add_subdirectory("third/glfw")
include_directories("third/glfw/include")
target_link_libraries(SkiaDesktopSample glfw)
set_property(TARGET SkiaDesktopSample PROPERTY CXX_STANDARD 17)
include_directoriesでskiaの2箇所をincludeパスに指定します。もっと深い階層でincludeすることもできるのですが、内部ファイルのインクルードの指定の影響でこの書き方でないとコンパイルできません。
あまり行儀よくないですが、target_link_librariesにその1で作ったskia.libファイルをリンクします。openglも必要なので一緒にリンクしましょう。
またGLFWはsubdirectoryとして追加します。
Skiaは現時点ではC++20に対応していないため、C++17を指定します。
ファイルをこれで書き換え、保存してエラーが出ないことを確認してください。
コードを書く
プロジェクト作成時に作られているcppファイルを以下の内容で置き換えます。
// SkiaDesktopSample.cpp : アプリケーションのエントリ ポイントを定義します。
//
#include "SkiaDesktopSample.h"
#define SK_GL
#include "GLFW/glfw3.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrContext.h"
#include "include/gpu/gl/GrGLInterface.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkSurface.h"
#include "include/core/SkFont.h"
#include <stdio.h>
#include <stdlib.h>
#include "include/effects/Sk2DPathEffect.h"
using namespace std;
GrContext* sContext = nullptr;
SkSurface* sSurface = nullptr;
void errorCallback(int error, const char* description) {
fputs(description, stderr);
}
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
void initSkia(int w, int h) {
GrContextOptions options;
sContext = GrContext::MakeGL(nullptr, options).release();
GrGLFramebufferInfo framebufferInfo;
framebufferInfo.fFBOID = 0;
framebufferInfo.fFormat = GL_RGBA8;
SkColorType colorType;
colorType = kRGBA_8888_SkColorType;
GrBackendRenderTarget backendRenderTarget(w, h, 0, 0, framebufferInfo);
sSurface = SkSurface::MakeFromBackendRenderTarget(
sContext, backendRenderTarget, kBottomLeft_GrSurfaceOrigin, colorType, nullptr, nullptr
).release();
if (sSurface == nullptr) abort();
}
void cleanupSkia() {
delete sSurface;
delete sContext;
}
const int kWidth = 960;
const int kHeight = 640;
int main(int argc, char* argv[])
{
cout << "Hello CMake." << endl;
GLFWwindow* window;
glfwSetErrorCallback(errorCallback);
if (!glfwInit()) {
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_STENCIL_BITS, 0);
glfwWindowHint(GLFW_DEPTH_BITS, 0);
window = glfwCreateWindow(kWidth, kHeight, "Simple Example", NULL, NULL);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
initSkia(kWidth, kHeight);
glfwSwapInterval(1);
glfwSetKeyCallback(window, keyCallback);
SkCanvas* canvas = sSurface->getCanvas();
const char message[] = "Hello, Skia!";
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
SkPaint paint;
canvas->clear(SK_ColorWHITE);
paint.setColor(SK_ColorBLUE);
canvas->drawRect({ 100,200,300,500 }, paint);
paint.setColor(SK_ColorRED);
SkFont font;
font.setSubpixel(true);
font.setSize(72);
canvas->drawSimpleText(message, strlen(message), SkTextEncoding::kUTF8, kWidth / 2, kHeight / 2, font, paint);
sContext->flush();
glfwSwapBuffers(window);
}
cleanupSkia();
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
return 0;
}
CMakeの設定を変更
少し設定を弄ります。[プロジェクト]>[SkiaDesktopSampleのCMakeの設定]>[CMake変数とキャッシュ]で、[高度な変数を表示]にチェックを入れます。
すると複数の変数が表示されるのでCMAKE_CXX_FLAGS_DEBUGを探し出し、最初の/MDd
を/MTd
に変更し、保存します。
またUSE_MSVC_RUNTIME_LIBRARY_DLLのチェックを外します。
ビルドして実行
[デバッグ]>[デバッグの開始]を選択すると、ウィンドウが表示されます!!!!!!!