Add an example showing how to use the Pathfinder C API with GLFW

Closes #258.
This commit is contained in:
Patrick Walton 2020-05-08 15:09:21 -07:00
parent fd57193442
commit bbf4c88d0d
4 changed files with 151 additions and 5 deletions

1
.gitignore vendored
View File

@ -6,6 +6,7 @@ target
/site/dist
node_modules
/examples/c_canvas_minimal/build
/examples/c_canvas_glfw_minimal/build
/shaders/build
/c/build
/examples/macos_app/Pathfinder\ Example.xcodeproj/project.xcworkspace/xcuserdata/*

View File

@ -5,17 +5,15 @@ header = """\
#ifndef PF_PATHFINDER_H
#define PF_PATHFINDER_H
#ifdef __APPLE__
#if defined(__APPLE__) && defined(__OBJC__)
#include <QuartzCore/QuartzCore.h>
#else
typedef struct CAMetalLayerPrivate CAMetalLayer;
#endif
#ifdef __cplusplus
extern \"C\" {
#endif
#ifndef __APPLE__
typedef struct CAMetalLayerPrivate CAMetalLayer;
#endif
"""
trailer = """\
#ifdef __cplusplus

View File

@ -0,0 +1,47 @@
OBJ_DIR?=build
TARGET_DIR?=build
SRC_DIR?=.
RUST_TARGET_DIR?=../../target
RUST_SRC_DIR?=../../c
RUSTFLAGS?=
CFLAGS?=-Wall -g -I../../c/build/include
LIBS?=-lpathfinder_c -lglfw
MKDIR?=mkdir -p
RM?=rm
CARGO?=cargo
UNAME=$(shell uname -s)
ifeq ($(UNAME),Darwin)
# FIXME(pcwalton): Don't link against HarfBuzz!!
LIBS+=-framework OpenGL -framework CoreFoundation -framework CoreGraphics -framework CoreText
LIBS+=-framework Metal -lharfbuzz
else
LIBS+=-lGL
endif
ifeq ($(DEBUG),)
CFLAGS+=-O2
LDFLAGS?=-L$(RUST_TARGET_DIR)/release
CARGOFLAGS?=--release
else
CFLAGS+=-O0
LDFLAGS?=-L$(RUST_TARGET_DIR)/debug
CARGOFLAGS?=
endif
all: $(TARGET_DIR)/c_canvas_glfw_minimal
.PHONY: clean rustlib
$(TARGET_DIR)/c_canvas_glfw_minimal: $(OBJ_DIR)/c_canvas_glfw_minimal.o rustlib
$(MKDIR) $(TARGET_DIR) && $(CC) $(LDFLAGS) $(LIBS) -o $@ $<
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(MKDIR) $(OBJ_DIR) && $(CC) -c $(CFLAGS) -o $@ $<
rustlib:
cd $(RUST_SRC_DIR) && RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build $(CARGOFLAGS)
clean:
$(RM) -rf $(TARGET_DIR) && $(RM) -rf $(OBJ_DIR)

View File

@ -0,0 +1,100 @@
// pathfinder/examples/c_canvas_glfw_minimal/c_canvas_glfw_minimal.c
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#include <GLFW/glfw3.h>
#include <pathfinder/pathfinder.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
static void HandleGLFWError(int errorCode, const char *description);
static const void *LoadGLFunction(const char *name, void *userdata);
static void HandleKeypress(GLFWwindow *window, int key, int scancode, int action, int mods);
int main(int argc, const char **argv) {
// Set up GLFW.
GLFWwindow *window;
if (!glfwInit())
return 1;
glfwSetErrorCallback(HandleGLFWError);
// Make sure we have at least a GL 3.0 context. Pathfinder requires this.
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
// Open a window.
window = glfwCreateWindow(640, 480, "Minimal canvas example (GLFW/C API)", NULL, NULL);
// Make the OpenGL context current.
glfwMakeContextCurrent(window);
// Create a Pathfinder renderer.
PFGLLoadWith(LoadGLFunction, NULL);
PFGLDestFramebufferRef dest_framebuffer =
PFGLDestFramebufferCreateFullWindow(&(PFVector2I){640, 480});
PFGLRendererRef renderer = PFGLRendererCreate(PFGLDeviceCreate(PF_GL_VERSION_GL3, 0),
PFFilesystemResourceLoaderLocate(),
dest_framebuffer,
&(PFRendererOptions){
(PFColorF){1.0, 1.0, 1.0, 1.0}, PF_RENDERER_OPTIONS_FLAGS_HAS_BACKGROUND_COLOR
});
// Make a canvas. We're going to draw a house.
PFCanvasRef canvas = PFCanvasCreate(PFCanvasFontContextCreateWithSystemSource(),
&(PFVector2F){640.0f, 480.0f});
// Set line width.
PFCanvasSetLineWidth(canvas, 10.0f);
// Draw walls.
PFCanvasStrokeRect(canvas, &(PFRectF){{75.0f, 140.0f}, {225.0f, 250.0f}});
// Draw door.
PFCanvasFillRect(canvas, &(PFRectF){{130.0f, 190.0f}, {170.0f, 250.0f}});
// Draw roof.
PFPathRef path = PFPathCreate();
PFPathMoveTo(path, &(PFVector2F){50.0, 140.0});
PFPathLineTo(path, &(PFVector2F){150.0, 60.0});
PFPathLineTo(path, &(PFVector2F){250.0, 140.0});
PFPathClosePath(path);
PFCanvasStrokePath(canvas, path);
// Render the canvas to screen.
PFSceneRef scene = PFCanvasCreateScene(canvas);
PFSceneProxyRef scene_proxy = PFSceneProxyCreateFromSceneAndRayonExecutor(scene);
PFSceneProxyBuildAndRenderGL(scene_proxy, renderer, PFBuildOptionsCreate());
glfwSwapBuffers(window);
// Wait for a keypress.
glfwSetKeyCallback(window, HandleKeypress);
while (!glfwWindowShouldClose(window))
glfwPollEvents();
// Finish up.
glfwTerminate();
return 0;
}
static void HandleGLFWError(int errorCode, const char *description) {
fprintf(stderr, "GLFW error: %s [%d]\n", description, errorCode);
exit(1);
}
static void HandleKeypress(GLFWwindow *window, int key, int scancode, int action, int mods) {
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static const void *LoadGLFunction(const char *name, void *userdata) {
return glfwGetProcAddress(name);
}