add nanovg lcd

This commit is contained in:
xianjimli 2018-04-13 10:25:58 +08:00
parent 7ee3205aa7
commit 23eb92a0d9
91 changed files with 30872 additions and 642 deletions

28
3rd/nanovg/.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
## Compiled source #
*.com
*.class
*.dll
*.exe
*.o
*.so
test
## Logs and databases #
*.log
*.sql
*.sqlite
## OS generated files #
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
## Build dir
build/*
## xcode specific
*xcuserdata*

18
3rd/nanovg/LICENSE.txt Normal file
View File

@ -0,0 +1,18 @@
Copyright (c) 2013 Mikko Mononen memon@inside.org
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

119
3rd/nanovg/README.md Normal file
View File

@ -0,0 +1,119 @@
NanoVG
==========
NanoVG is small antialiased vector graphics rendering library for OpenGL. It has lean API modeled after HTML5 canvas API. It is aimed to be a practical and fun toolset for building scalable user interfaces and visualizations.
## Screenshot
![screenshot of some text rendered witht the sample program](/example/screenshot-01.png?raw=true)
Usage
=====
The NanoVG API is modeled loosely on HTML5 canvas API. If you know canvas, you're up to speed with NanoVG in no time.
## Creating drawing context
The drawing context is created using platform specific constructor function. If you're using the OpenGL 2.0 back-end the context is created as follows:
```C
#define NANOVG_GL2_IMPLEMENTATION // Use GL2 implementation.
#include "nanovg_gl.h"
...
struct NVGcontext* vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
```
The first parameter defines flags for creating the renderer.
- `NVG_ANTIALIAS` means that the renderer adjusts the geometry to include anti-aliasing. If you're using MSAA, you can omit this flags.
- `NVG_STENCIL_STROKES` means that the render uses better quality rendering for (overlapping) strokes. The quality is mostly visible on wider strokes. If you want speed, you can omit this flag.
Currently there is an OpenGL back-end for NanoVG: [nanovg_gl.h](/src/nanovg_gl.h) for OpenGL 2.0, OpenGL ES 2.0, OpenGL 3.2 core profile and OpenGL ES 3. The implementation can be chosen using a define as in above example. See the header file and examples for further info.
*NOTE:* The render target you're rendering to must have stencil buffer.
## Drawing shapes with NanoVG
Drawing a simple shape using NanoVG consists of four steps: 1) begin a new shape, 2) define the path to draw, 3) set fill or stroke, 4) and finally fill or stroke the path.
```C
nvgBeginPath(vg);
nvgRect(vg, 100,100, 120,30);
nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgFill(vg);
```
Calling `nvgBeginPath()` will clear any existing paths and start drawing from blank slate. There are number of number of functions to define the path to draw, such as rectangle, rounded rectangle and ellipse, or you can use the common moveTo, lineTo, bezierTo and arcTo API to compose the paths step by step.
## Understanding Composite Paths
Because of the way the rendering backend is build in NanoVG, drawing a composite path, that is path consisting from multiple paths defining holes and fills, is a bit more involved. NanoVG uses even-odd filling rule and by default the paths are wound in counter clockwise order. Keep that in mind when drawing using the low level draw API. In order to wind one of the predefined shapes as a hole, you should call `nvgPathWinding(vg, NVG_HOLE)`, or `nvgPathWinding(vg, NVG_CW)` _after_ defining the path.
``` C
nvgBeginPath(vg);
nvgRect(vg, 100,100, 120,30);
nvgCircle(vg, 120,120, 5);
nvgPathWinding(vg, NVG_HOLE); // Mark circle as a hole.
nvgFillColor(vg, nvgRGBA(255,192,0,255));
nvgFill(vg);
```
## Rendering is wrong, what to do?
- make sure you have created NanoVG context using one of the `nvgCreatexxx()` calls
- make sure you have initialised OpenGL with *stencil buffer*
- make sure you have cleared stencil buffer
- make sure all rendering calls happen between `nvgBeginFrame()` and `nvgEndFrame()`
- to enable more checks for OpenGL errors, add `NVG_DEBUG` flag to `nvgCreatexxx()`
- if the problem still persists, please report an issue!
## OpenGL state touched by the backend
The OpenGL back-end touches following states:
When textures are uploaded or updated, the following pixel store is set to defaults: `GL_UNPACK_ALIGNMENT`, `GL_UNPACK_ROW_LENGTH`, `GL_UNPACK_SKIP_PIXELS`, `GL_UNPACK_SKIP_ROWS`. Texture binding is also affected. Texture updates can happen when the user loads images, or when new font glyphs are added. Glyphs are added as needed between calls to `nvgBeginFrame()` and `nvgEndFrame()`.
The data for the whole frame is buffered and flushed in `nvgEndFrame()`. The following code illustrates the OpenGL state touched by the rendering code:
```C
glUseProgram(prog);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilMask(0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, 0xffffffff);
glActiveTexture(GL_TEXTURE0);
glBindBuffer(GL_UNIFORM_BUFFER, buf);
glBindVertexArray(arr);
glBindBuffer(GL_ARRAY_BUFFER, buf);
glBindTexture(GL_TEXTURE_2D, tex);
glUniformBlockBinding(... , GLNVG_FRAG_BINDING);
```
## API Reference
See the header file [nanovg.h](/src/nanovg.h) for API reference.
## Ports
- [DX11 port](https://github.com/cmaughan/nanovg) by [Chris Maughan](https://github.com/cmaughan)
- [Metal port](https://github.com/ollix/MetalNanoVG) by [Olli Wang](https://github.com/olliwang)
- [bgfx port](https://github.com/bkaradzic/bgfx/tree/master/examples/20-nanovg) by [Branimir Karadžić](https://github.com/bkaradzic)
## Projects using NanoVG
- [Processing API simulation by vinjn](https://github.com/vinjn/island/blob/master/examples/01-processing/sketch2d.h)
## License
The library is licensed under [zlib license](LICENSE.txt)
## Discussions
[NanoVG mailing list](https://groups.google.com/forum/#!forum/nanovg)
## Links
Uses [stb_truetype](http://nothings.org) (or, optionally, [freetype](http://freetype.org)) for font rendering.
Uses [stb_image](http://nothings.org) for image loading.

6
3rd/nanovg/SConscript Normal file
View File

@ -0,0 +1,6 @@
import os
env=DefaultEnvironment().Clone()
LIB_DIR=os.environ['LIB_DIR'];
env.Library(os.path.join(LIB_DIR, 'nanovg'), Glob('src/*.c'))

View File

@ -0,0 +1,116 @@
---
Language: Cpp
# BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 100
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
RawStringFormats:
- Delimiter: pb
Language: TextProto
BasedOnStyle: google
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 2
UseTab: Never
...

View File

@ -0,0 +1,92 @@
This Font Software is licensed under the SIL Open Font License,
Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font
creation efforts of academic and linguistic communities, and to
provide a free and open framework in which fonts may be shared and
improved in partnership with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply to
any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software
components as distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to,
deleting, or substituting -- in part or in whole -- any of the
components of the Original Version, by changing formats or by porting
the Font Software to a new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed,
modify, redistribute, and sell modified and unmodified copies of the
Font Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components, in
Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the
corresponding Copyright Holder. This restriction only applies to the
primary font name as presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created using
the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1226
3rd/nanovg/example/demo.c Normal file

File diff suppressed because it is too large Load Diff

26
3rd/nanovg/example/demo.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef DEMO_H
#define DEMO_H
#include "nanovg.h"
#ifdef __cplusplus
extern "C" {
#endif
struct DemoData {
int fontNormal, fontBold, fontIcons, fontEmoji;
int images[12];
};
typedef struct DemoData DemoData;
int loadDemoData(NVGcontext* vg, DemoData* data);
void freeDemoData(NVGcontext* vg, DemoData* data);
void renderDemo(NVGcontext* vg, float mx, float my, float width, float height, float t, int blowup, DemoData* data);
void saveScreenShot(int w, int h, int premult, const char* name);
#ifdef __cplusplus
}
#endif
#endif // DEMO_H

Binary file not shown.

View File

@ -0,0 +1,272 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#ifdef NANOVG_GLEW
# include <GL/glew.h>
#endif
#ifdef __APPLE__
# define GLFW_INCLUDE_GLCOREARB
#endif
#include <GLFW/glfw3.h>
#include "nanovg.h"
#define NANOVG_GL3_IMPLEMENTATION
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"
#include "perf.h"
void renderPattern(NVGcontext* vg, NVGLUframebuffer* fb, float t, float pxRatio)
{
int winWidth, winHeight;
int fboWidth, fboHeight;
int pw, ph, x, y;
float s = 20.0f;
float sr = (cosf(t)+1)*0.5f;
float r = s * 0.6f * (0.2f + 0.8f * sr);
if (fb == NULL) return;
nvgImageSize(vg, fb->image, &fboWidth, &fboHeight);
winWidth = (int)(fboWidth / pxRatio);
winHeight = (int)(fboHeight / pxRatio);
// Draw some stuff to an FBO as a test
nvgluBindFramebuffer(fb);
glViewport(0, 0, fboWidth, fboHeight);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
pw = (int)ceilf(winWidth / s);
ph = (int)ceilf(winHeight / s);
nvgBeginPath(vg);
for (y = 0; y < ph; y++) {
for (x = 0; x < pw; x++) {
float cx = (x+0.5f) * s;
float cy = (y+0.5f) * s;
nvgCircle(vg, cx,cy, r);
}
}
nvgFillColor(vg, nvgRGBA(220,160,0,200));
nvgFill(vg);
nvgEndFrame(vg);
nvgluBindFramebuffer(NULL);
}
int loadFonts(NVGcontext* vg)
{
int font;
font = nvgCreateFont(vg, "sans", "../example/Roboto-Regular.ttf");
if (font == -1) {
printf("Could not add font regular.\n");
return -1;
}
font = nvgCreateFont(vg, "sans-bold", "../example/Roboto-Bold.ttf");
if (font == -1) {
printf("Could not add font bold.\n");
return -1;
}
return 0;
}
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main()
{
GLFWwindow* window;
NVGcontext* vg = NULL;
GPUtimer gpuTimer;
PerfGraph fps, cpuGraph, gpuGraph;
double prevt = 0, cpuTime = 0;
NVGLUframebuffer* fb = NULL;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(&cpuGraph, GRAPH_RENDER_MS, "CPU Time");
initGraph(&gpuGraph, GRAPH_RENDER_MS, "GPU Time");
glfwSetErrorCallback(errorcb);
#ifndef _WIN32 // don't require this on win32, and works with more cards
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);
#endif
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
#ifdef DEMO_MSAA
glfwWindowHint(GLFW_SAMPLES, 4);
#endif
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
#ifdef NANOVG_GLEW
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK) {
printf("Could not init glew.\n");
return -1;
}
// GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
glGetError();
#endif
#ifdef DEMO_MSAA
vg = nvgCreateGL3(NVG_STENCIL_STROKES | NVG_DEBUG);
#else
vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
#endif
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
// Create hi-dpi FBO for hi-dpi screens.
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// The image pattern is tiled, set repeat on x and y.
fb = nvgluCreateFramebuffer(vg, (int)(100*pxRatio), (int)(100*pxRatio), NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
if (fb == NULL) {
printf("Could not create FBO.\n");
return -1;
}
if (loadFonts(vg) == -1) {
printf("Could not load fonts\n");
return -1;
}
glfwSwapInterval(0);
initGPUTimer(&gpuTimer);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
float gpuTimes[3];
int i, n;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
startGPUTimer(&gpuTimer);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
renderPattern(vg, fb, t, pxRatio);
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
// Use the FBO as image pattern.
if (fb != NULL) {
NVGpaint img = nvgImagePattern(vg, 0, 0, 100, 100, 0, fb->image, 1.0f);
nvgSave(vg);
for (i = 0; i < 20; i++) {
nvgBeginPath(vg);
nvgRect(vg, 10 + i*30,10, 10, winHeight-20);
nvgFillColor(vg, nvgHSLA(i/19.0f, 0.5f, 0.5f, 255));
nvgFill(vg);
}
nvgBeginPath(vg);
nvgRoundedRect(vg, 140 + sinf(t*1.3f)*100, 140 + cosf(t*1.71244f)*100, 250, 250, 20);
nvgFillPaint(vg, img);
nvgFill(vg);
nvgStrokeColor(vg, nvgRGBA(220,160,0,255));
nvgStrokeWidth(vg, 3.0f);
nvgStroke(vg);
nvgRestore(vg);
}
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5+200+5,5, &cpuGraph);
if (gpuTimer.supported)
renderGraph(vg, 5+200+5+200+5,5, &gpuGraph);
nvgEndFrame(vg);
// Measure the CPU time taken excluding swap buffers (as the swap may wait for GPU)
cpuTime = glfwGetTime() - t;
updateGraph(&fps, dt);
updateGraph(&cpuGraph, cpuTime);
// We may get multiple results.
n = stopGPUTimer(&gpuTimer, gpuTimes, 3);
for (i = 0; i < n; i++)
updateGraph(&gpuGraph, gpuTimes[i]);
glfwSwapBuffers(window);
glfwPollEvents();
}
nvgluDeleteFramebuffer(fb);
nvgDeleteGL3(vg);
printf("Average Frame Time: %.2f ms\n", getGraphAverage(&fps) * 1000.0f);
printf(" CPU Time: %.2f ms\n", getGraphAverage(&cpuGraph) * 1000.0f);
printf(" GPU Time: %.2f ms\n", getGraphAverage(&gpuGraph) * 1000.0f);
glfwTerminate();
return 0;
}

View File

@ -0,0 +1,163 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#ifdef NANOVG_GLEW
# include <GL/glew.h>
#endif
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include "nanovg.h"
#define NANOVG_GL2_IMPLEMENTATION
#include "nanovg_gl.h"
#include "demo.h"
#include "perf.h"
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
int blowup = 0;
int screenshot = 0;
int premult = 0;
static void key(GLFWwindow* glfw_window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(glfw_window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
blowup = !blowup;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
screenshot = 1;
if (key == GLFW_KEY_P && action == GLFW_PRESS)
premult = !premult;
}
int main()
{
GLFWwindow* glfw_window;
DemoData data;
NVGcontext* vg = NULL;
PerfGraph fps;
double prevt = 0;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
#ifdef DEMO_MSAA
glfwWindowHint(GLFW_SAMPLES, 4);
#endif
glfw_window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// glfw_window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!glfw_window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(glfw_window, key);
glfwMakeContextCurrent(glfw_window);
#ifdef NANOVG_GLEW
if(glewInit() != GLEW_OK) {
printf("Could not init glew.\n");
return -1;
}
#endif
#ifdef DEMO_MSAA
vg = nvgCreateGL2(NVG_STENCIL_STROKES | NVG_DEBUG);
#else
vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
#endif
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
if (loadDemoData(vg, &data) == -1)
return -1;
glfwSwapInterval(0);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(glfw_window))
{
double mx, my, t, dt;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
glfwGetCursorPos(glfw_window, &mx, &my);
glfwGetWindowSize(glfw_window, &winWidth, &winHeight);
glfwGetFramebufferSize(glfw_window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
if (premult)
glClearColor(0,0,0,0);
else
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
printf("t=%lf\n",t);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
nvgEndFrame(vg);
if (screenshot) {
screenshot = 0;
saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
glfwSwapBuffers(glfw_window);
glfwPollEvents();
}
freeDemoData(vg, &data);
nvgDeleteGL2(vg);
glfwTerminate();
return 0;
}

View File

@ -0,0 +1,198 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#ifdef NANOVG_GLEW
# include <GL/glew.h>
#endif
#ifdef __APPLE__
# define GLFW_INCLUDE_GLCOREARB
#endif
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include "nanovg.h"
#define NANOVG_GL3_IMPLEMENTATION
#include "nanovg_gl.h"
#include "demo.h"
#include "perf.h"
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
int blowup = 0;
int screenshot = 0;
int premult = 0;
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
blowup = !blowup;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
screenshot = 1;
if (key == GLFW_KEY_P && action == GLFW_PRESS)
premult = !premult;
}
int main()
{
GLFWwindow* window;
DemoData data;
NVGcontext* vg = NULL;
GPUtimer gpuTimer;
PerfGraph fps, cpuGraph, gpuGraph;
double prevt = 0, cpuTime = 0;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
initGraph(&cpuGraph, GRAPH_RENDER_MS, "CPU Time");
initGraph(&gpuGraph, GRAPH_RENDER_MS, "GPU Time");
glfwSetErrorCallback(errorcb);
#ifndef _WIN32 // don't require this on win32, and works with more cards
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);
#endif
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
#ifdef DEMO_MSAA
glfwWindowHint(GLFW_SAMPLES, 4);
#endif
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
#ifdef NANOVG_GLEW
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK) {
printf("Could not init glew.\n");
return -1;
}
// GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
glGetError();
#endif
#ifdef DEMO_MSAA
vg = nvgCreateGL3(NVG_STENCIL_STROKES | NVG_DEBUG);
#else
vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
#endif
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
if (loadDemoData(vg, &data) == -1)
return -1;
glfwSwapInterval(0);
initGPUTimer(&gpuTimer);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
float gpuTimes[3];
int i, n;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
startGPUTimer(&gpuTimer);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
if (premult)
glClearColor(0,0,0,0);
else
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
renderGraph(vg, 5+200+5,5, &cpuGraph);
if (gpuTimer.supported)
renderGraph(vg, 5+200+5+200+5,5, &gpuGraph);
nvgEndFrame(vg);
// Measure the CPU time taken excluding swap buffers (as the swap may wait for GPU)
cpuTime = glfwGetTime() - t;
updateGraph(&fps, dt);
updateGraph(&cpuGraph, cpuTime);
// We may get multiple results.
n = stopGPUTimer(&gpuTimer, gpuTimes, 3);
for (i = 0; i < n; i++)
updateGraph(&gpuGraph, gpuTimes[i]);
if (screenshot) {
screenshot = 0;
saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
glfwSwapBuffers(window);
glfwPollEvents();
}
freeDemoData(vg, &data);
nvgDeleteGL3(vg);
printf("Average Frame Time: %.2f ms\n", getGraphAverage(&fps) * 1000.0f);
printf(" CPU Time: %.2f ms\n", getGraphAverage(&cpuGraph) * 1000.0f);
printf(" GPU Time: %.2f ms\n", getGraphAverage(&gpuGraph) * 1000.0f);
glfwTerminate();
return 0;
}

View File

@ -0,0 +1,155 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#define GLFW_INCLUDE_ES2
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include "nanovg.h"
#define NANOVG_GLES2_IMPLEMENTATION
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"
#include "demo.h"
#include "perf.h"
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
int blowup = 0;
int screenshot = 0;
int premult = 0;
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
blowup = !blowup;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
screenshot = 1;
if (key == GLFW_KEY_P && action == GLFW_PRESS)
premult = !premult;
}
int main()
{
GLFWwindow* window;
DemoData data;
NVGcontext* vg = NULL;
PerfGraph fps;
double prevt = 0;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
vg = nvgCreateGLES2(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
if (loadDemoData(vg, &data) == -1)
return -1;
glfwSwapInterval(0);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
if (premult)
glClearColor(0,0,0,0);
else
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
nvgEndFrame(vg);
if (screenshot) {
screenshot = 0;
saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
glEnable(GL_DEPTH_TEST);
glfwSwapBuffers(window);
glfwPollEvents();
}
freeDemoData(vg, &data);
nvgDeleteGLES2(vg);
glfwTerminate();
return 0;
}

View File

@ -0,0 +1,155 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#define GLFW_INCLUDE_ES3
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#include "nanovg.h"
#define NANOVG_GLES3_IMPLEMENTATION
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"
#include "demo.h"
#include "perf.h"
void errorcb(int error, const char* desc)
{
printf("GLFW error %d: %s\n", error, desc);
}
int blowup = 0;
int screenshot = 0;
int premult = 0;
static void key(GLFWwindow* window, int key, int scancode, int action, int mods)
{
NVG_NOTUSED(scancode);
NVG_NOTUSED(mods);
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS)
blowup = !blowup;
if (key == GLFW_KEY_S && action == GLFW_PRESS)
screenshot = 1;
if (key == GLFW_KEY_P && action == GLFW_PRESS)
premult = !premult;
}
int main()
{
GLFWwindow* window;
DemoData data;
NVGcontext* vg = NULL;
PerfGraph fps;
double prevt = 0;
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
glfwSetErrorCallback(errorcb);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(1000, 600, "NanoVG", NULL, NULL);
// window = glfwCreateWindow(1000, 600, "NanoVG", glfwGetPrimaryMonitor(), NULL);
if (!window) {
glfwTerminate();
return -1;
}
glfwSetKeyCallback(window, key);
glfwMakeContextCurrent(window);
vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
if (vg == NULL) {
printf("Could not init nanovg.\n");
return -1;
}
if (loadDemoData(vg, &data) == -1)
return -1;
glfwSwapInterval(0);
glfwSetTime(0);
prevt = glfwGetTime();
while (!glfwWindowShouldClose(window))
{
double mx, my, t, dt;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
t = glfwGetTime();
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
glfwGetCursorPos(window, &mx, &my);
glfwGetWindowSize(window, &winWidth, &winHeight);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
// Calculate pixel ration for hi-dpi devices.
pxRatio = (float)fbWidth / (float)winWidth;
// Update and render
glViewport(0, 0, fbWidth, fbHeight);
if (premult)
glClearColor(0,0,0,0);
else
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, mx,my, winWidth,winHeight, t, blowup, &data);
renderGraph(vg, 5,5, &fps);
nvgEndFrame(vg);
glEnable(GL_DEPTH_TEST);
if (screenshot) {
screenshot = 0;
saveScreenShot(fbWidth, fbHeight, premult, "dump.png");
}
glfwSwapBuffers(window);
glfwPollEvents();
}
freeDemoData(vg, &data);
nvgDeleteGLES3(vg);
glfwTerminate();
return 0;
}

6
3rd/nanovg/example/format.sh Executable file
View File

@ -0,0 +1,6 @@
find src tools lua demos tests -name \*.c -exec clang-format -i {} \;
find src tools lua demos tests -name \*.h -exec clang-format -i {} \;
find src tools lua demos tests -name \*.cc -exec clang-format -i {} \;
find src tools lua demos tests -name \*.cpp -exec clang-format -i {} \;
find src tools lua demos tests -name \*.inc -exec clang-format -i {} \;

View File

@ -0,0 +1,13 @@
Image credits
http://cuteoverload.com/2013/11/05/mom-taxi-xvi-birthday-party/
http://cuteoverload.com/2013/11/05/benson-hedges-private-eye-in-the-case-of-the-crafty-craftsman/
http://cuteoverload.com/2013/11/05/no-underwater-ballets/
http://cuteoverload.com/2013/11/05/every-nose-has-a-story/
http://cuteoverload.com/2013/11/04/nosevember-nozzle-nose/
http://cuteoverload.com/2013/11/04/this-just-in-super-strength-cute/
http://cuteoverload.com/2013/11/03/have-a-bunderful-sunday/
http://cuteoverload.com/2013/11/02/caturday-sense-a-common-theme-here/
http://cuteoverload.com/2013/11/01/nosevember-1st-24-hours-of-noses-1148pm-pt/
http://cuteoverload.com/2013/04/02/there-might-be-something-cuter-than-this/
http://cuteoverload.com/2013/07/17/snorting-micro-peeg-gets-belleh-rubs-interwebs-explode/
http://cuteoverload.com/2013/08/07/bark-in-the-park-v3-0/

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

186
3rd/nanovg/example/perf.c Normal file
View File

@ -0,0 +1,186 @@
#include "perf.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef NANOVG_GLEW
# include <GL/glew.h>
#endif
#include <GLFW/glfw3.h>
#include "nanovg.h"
#ifdef _MSC_VER
#define snprintf _snprintf
#elif !defined(__MINGW32__)
#include <iconv.h>
#endif
// timer query support
#ifndef GL_ARB_timer_query
#define GL_TIME_ELAPSED 0x88BF
//typedef void (APIENTRY *pfnGLGETQUERYOBJECTUI64V)(GLuint id, GLenum pname, GLuint64* params);
//pfnGLGETQUERYOBJECTUI64V glGetQueryObjectui64v = 0;
#endif
void initGPUTimer(GPUtimer* timer)
{
memset(timer, 0, sizeof(*timer));
/* timer->supported = glfwExtensionSupported("GL_ARB_timer_query");
if (timer->supported) {
#ifndef GL_ARB_timer_query
glGetQueryObjectui64v = (pfnGLGETQUERYOBJECTUI64V)glfwGetProcAddress("glGetQueryObjectui64v");
printf("glGetQueryObjectui64v=%p\n", glGetQueryObjectui64v);
if (!glGetQueryObjectui64v) {
timer->supported = GL_FALSE;
return;
}
#endif
glGenQueries(GPU_QUERY_COUNT, timer->queries);
}*/
}
void startGPUTimer(GPUtimer* timer)
{
if (!timer->supported)
return;
glBeginQuery(GL_TIME_ELAPSED, timer->queries[timer->cur % GPU_QUERY_COUNT] );
timer->cur++;
}
int stopGPUTimer(GPUtimer* timer, float* times, int maxTimes)
{
NVG_NOTUSED(times);
NVG_NOTUSED(maxTimes);
GLint available = 1;
int n = 0;
if (!timer->supported)
return 0;
glEndQuery(GL_TIME_ELAPSED);
while (available && timer->ret <= timer->cur) {
// check for results if there are any
glGetQueryObjectiv(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT_AVAILABLE, &available);
if (available) {
/* GLuint64 timeElapsed = 0;
glGetQueryObjectui64v(timer->queries[timer->ret % GPU_QUERY_COUNT], GL_QUERY_RESULT, &timeElapsed);
timer->ret++;
if (n < maxTimes) {
times[n] = (float)((double)timeElapsed * 1e-9);
n++;
}*/
}
}
return n;
}
void initGraph(PerfGraph* fps, int style, const char* name)
{
memset(fps, 0, sizeof(PerfGraph));
fps->style = style;
strncpy(fps->name, name, sizeof(fps->name));
fps->name[sizeof(fps->name)-1] = '\0';
}
void updateGraph(PerfGraph* fps, float frameTime)
{
fps->head = (fps->head+1) % GRAPH_HISTORY_COUNT;
fps->values[fps->head] = frameTime;
}
float getGraphAverage(PerfGraph* fps)
{
int i;
float avg = 0;
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
avg += fps->values[i];
}
return avg / (float)GRAPH_HISTORY_COUNT;
}
void renderGraph(NVGcontext* vg, float x, float y, PerfGraph* fps)
{
int i;
float avg, w, h;
char str[64];
avg = getGraphAverage(fps);
w = 200;
h = 35;
nvgBeginPath(vg);
nvgRect(vg, x,y, w,h);
nvgFillColor(vg, nvgRGBA(0,0,0,128));
nvgFill(vg);
nvgBeginPath(vg);
nvgMoveTo(vg, x, y+h);
if (fps->style == GRAPH_RENDER_FPS) {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = 1.0f / (0.00001f + fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT]);
float vx, vy;
if (v > 80.0f) v = 80.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
vy = y + h - ((v / 80.0f) * h);
nvgLineTo(vg, vx, vy);
}
} else if (fps->style == GRAPH_RENDER_PERCENT) {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT] * 1.0f;
float vx, vy;
if (v > 100.0f) v = 100.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
vy = y + h - ((v / 100.0f) * h);
nvgLineTo(vg, vx, vy);
}
} else {
for (i = 0; i < GRAPH_HISTORY_COUNT; i++) {
float v = fps->values[(fps->head+i) % GRAPH_HISTORY_COUNT] * 1000.0f;
float vx, vy;
if (v > 20.0f) v = 20.0f;
vx = x + ((float)i/(GRAPH_HISTORY_COUNT-1)) * w;
vy = y + h - ((v / 20.0f) * h);
nvgLineTo(vg, vx, vy);
}
}
nvgLineTo(vg, x+w, y+h);
nvgFillColor(vg, nvgRGBA(255,192,0,128));
nvgFill(vg);
nvgFontFace(vg, "sans");
if (fps->name[0] != '\0') {
nvgFontSize(vg, 14.0f);
nvgTextAlign(vg, NVG_ALIGN_LEFT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,192));
nvgText(vg, x+3,y+1, fps->name, NULL);
}
if (fps->style == GRAPH_RENDER_FPS) {
nvgFontSize(vg, 18.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.2f FPS", 1.0f / avg);
nvgText(vg, x+w-3,y+1, str, NULL);
nvgFontSize(vg, 15.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_BOTTOM);
nvgFillColor(vg, nvgRGBA(240,240,240,160));
sprintf(str, "%.2f ms", avg * 1000.0f);
nvgText(vg, x+w-3,y+h-1, str, NULL);
}
else if (fps->style == GRAPH_RENDER_PERCENT) {
nvgFontSize(vg, 18.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.1f %%", avg * 1.0f);
nvgText(vg, x+w-3,y+1, str, NULL);
} else {
nvgFontSize(vg, 18.0f);
nvgTextAlign(vg,NVG_ALIGN_RIGHT|NVG_ALIGN_TOP);
nvgFillColor(vg, nvgRGBA(240,240,240,255));
sprintf(str, "%.2f ms", avg * 1000.0f);
nvgText(vg, x+w-3,y+1, str, NULL);
}
}

46
3rd/nanovg/example/perf.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef PERF_H
#define PERF_H
#include "nanovg.h"
#ifdef __cplusplus
extern "C" {
#endif
enum GraphrenderStyle {
GRAPH_RENDER_FPS,
GRAPH_RENDER_MS,
GRAPH_RENDER_PERCENT,
};
#define GRAPH_HISTORY_COUNT 100
struct PerfGraph {
int style;
char name[32];
float values[GRAPH_HISTORY_COUNT];
int head;
};
typedef struct PerfGraph PerfGraph;
void initGraph(PerfGraph* fps, int style, const char* name);
void updateGraph(PerfGraph* fps, float frameTime);
void renderGraph(NVGcontext* vg, float x, float y, PerfGraph* fps);
float getGraphAverage(PerfGraph* fps);
#define GPU_QUERY_COUNT 5
struct GPUtimer {
int supported;
int cur, ret;
unsigned int queries[GPU_QUERY_COUNT];
};
typedef struct GPUtimer GPUtimer;
void initGPUTimer(GPUtimer* timer);
void startGPUTimer(GPUtimer* timer);
int stopGPUTimer(GPUtimer* timer, float* times, int maxTimes);
#ifdef __cplusplus
}
#endif
#endif // PERF_H

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

137
3rd/nanovg/example/sdl-ok.c Normal file
View File

@ -0,0 +1,137 @@
#define GL_GLEXT_PROTOTYPES
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_opengl_glext.h>
#include "nanovg.h"
#define GLFW_INCLUDE_GLEXT
#include <GLFW/glfw3.h>
#define NANOVG_GL2_IMPLEMENTATION
#include "nanovg_gl.h"
#include "demo.h"
#include "perf.h"
#define USE_SDL
static int quitting = 0;
static float r = 0.0f;
GLFWwindow* glfw_window;
static SDL_Window* sdl_window = NULL;
static SDL_GLContext gl_context;
int SDLCALL watch(void* userdata, SDL_Event* event) {
if (event->type == SDL_APP_WILLENTERBACKGROUND) {
quitting = 1;
}
return 1;
}
int main(int argc, char* argv[]) {
int t = 0;
PerfGraph fps;
DemoData data;
NVGcontext* vg = NULL;
int winWidth = 1000;
int winHeight = 600;
double prevt =(double)SDL_GetTicks()/1000;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
return 1;
}
if (!glfwInit()) {
printf("Failed to init GLFW.");
return -1;
}
#ifdef USE_SDL
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
//SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
sdl_window = SDL_CreateWindow("title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, winWidth,
winHeight, SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI|SDL_WINDOW_RESIZABLE);
gl_context = SDL_GL_CreateContext(sdl_window);
SDL_GL_MakeCurrent(sdl_window, gl_context);
SDL_GL_SetSwapInterval(0);
SDL_GL_SetAttribute(SDL_GL_STEREO, 1);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfw_window = glfwCreateWindow(winWidth, winHeight, "NanoVG", NULL, NULL);
glfwMakeContextCurrent(glfw_window);
#endif
glEnable(GL_ALPHA_TEST);
glEnable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
SDL_AddEventWatch(watch, NULL);
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
//vg = nvgCreateGL2(NVG_STENCIL_STROKES | NVG_DEBUG);
if (loadDemoData(vg, &data) == -1) return -1;
while (!quitting) {
double mx, my, t, dt = 0;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quitting = 1;
}
}
t =(double)SDL_GetTicks()/1000;
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
printf("t=%lf dt=%lf\n", t, dt);
#ifdef USE_SDL
SDL_GetWindowSize(sdl_window, &winWidth, &winHeight);
SDL_GL_GetDrawableSize(sdl_window, &fbWidth, &fbHeight);
#else
glfwGetWindowSize(glfw_window, &winWidth, &winHeight);
glfwGetFramebufferSize(glfw_window, &fbWidth, &fbHeight);
#endif
pxRatio = (float)fbWidth / (float)winWidth;
glViewport(0, 0, fbWidth, fbHeight);
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, 0, 0, winWidth, winHeight, t, 0, &data);
renderGraph(vg, 5,5, &fps);
nvgEndFrame(vg);
#ifdef USE_SDL
SDL_GL_SwapWindow(sdl_window);
SDL_Delay(2);
#else
glfwSwapBuffers(glfw_window);
#endif
}
SDL_DelEventWatch(watch, NULL);
SDL_GL_DeleteContext(gl_context);
SDL_DestroyWindow(sdl_window);
SDL_Quit();
exit(0);
} // main

109
3rd/nanovg/example/sdl.c Normal file
View File

@ -0,0 +1,109 @@
#define GL_GLEXT_PROTOTYPES
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_opengl_glext.h>
#include "nanovg.h"
#define NANOVG_GL2_IMPLEMENTATION
#include "nanovg_gl.h"
#include "demo.h"
#include "perf.h"
#define USE_SDL
static int quitting = 0;
static SDL_GLContext gl_context;
static SDL_Window* sdl_window = NULL;
int SDLCALL watch(void* userdata, SDL_Event* event) {
if (event->type == SDL_APP_WILLENTERBACKGROUND) {
quitting = 1;
}
return 1;
}
int main(int argc, char* argv[]) {
int t = 0;
PerfGraph fps;
DemoData data;
NVGcontext* vg = NULL;
int winWidth = 1000;
int winHeight = 600;
double prevt = (double)SDL_GetTicks() / 1000;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
return 1;
}
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
sdl_window = SDL_CreateWindow(
"title", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, winWidth, winHeight,
SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE);
gl_context = SDL_GL_CreateContext(sdl_window);
SDL_GL_MakeCurrent(sdl_window, gl_context);
SDL_GL_SetSwapInterval(0);
glEnable(GL_ALPHA_TEST);
glEnable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
SDL_AddEventWatch(watch, NULL);
initGraph(&fps, GRAPH_RENDER_FPS, "Frame Time");
vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
// vg = nvgCreateGL2(NVG_STENCIL_STROKES | NVG_DEBUG);
if (loadDemoData(vg, &data) == -1) return -1;
while (!quitting) {
double mx, my, t, dt = 0;
int winWidth, winHeight;
int fbWidth, fbHeight;
float pxRatio;
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quitting = 1;
}
}
t = (double)SDL_GetTicks() / 1000;
dt = t - prevt;
prevt = t;
updateGraph(&fps, dt);
printf("t=%lf dt=%lf\n", t, dt);
SDL_GetWindowSize(sdl_window, &winWidth, &winHeight);
SDL_GL_GetDrawableSize(sdl_window, &fbWidth, &fbHeight);
pxRatio = (float)fbWidth / (float)winWidth;
glViewport(0, 0, fbWidth, fbHeight);
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, winWidth, winHeight, pxRatio);
renderDemo(vg, 0, 0, winWidth, winHeight, t, 0, &data);
renderGraph(vg, 5, 5, &fps);
nvgEndFrame(vg);
SDL_GL_SwapWindow(sdl_window);
SDL_Delay(16);
}
SDL_DelEventWatch(watch, NULL);
SDL_GL_DeleteContext(gl_context);
SDL_DestroyWindow(sdl_window);
SDL_Quit();
exit(0);
} // main

View File

@ -0,0 +1,511 @@
/* stbiw-0.92 - public domain - http://nothings.org/stb/stb_image_write.h
writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
no warranty implied; use at your own risk
Before including,
#define STB_IMAGE_WRITE_IMPLEMENTATION
in the file that you want to have the implementation.
ABOUT:
This header file is a library for writing images to C stdio. It could be
adapted to write to memory or a general streaming interface; let me know.
The PNG output is not optimal; it is 20-50% larger than the file
written by a decent optimizing implementation. This library is designed
for source code compactness and simplicitly, not optimal image file size
or run-time performance.
USAGE:
There are three functions, one for each image file format:
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
Each function returns 0 on failure and non-0 on success.
The functions create an image file defined by the parameters. The image
is a rectangle of pixels stored from left-to-right, top-to-bottom.
Each pixel contains 'comp' channels of data stored interleaved with 8-bits
per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
The *data pointer points to the first byte of the top-left-most pixel.
For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
a row of pixels to the first byte of the next row of pixels.
PNG creates output files with the same number of components as the input.
The BMP and TGA formats expand Y to RGB in the file format. BMP does not
output alpha.
PNG supports writing rectangles of data even when the bytes storing rows of
data are not consecutive in memory (e.g. sub-rectangles of a larger image),
by supplying the stride between the beginning of adjacent rows. The other
formats do not. (Thus you cannot write a native-format BMP through the BMP
writer, both because it is in BGR order and because it may have padding
at the end of the line.)
*/
#ifndef INCLUDE_STB_IMAGE_WRITE_H
#define INCLUDE_STB_IMAGE_WRITE_H
#ifdef __cplusplus
extern "C" {
#endif
extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
#ifdef __cplusplus
}
#endif
#endif//INCLUDE_STB_IMAGE_WRITE_H
#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef unsigned int stbiw_uint32;
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
static void writefv(FILE *f, const char *fmt, va_list v)
{
while (*fmt) {
switch (*fmt++) {
case ' ': break;
case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
case '2': { int x = va_arg(v,int); unsigned char b[2];
b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
fwrite(b,2,1,f); break; }
case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
fwrite(b,4,1,f); break; }
default:
assert(0);
return;
}
}
}
static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
{
unsigned char arr[3];
arr[0] = a, arr[1] = b, arr[2] = c;
fwrite(arr, 3, 1, f);
}
static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad)
{
unsigned char bg[3] = { 255, 0, 255}, px[3];
stbiw_uint32 zero = 0;
int i,j,k, j_end;
if (y <= 0)
return;
if (vdir < 0)
j_end = -1, j = y-1;
else
j_end = y, j = 0;
for (; j != j_end; j += vdir) {
for (i=0; i < x; ++i) {
unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
if (write_alpha < 0)
fwrite(&d[comp-1], 1, 1, f);
switch (comp) {
case 1:
case 2: write3(f, d[0],d[0],d[0]);
break;
case 4:
if (!write_alpha) {
// composite against pink background
for (k=0; k < 3; ++k)
px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
break;
}
/* FALLTHROUGH */
case 3:
write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
break;
}
if (write_alpha > 0)
fwrite(&d[comp-1], 1, 1, f);
}
fwrite(&zero,scanline_pad,1,f);
}
}
static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...)
{
FILE *f;
if (y < 0 || x < 0) return 0;
f = fopen(filename, "wb");
if (f) {
va_list v;
va_start(v, fmt);
writefv(f, fmt, v);
va_end(v);
write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
fclose(f);
}
return f != NULL;
}
int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
{
int pad = (-x*3) & 3;
return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad,
"11 4 22 4" "4 44 22 444444",
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
}
int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
{
int has_alpha = !(comp & 1);
return outfile(filename, -1,-1, x, y, comp, (void *) data, has_alpha, 0,
"111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha);
}
// stretchy buffer; stbi__sbpush() == vector<>::push_back() -- stbi__sbcount() == vector<>::size()
#define stbi__sbraw(a) ((int *) (a) - 2)
#define stbi__sbm(a) stbi__sbraw(a)[0]
#define stbi__sbn(a) stbi__sbraw(a)[1]
#define stbi__sbneedgrow(a,n) ((a)==0 || stbi__sbn(a)+n >= stbi__sbm(a))
#define stbi__sbmaybegrow(a,n) (stbi__sbneedgrow(a,(n)) ? stbi__sbgrow(a,n) : 0)
#define stbi__sbgrow(a,n) stbi__sbgrowf((void **) &(a), (n), sizeof(*(a)))
#define stbi__sbpush(a, v) (stbi__sbmaybegrow(a,1), (a)[stbi__sbn(a)++] = (v))
#define stbi__sbcount(a) ((a) ? stbi__sbn(a) : 0)
#define stbi__sbfree(a) ((a) ? free(stbi__sbraw(a)),0 : 0)
static void *stbi__sbgrowf(void **arr, int increment, int itemsize)
{
int m = *arr ? 2*stbi__sbm(*arr)+increment : increment+1;
void *p = realloc(*arr ? stbi__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
assert(p);
if (p) {
if (!*arr) ((int *) p)[1] = 0;
*arr = (void *) ((int *) p + 2);
stbi__sbm(*arr) = m;
}
return *arr;
}
static unsigned char *stbi__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
{
while (*bitcount >= 8) {
stbi__sbpush(data, (unsigned char) *bitbuffer);
*bitbuffer >>= 8;
*bitcount -= 8;
}
return data;
}
static int stbi__zlib_bitrev(int code, int codebits)
{
int res=0;
while (codebits--) {
res = (res << 1) | (code & 1);
code >>= 1;
}
return res;
}
static unsigned int stbi__zlib_countm(unsigned char *a, unsigned char *b, int limit)
{
int i;
for (i=0; i < limit && i < 258; ++i)
if (a[i] != b[i]) break;
return i;
}
static unsigned int stbi__zhash(unsigned char *data)
{
stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
}
#define stbi__zlib_flush() (out = stbi__zlib_flushf(out, &bitbuf, &bitcount))
#define stbi__zlib_add(code,codebits) \
(bitbuf |= (code) << bitcount, bitcount += (codebits), stbi__zlib_flush())
#define stbi__zlib_huffa(b,c) stbi__zlib_add(stbi__zlib_bitrev(b,c),c)
// default huffman tables
#define stbi__zlib_huff1(n) stbi__zlib_huffa(0x30 + (n), 8)
#define stbi__zlib_huff2(n) stbi__zlib_huffa(0x190 + (n)-144, 9)
#define stbi__zlib_huff3(n) stbi__zlib_huffa(0 + (n)-256,7)
#define stbi__zlib_huff4(n) stbi__zlib_huffa(0xc0 + (n)-280,8)
#define stbi__zlib_huff(n) ((n) <= 143 ? stbi__zlib_huff1(n) : (n) <= 255 ? stbi__zlib_huff2(n) : (n) <= 279 ? stbi__zlib_huff3(n) : stbi__zlib_huff4(n))
#define stbi__zlib_huffb(n) ((n) <= 143 ? stbi__zlib_huff1(n) : stbi__zlib_huff2(n))
#define stbi__ZHASH 16384
unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
{
static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 };
static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 };
static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 };
unsigned int bitbuf=0;
int i,j, bitcount=0;
unsigned char *out = NULL;
unsigned char **hash_table[stbi__ZHASH]; // 64KB on the stack!
if (quality < 5) quality = 5;
stbi__sbpush(out, 0x78); // DEFLATE 32K window
stbi__sbpush(out, 0x5e); // FLEVEL = 1
stbi__zlib_add(1,1); // BFINAL = 1
stbi__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
for (i=0; i < stbi__ZHASH; ++i)
hash_table[i] = NULL;
i=0;
while (i < data_len-3) {
// hash next 3 bytes of data to be compressed
int h = stbi__zhash(data+i)&(stbi__ZHASH-1), best=3;
unsigned char *bestloc = 0;
unsigned char **hlist = hash_table[h];
int n = stbi__sbcount(hlist);
for (j=0; j < n; ++j) {
if (hlist[j]-data > i-32768) { // if entry lies within window
int d = stbi__zlib_countm(hlist[j], data+i, data_len-i);
if (d >= best) best=d,bestloc=hlist[j];
}
}
// when hash table entry is too long, delete half the entries
if (hash_table[h] && stbi__sbn(hash_table[h]) == 2*quality) {
memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
stbi__sbn(hash_table[h]) = quality;
}
stbi__sbpush(hash_table[h],data+i);
if (bestloc) {
// "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
h = stbi__zhash(data+i+1)&(stbi__ZHASH-1);
hlist = hash_table[h];
n = stbi__sbcount(hlist);
for (j=0; j < n; ++j) {
if (hlist[j]-data > i-32767) {
int e = stbi__zlib_countm(hlist[j], data+i+1, data_len-i-1);
if (e > best) { // if next match is better, bail on current match
bestloc = NULL;
break;
}
}
}
}
if (bestloc) {
int d = data+i - bestloc; // distance back
assert(d <= 32767 && best <= 258);
for (j=0; best > lengthc[j+1]-1; ++j);
stbi__zlib_huff(j+257);
if (lengtheb[j]) stbi__zlib_add(best - lengthc[j], lengtheb[j]);
for (j=0; d > distc[j+1]-1; ++j);
stbi__zlib_add(stbi__zlib_bitrev(j,5),5);
if (disteb[j]) stbi__zlib_add(d - distc[j], disteb[j]);
i += best;
} else {
stbi__zlib_huffb(data[i]);
++i;
}
}
// write out final bytes
for (;i < data_len; ++i)
stbi__zlib_huffb(data[i]);
stbi__zlib_huff(256); // end of block
// pad with 0 bits to byte boundary
while (bitcount)
stbi__zlib_add(0,1);
for (i=0; i < stbi__ZHASH; ++i)
(void) stbi__sbfree(hash_table[i]);
{
// compute adler32 on input
unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
int j=0;
while (j < data_len) {
for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
s1 %= 65521, s2 %= 65521;
j += blocklen;
blocklen = 5552;
}
stbi__sbpush(out, (unsigned char) (s2 >> 8));
stbi__sbpush(out, (unsigned char) s2);
stbi__sbpush(out, (unsigned char) (s1 >> 8));
stbi__sbpush(out, (unsigned char) s1);
}
*out_len = stbi__sbn(out);
// make returned pointer freeable
memmove(stbi__sbraw(out), out, *out_len);
return (unsigned char *) stbi__sbraw(out);
}
unsigned int stbi__crc32(unsigned char *buffer, int len)
{
static unsigned int crc_table[256];
unsigned int crc = ~0u;
int i,j;
if (crc_table[1] == 0)
for(i=0; i < 256; i++)
for (crc_table[i]=i, j=0; j < 8; ++j)
crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
for (i=0; i < len; ++i)
crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
return ~crc;
}
#define stbi__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
#define stbi__wp32(data,v) stbi__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
#define stbi__wptag(data,s) stbi__wpng4(data, s[0],s[1],s[2],s[3])
static void stbi__wpcrc(unsigned char **data, int len)
{
unsigned int crc = stbi__crc32(*data - len - 4, len+4);
stbi__wp32(*data, crc);
}
static unsigned char stbi__paeth(int a, int b, int c)
{
int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
if (pa <= pb && pa <= pc) return (unsigned char) a;
if (pb <= pc) return (unsigned char) b;
return (unsigned char) c;
}
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
{
int ctype[5] = { -1, 0, 4, 2, 6 };
unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
unsigned char *out,*o, *filt, *zlib;
signed char *line_buffer;
int i,j,k,p,zlen;
if (stride_bytes == 0)
stride_bytes = x * n;
filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0;
line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; }
for (j=0; j < y; ++j) {
static int mapping[] = { 0,1,2,3,4 };
static int firstmap[] = { 0,1,0,5,6 };
int *mymap = j ? mapping : firstmap;
int best = 0, bestval = 0x7fffffff;
for (p=0; p < 2; ++p) {
for (k= p?best:0; k < 5; ++k) {
int type = mymap[k],est=0;
unsigned char *z = pixels + stride_bytes*j;
for (i=0; i < n; ++i)
switch (type) {
case 0: line_buffer[i] = z[i]; break;
case 1: line_buffer[i] = z[i]; break;
case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
case 4: line_buffer[i] = (signed char) (z[i] - stbi__paeth(0,z[i-stride_bytes],0)); break;
case 5: line_buffer[i] = z[i]; break;
case 6: line_buffer[i] = z[i]; break;
}
for (i=n; i < x*n; ++i) {
switch (type) {
case 0: line_buffer[i] = z[i]; break;
case 1: line_buffer[i] = z[i] - z[i-n]; break;
case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
case 4: line_buffer[i] = z[i] - stbi__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
case 6: line_buffer[i] = z[i] - stbi__paeth(z[i-n], 0,0); break;
}
}
if (p) break;
for (i=0; i < x*n; ++i)
est += abs((signed char) line_buffer[i]);
if (est < bestval) { bestval = est; best = k; }
}
}
// when we get here, best contains the filter type, and line_buffer contains the data
filt[j*(x*n+1)] = (unsigned char) best;
memcpy(filt+j*(x*n+1)+1, line_buffer, x*n);
}
free(line_buffer);
zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
free(filt);
if (!zlib) return 0;
// each tag requires 12 bytes of overhead
out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12);
if (!out) return 0;
*out_len = 8 + 12+13 + 12+zlen + 12;
o=out;
memcpy(o,sig,8); o+= 8;
stbi__wp32(o, 13); // header length
stbi__wptag(o, "IHDR");
stbi__wp32(o, x);
stbi__wp32(o, y);
*o++ = 8;
*o++ = (unsigned char) ctype[n];
*o++ = 0;
*o++ = 0;
*o++ = 0;
stbi__wpcrc(&o,13);
stbi__wp32(o, zlen);
stbi__wptag(o, "IDAT");
memcpy(o, zlib, zlen); o += zlen; free(zlib);
stbi__wpcrc(&o, zlen);
stbi__wp32(o,0);
stbi__wptag(o, "IEND");
stbi__wpcrc(&o,0);
assert(o == out + *out_len);
return out;
}
int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
{
FILE *f;
int len;
unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
if (!png) return 0;
f = fopen(filename, "wb");
if (!f) { free(png); return 0; }
fwrite(png, 1, len, f);
fclose(f);
free(png);
return 1;
}
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history
0.92 (2010-08-01)
casts to unsigned char to fix warnings
0.91 (2010-07-17)
first public release
0.90 first internal release
*/

View File

@ -0,0 +1,952 @@
//
// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_GL2_H
#define NANOVG_GL2_H
#ifdef __cplusplus
extern "C" {
#endif
#define NVG_ANTIALIAS 1
#ifdef NANOVG_GLES2_IMPLEMENTATION
# ifndef NANOVG_GLES2
# define NANOVG_GLES2
# endif
# ifndef NANOVG_GL2_IMPLEMENTATION
# define NANOVG_GL2_IMPLEMENTATION
# endif
#endif
#ifdef NANOVG_GLES2
struct NVGcontext* nvgCreateGLES2(int atlasw, int atlash, int edgeaa);
void nvgDeleteGLES2(struct NVGcontext* ctx);
#else
struct NVGcontext* nvgCreateGL2(int atlasw, int atlash, int edgeaa);
void nvgDeleteGL2(struct NVGcontext* ctx);
#endif
#ifdef __cplusplus
}
#endif
#endif
#ifdef NANOVG_GL2_IMPLEMENTATION
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "nanovg.h"
enum GLNVGuniformLoc {
GLNVG_LOC_VIEWSIZE,
GLNVG_LOC_SCISSORMAT,
GLNVG_LOC_SCISSOREXT,
GLNVG_LOC_SCISSORSCALE,
GLNVG_LOC_PAINTMAT,
GLNVG_LOC_EXTENT,
GLNVG_LOC_RADIUS,
GLNVG_LOC_FEATHER,
GLNVG_LOC_INNERCOL,
GLNVG_LOC_OUTERCOL,
GLNVG_LOC_STROKEMULT,
GLNVG_LOC_TEX,
GLNVG_LOC_TEXTYPE,
GLNVG_LOC_TYPE,
GLNVG_MAX_LOCS
};
enum GLNVGshaderType {
NSVG_SHADER_FILLGRAD,
NSVG_SHADER_FILLIMG,
NSVG_SHADER_SIMPLE,
NSVG_SHADER_IMG
};
struct GLNVGshader {
GLuint prog;
GLuint frag;
GLuint vert;
GLint loc[GLNVG_MAX_LOCS];
};
struct GLNVGtexture {
int id;
GLuint tex;
int width, height;
int type;
};
struct GLNVGcontext {
struct GLNVGshader shader;
struct GLNVGtexture* textures;
float viewWidth, viewHeight;
int ntextures;
int ctextures;
int textureId;
GLuint vertBuf;
int edgeAntiAlias;
};
static struct GLNVGtexture* glnvg__allocTexture(struct GLNVGcontext* gl)
{
struct GLNVGtexture* tex = NULL;
int i;
for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].id == 0) {
tex = &gl->textures[i];
break;
}
}
if (tex == NULL) {
if (gl->ntextures+1 > gl->ctextures) {
gl->ctextures = (gl->ctextures == 0) ? 2 : gl->ctextures*2;
gl->textures = (struct GLNVGtexture*)realloc(gl->textures, sizeof(struct GLNVGtexture)*gl->ctextures);
if (gl->textures == NULL) return NULL;
}
tex = &gl->textures[gl->ntextures++];
}
memset(tex, 0, sizeof(*tex));
tex->id = ++gl->textureId;
return tex;
}
static struct GLNVGtexture* glnvg__findTexture(struct GLNVGcontext* gl, int id)
{
int i;
for (i = 0; i < gl->ntextures; i++)
if (gl->textures[i].id == id)
return &gl->textures[i];
return NULL;
}
static int glnvg__deleteTexture(struct GLNVGcontext* gl, int id)
{
int i;
for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].id == id) {
if (gl->textures[i].tex != 0)
glDeleteTextures(1, &gl->textures[i].tex);
memset(&gl->textures[i], 0, sizeof(gl->textures[i]));
return 1;
}
}
return 0;
}
static void glnvg__dumpShaderError(GLuint shader, const char* name, const char* type)
{
char str[512+1];
int len = 0;
glGetShaderInfoLog(shader, 512, &len, str);
if (len > 512) len = 512;
str[len] = '\0';
printf("Shader %s/%s error:\n%s\n", name, type, str);
}
static void glnvg__dumpProgramError(GLuint prog, const char* name)
{
char str[512+1];
int len = 0;
glGetProgramInfoLog(prog, 512, &len, str);
if (len > 512) len = 512;
str[len] = '\0';
printf("Program %s error:\n%s\n", name, str);
}
static int glnvg__checkError(const char* str)
{
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
printf("Error %08x after %s\n", err, str);
return 1;
}
return 0;
}
static int glnvg__createShader(struct GLNVGshader* shader, const char* name, const char* vshader, const char* fshader)
{
GLint status;
GLuint prog, vert, frag;
memset(shader, 0, sizeof(*shader));
prog = glCreateProgram();
vert = glCreateShader(GL_VERTEX_SHADER);
frag = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vert, 1, &vshader, 0);
glShaderSource(frag, 1, &fshader, 0);
glCompileShader(vert);
glGetShaderiv(vert, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
glnvg__dumpShaderError(vert, name, "vert");
return 0;
}
glCompileShader(frag);
glGetShaderiv(frag, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
glnvg__dumpShaderError(frag, name, "frag");
return 0;
}
glAttachShader(prog, vert);
glAttachShader(prog, frag);
glBindAttribLocation(prog, 0, "vertex");
glBindAttribLocation(prog, 1, "tcoord");
glBindAttribLocation(prog, 2, "color");
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
glnvg__dumpProgramError(prog, name);
return 0;
}
shader->prog = prog;
shader->vert = vert;
shader->frag = frag;
return 1;
}
static void glnvg__deleteShader(struct GLNVGshader* shader)
{
if (shader->prog != 0)
glDeleteProgram(shader->prog);
if (shader->vert != 0)
glDeleteShader(shader->vert);
if (shader->frag != 0)
glDeleteShader(shader->frag);
}
static void glnvg__getUniforms(struct GLNVGshader* shader)
{
shader->loc[GLNVG_LOC_VIEWSIZE] = glGetUniformLocation(shader->prog, "viewSize");
shader->loc[GLNVG_LOC_SCISSORMAT] = glGetUniformLocation(shader->prog, "scissorMat");
shader->loc[GLNVG_LOC_SCISSOREXT] = glGetUniformLocation(shader->prog, "scissorExt");
shader->loc[GLNVG_LOC_SCISSORSCALE] = glGetUniformLocation(shader->prog, "scissorScale");
shader->loc[GLNVG_LOC_PAINTMAT] = glGetUniformLocation(shader->prog, "paintMat");
shader->loc[GLNVG_LOC_EXTENT] = glGetUniformLocation(shader->prog, "extent");
shader->loc[GLNVG_LOC_RADIUS] = glGetUniformLocation(shader->prog, "radius");
shader->loc[GLNVG_LOC_FEATHER] = glGetUniformLocation(shader->prog, "feather");
shader->loc[GLNVG_LOC_INNERCOL] = glGetUniformLocation(shader->prog, "innerCol");
shader->loc[GLNVG_LOC_OUTERCOL] = glGetUniformLocation(shader->prog, "outerCol");
shader->loc[GLNVG_LOC_STROKEMULT] = glGetUniformLocation(shader->prog, "strokeMult");
shader->loc[GLNVG_LOC_TEX] = glGetUniformLocation(shader->prog, "tex");
shader->loc[GLNVG_LOC_TEXTYPE] = glGetUniformLocation(shader->prog, "texType");
shader->loc[GLNVG_LOC_TYPE] = glGetUniformLocation(shader->prog, "type");
}
static int glnvg__renderCreate(void* uptr)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
static const char* fillVertShader =
#ifdef NANOVG_GLES2
"#version 100\n"
"precision mediump float;\n"
#endif
"uniform vec2 viewSize;\n"
"attribute vec2 vertex;\n"
"attribute vec2 tcoord;\n"
"attribute vec4 color;\n"
"varying vec2 ftcoord;\n"
"varying vec4 fcolor;\n"
"varying vec2 fpos;\n"
"void main(void) {\n"
" ftcoord = tcoord;\n"
" fcolor = color;\n"
" fpos = vertex;\n"
" gl_Position = vec4(2.0*vertex.x/viewSize.x - 1.0, 1.0 - 2.0*vertex.y/viewSize.y, 0, 1);\n"
"}\n";
static const char* fillFragShaderEdgeAA =
#ifdef NANOVG_GLES2
"#version 100\n"
"precision mediump float;\n"
#endif
"uniform mat3 scissorMat;\n"
"uniform vec2 scissorExt;\n"
"uniform vec2 scissorScale;\n"
"uniform mat3 paintMat;\n"
"uniform vec2 extent;\n"
"uniform float radius;\n"
"uniform float feather;\n"
"uniform vec4 innerCol;\n"
"uniform vec4 outerCol;\n"
"uniform float strokeMult;\n"
"uniform sampler2D tex;\n"
"uniform int texType;\n"
"uniform int type;\n"
"varying vec2 ftcoord;\n"
"varying vec4 fcolor;\n"
"varying vec2 fpos;\n"
"\n"
"float sdroundrect(vec2 pt, vec2 ext, float rad) {\n"
" vec2 ext2 = ext - vec2(rad,rad);\n"
" vec2 d = abs(pt) - ext2;\n"
" return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;\n"
"}\n"
"\n"
"// Scissoring\n"
"float scissorMask(vec2 p) {\n"
" vec2 sc = (abs((scissorMat * vec3(p,1.0)).xy) - scissorExt);\n"
" sc = vec2(0.5,0.5) - sc * scissorScale;\n"
" return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n"
"}\n"
"\n"
"// Stroke - from [0..1] to clipped pyramid, where the slope is 1px.\n"
"float strokeMask() {\n"
" return min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * ftcoord.y;\n"
"}\n"
"\n"
"void main(void) {\n"
" if (type == 0) {\n"
" float scissor = scissorMask(fpos);\n"
" float strokeAlpha = strokeMask();\n"
" // Calculate gradient color using box gradient\n"
" vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n"
" float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n"
" vec4 color = mix(innerCol,outerCol,d);\n"
" // Combine alpha\n"
" color.w *= strokeAlpha * scissor;\n"
" gl_FragColor = color;\n"
" } else if (type == 1) {\n"
" float scissor = scissorMask(fpos);\n"
" float strokeAlpha = strokeMask();\n"
" // Calculate color fron texture\n"
" vec2 pt = (paintMat * vec3(fpos,1.0)).xy / extent;\n"
" vec4 color = texture2D(tex, pt);\n"
" color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
" // Combine alpha\n"
" color.w *= strokeAlpha * scissor;\n"
" gl_FragColor = color;\n"
" } else if (type == 2) {\n"
" gl_FragColor = vec4(1,1,1,1);\n"
" } else if (type == 3) {\n"
" vec4 color = texture2D(tex, ftcoord);\n"
" color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
" gl_FragColor = color * fcolor;\n"
" }\n"
"}\n";
static const char* fillFragShader =
#ifdef NANOVG_GLES2
"#version 100\n"
"precision mediump float;\n"
#endif
"uniform mat3 scissorMat;\n"
"uniform vec2 scissorExt;\n"
"uniform vec2 scissorScale;\n"
"uniform mat3 paintMat;\n"
"uniform vec2 extent;\n"
"uniform float radius;\n"
"uniform float feather;\n"
"uniform vec4 innerCol;\n"
"uniform vec4 outerCol;\n"
"uniform float strokeMult;\n"
"uniform sampler2D tex;\n"
"uniform int texType;\n"
"uniform int type;\n"
"varying vec2 ftcoord;\n"
"varying vec4 fcolor;\n"
"varying vec2 fpos;\n"
"\n"
"float sdroundrect(vec2 pt, vec2 ext, float rad) {\n"
" vec2 ext2 = ext - vec2(rad,rad);\n"
" vec2 d = abs(pt) - ext2;\n"
" return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;\n"
"}\n"
"\n"
"// Scissoring\n"
"float scissorMask(vec2 p) {\n"
" vec2 sc = (abs((scissorMat * vec3(p,1.0)).xy) - scissorExt);\n"
" sc = vec2(0.5,0.5) - sc * scissorScale;\n"
" return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n"
"}\n"
"\n"
"void main(void) {\n"
" if (type == 0) {\n"
" float scissor = scissorMask(fpos);\n"
" // Calculate gradient color using box gradient\n"
" vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n"
" float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n"
" vec4 color = mix(innerCol,outerCol,d);\n"
" // Combine alpha\n"
" color.w *= scissor;\n"
" gl_FragColor = color;\n"
" } else if (type == 1) {\n"
" float scissor = scissorMask(fpos);\n"
" // Calculate color fron texture\n"
" vec2 pt = (paintMat * vec3(fpos,1.0)).xy / extent;\n"
" vec4 color = texture2D(tex, pt);\n"
" color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
" // Combine alpha\n"
" color.w *= scissor;\n"
" gl_FragColor = color;\n"
" } else if (type == 2) {\n"
" gl_FragColor = vec4(1,1,1,1);\n"
" } else if (type == 3) {\n"
" vec4 color = texture2D(tex, ftcoord);\n"
" color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
" gl_FragColor = color * fcolor;\n"
" }\n"
"}\n";
glnvg__checkError("init");
if (gl->edgeAntiAlias) {
if (glnvg__createShader(&gl->shader, "shader", fillVertShader, fillFragShaderEdgeAA) == 0)
return 0;
} else {
if (glnvg__createShader(&gl->shader, "shader", fillVertShader, fillFragShader) == 0)
return 0;
}
glnvg__checkError("uniform locations");
glnvg__getUniforms(&gl->shader);
// Create dynamic vertex array
glGenBuffers(1, &gl->vertBuf);
glnvg__checkError("done");
return 1;
}
static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, const unsigned char* data)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
struct GLNVGtexture* tex = glnvg__allocTexture(gl);
if (tex == NULL) return 0;
glGenTextures(1, &tex->tex);
tex->width = w;
tex->height = h;
tex->type = type;
glBindTexture(GL_TEXTURE_2D, tex->tex);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
if (type == NVG_TEXTURE_RGBA)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (glnvg__checkError("create tex"))
return 0;
return tex->id;
}
static int glnvg__renderDeleteTexture(void* uptr, int image)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
return glnvg__deleteTexture(gl, image);
}
static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
if (tex == NULL) return 0;
glBindTexture(GL_TEXTURE_2D, tex->tex);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
#ifdef NANOVG_GLES2
// No support for all of unpack, need to update a whole row at a time.
if (tex->type == NVG_TEXTURE_RGBA)
data += y*tex->width*4;
else
data += y*tex->width;
x = 0;
w = tex->width;
#else
glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
#endif
if (tex->type == NVG_TEXTURE_RGBA)
glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data);
else
glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
return 1;
}
static int glnvg__renderGetTextureSize(void* uptr, int image, int* w, int* h)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
if (tex == NULL) return 0;
*w = tex->width;
*h = tex->height;
return 1;
}
static void glnvg__xformIdentity(float* t)
{
t[0] = 1.0f; t[1] = 0.0f;
t[2] = 0.0f; t[3] = 1.0f;
t[4] = 0.0f; t[5] = 0.0f;
}
static void glnvg__xformInverse(float* inv, float* t)
{
double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
if (det > -1e-6 && det < 1e-6) {
glnvg__xformIdentity(t);
return;
}
invdet = 1.0 / det;
inv[0] = (float)(t[3] * invdet);
inv[2] = (float)(-t[2] * invdet);
inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
inv[1] = (float)(-t[1] * invdet);
inv[3] = (float)(t[0] * invdet);
inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
}
static void glnvg__xformToMat3x3(float* m3, float* t)
{
m3[0] = t[0];
m3[1] = t[1];
m3[2] = 0.0f;
m3[3] = t[2];
m3[4] = t[3];
m3[5] = 0.0f;
m3[6] = t[4];
m3[7] = t[5];
m3[8] = 1.0f;
}
static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, struct NVGscissor* scissor, float width, float fringe)
{
struct NVGcolor innerCol;
struct NVGcolor outerCol;
struct GLNVGtexture* tex = NULL;
float invxform[6], paintMat[9], scissorMat[9];
float scissorx = 0, scissory = 0;
float scissorsx = 0, scissorsy = 0;
innerCol = paint->innerColor;
outerCol = paint->outerColor;
glnvg__xformInverse(invxform, paint->xform);
glnvg__xformToMat3x3(paintMat, invxform);
if (scissor->extent[0] < 0.5f || scissor->extent[1] < 0.5f) {
memset(scissorMat, 0, sizeof(scissorMat));
scissorx = 1.0f;
scissory = 1.0f;
scissorsx = 1.0f;
scissorsy = 1.0f;
} else {
glnvg__xformInverse(invxform, scissor->xform);
glnvg__xformToMat3x3(scissorMat, invxform);
scissorx = scissor->extent[0];
scissory = scissor->extent[1];
scissorsx = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]) / fringe;
scissorsy = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]) / fringe;
}
if (paint->image != 0) {
tex = glnvg__findTexture(gl, paint->image);
if (tex == NULL) return 0;
glUseProgram(gl->shader.prog);
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_FILLIMG);
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat);
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory);
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], scissorsx, scissorsy);
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat);
glUniform2f(gl->shader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]);
glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], (width*0.5f + fringe*0.5f)/fringe);
glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0);
glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1);
glnvg__checkError("tex paint loc");
glBindTexture(GL_TEXTURE_2D, tex->tex);
glnvg__checkError("tex paint tex");
} else {
glUseProgram(gl->shader.prog);
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_FILLGRAD);
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat);
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory);
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], scissorsx, scissorsy);
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat);
glUniform2f(gl->shader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]);
glUniform1f(gl->shader.loc[GLNVG_LOC_RADIUS], paint->radius);
glUniform1f(gl->shader.loc[GLNVG_LOC_FEATHER], paint->feather);
glUniform4fv(gl->shader.loc[GLNVG_LOC_INNERCOL], 1, innerCol.rgba);
glUniform4fv(gl->shader.loc[GLNVG_LOC_OUTERCOL], 1, outerCol.rgba);
glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], (width*0.5f + fringe*0.5f)/fringe);
glnvg__checkError("grad paint loc");
}
return 1;
}
static void glnvg__renderViewport(void* uptr, int width, int height, int alphaBlend)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
gl->viewWidth = (float)width;
gl->viewHeight = (float)height;
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
if (alphaBlend == NVG_PREMULTIPLIED_ALPHA)
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
static void glnvg__renderFlush(void* uptr, int alphaBlend)
{
// struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
NVG_NOTUSED(uptr);
NVG_NOTUSED(alphaBlend);
}
static int glnvg__maxVertCount(const struct NVGpath* paths, int npaths)
{
int i, count = 0;
for (i = 0; i < npaths; i++) {
count += paths[i].nfill;
count += paths[i].nstroke;
}
return count;
}
static void glnvg__uploadPaths(const struct NVGpath* paths, int npaths)
{
const struct NVGpath* path;
int i, n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
if (path->nfill > 0) {
glBufferSubData(GL_ARRAY_BUFFER, n*sizeof(struct NVGvertex), path->nfill * sizeof(struct NVGvertex), &path->fill[0].x);
n += path->nfill;
}
if (path->nstroke > 0) {
glBufferSubData(GL_ARRAY_BUFFER, n*sizeof(struct NVGvertex), path->nstroke * sizeof(struct NVGvertex), &path->stroke[0].x);
n += path->nstroke;
}
}
}
static void glnvg__renderFill(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, float fringe,
const float* bounds, const struct NVGpath* paths, int npaths)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
const struct NVGpath* path;
int i, n, offset, maxCount;
if (gl->shader.prog == 0)
return;
maxCount = glnvg__maxVertCount(paths, npaths);
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
glBufferData(GL_ARRAY_BUFFER, maxCount * sizeof(struct NVGvertex), NULL, GL_STREAM_DRAW);
glnvg__uploadPaths(paths, npaths);
if (npaths == 1 && paths[0].convex) {
glEnable(GL_CULL_FACE);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glnvg__setupPaint(gl, paint, scissor, fringe, fringe);
glDisable(GL_CULL_FACE);
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = n * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
glDrawArrays(GL_TRIANGLE_FAN, 0, path->nfill);
n += path->nfill + path->nstroke;
}
glEnable(GL_CULL_FACE);
if (gl->edgeAntiAlias) {
// Draw fringes
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = (n + path->nfill) * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
n += path->nfill + path->nstroke;
}
}
glUseProgram(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
} else {
float quad[6*2] = {
bounds[0], bounds[3], bounds[2], bounds[3], bounds[2], bounds[1],
bounds[0], bounds[3], bounds[2], bounds[1], bounds[0], bounds[1],
};
glEnable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
// Draw shapes
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilMask(0xff);
glStencilFunc(GL_ALWAYS, 0, ~0U);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glUseProgram(gl->shader.prog);
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_SIMPLE);
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
glnvg__checkError("fill solid loc");
glEnableVertexAttribArray(0);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
glDisable(GL_CULL_FACE);
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = n * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glDrawArrays(GL_TRIANGLE_FAN, 0, path->nfill);
n += path->nfill + path->nstroke;
}
glEnable(GL_CULL_FACE);
// Draw aliased off-pixels
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_BLEND);
glEnableVertexAttribArray(1);
glnvg__setupPaint(gl, paint, scissor, fringe, fringe);
if (gl->edgeAntiAlias) {
glStencilFunc(GL_EQUAL, 0x00, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Draw fringes
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = (n + path->nfill) * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
n += path->nfill + path->nstroke;
}
}
// Draw fill
glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glDisableVertexAttribArray(1);
glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * 2*sizeof(float), quad);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (const GLvoid*)0);
glVertexAttrib2f(1, 0.5f, 1.0f);
glDrawArrays(GL_TRIANGLES, 0, 6);
glUseProgram(0);
glDisableVertexAttribArray(0);
glDisable(GL_STENCIL_TEST);
}
}
static void glnvg__renderStroke(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, float fringe,
float width, const struct NVGpath* paths, int npaths)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
const struct NVGpath* path;
int i, n, offset, maxCount;
if (gl->shader.prog == 0)
return;
glnvg__setupPaint(gl, paint, scissor, width, fringe);
glEnable(GL_CULL_FACE);
maxCount = glnvg__maxVertCount(paths, npaths);
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
glBufferData(GL_ARRAY_BUFFER, maxCount * sizeof(struct NVGvertex), NULL, GL_STREAM_DRAW);
glnvg__uploadPaths(paths, npaths);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
// Draw Strokes
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = (n + path->nfill) * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
n += path->nfill + path->nstroke;
}
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glUseProgram(0);
}
static void glnvg__renderTriangles(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor,
const struct NVGvertex* verts, int nverts)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
struct GLNVGtexture* tex = glnvg__findTexture(gl, paint->image);
struct NVGcolor color;
NVG_NOTUSED(scissor);
if (gl->shader.prog == 0)
return;
if (tex != NULL) {
glBindTexture(GL_TEXTURE_2D, tex->tex);
}
glUseProgram(gl->shader.prog);
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_IMG);
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0);
glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], (tex != NULL && tex->type == NVG_TEXTURE_RGBA) ? 0 : 1);
glnvg__checkError("tris solid img loc");
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
glBufferData(GL_ARRAY_BUFFER, nverts * sizeof(struct NVGvertex), verts, GL_STREAM_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(2 * sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
color = paint->innerColor;
glVertexAttrib4fv(2, color.rgba);
glDrawArrays(GL_TRIANGLES, 0, nverts);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
static void glnvg__renderDelete(void* uptr)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
int i;
if (gl == NULL) return;
glnvg__deleteShader(&gl->shader);
for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].tex != 0)
glDeleteTextures(1, &gl->textures[i].tex);
}
free(gl->textures);
free(gl);
}
#ifdef NANOVG_GLES2
struct NVGcontext* nvgCreateGLES2(int atlasw, int atlash, int edgeaa)
#else
struct NVGcontext* nvgCreateGL2(int atlasw, int atlash, int edgeaa)
#endif
{
struct NVGparams params;
struct NVGcontext* ctx = NULL;
struct GLNVGcontext* gl = (struct GLNVGcontext*)malloc(sizeof(struct GLNVGcontext));
if (gl == NULL) goto error;
memset(gl, 0, sizeof(struct GLNVGcontext));
memset(&params, 0, sizeof(params));
params.renderCreate = glnvg__renderCreate;
params.renderCreateTexture = glnvg__renderCreateTexture;
params.renderDeleteTexture = glnvg__renderDeleteTexture;
params.renderUpdateTexture = glnvg__renderUpdateTexture;
params.renderGetTextureSize = glnvg__renderGetTextureSize;
params.renderViewport = glnvg__renderViewport;
params.renderFlush = glnvg__renderFlush;
params.renderFill = glnvg__renderFill;
params.renderStroke = glnvg__renderStroke;
params.renderTriangles = glnvg__renderTriangles;
params.renderDelete = glnvg__renderDelete;
params.userPtr = gl;
params.atlasWidth = atlasw;
params.atlasHeight = atlash;
params.edgeAntiAlias = edgeaa;
gl->edgeAntiAlias = edgeaa;
ctx = nvgCreateInternal(&params);
if (ctx == NULL) goto error;
return ctx;
error:
// 'gl' is freed by nvgDeleteInternal.
if (ctx != NULL) nvgDeleteInternal(ctx);
return NULL;
}
#ifdef NANOVG_GLES2
void nvgDeleteGLES2(struct NVGcontext* ctx)
#else
void nvgDeleteGL2(struct NVGcontext* ctx)
#endif
{
nvgDeleteInternal(ctx);
}
#endif

View File

@ -0,0 +1,957 @@
//
// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_GL3_H
#define NANOVG_GL3_H
#ifdef __cplusplus
extern "C" {
#endif
#define NVG_ANTIALIAS 1
#ifdef NANOVG_GLES3_IMPLEMENTATION
# ifndef NANOVG_GLES3
# define NANOVG_GLES3
# endif
# ifndef NANOVG_GL3_IMPLEMENTATION
# define NANOVG_GL3_IMPLEMENTATION
# endif
#endif
#ifdef NANOVG_GLES3
struct NVGcontext* nvgCreateGLES3(int atlasw, int atlash, int edgeaa);
void nvgDeleteGLES3(struct NVGcontext* ctx);
#else
struct NVGcontext* nvgCreateGL3(int atlasw, int atlash, int edgeaa);
void nvgDeleteGL3(struct NVGcontext* ctx);
#endif
#ifdef __cplusplus
}
#endif
#endif
#ifdef NANOVG_GL3_IMPLEMENTATION
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "nanovg.h"
enum GLNVGuniformLoc {
GLNVG_LOC_VIEWSIZE,
GLNVG_LOC_SCISSORMAT,
GLNVG_LOC_SCISSOREXT,
GLNVG_LOC_SCISSORSCALE,
GLNVG_LOC_PAINTMAT,
GLNVG_LOC_EXTENT,
GLNVG_LOC_RADIUS,
GLNVG_LOC_FEATHER,
GLNVG_LOC_INNERCOL,
GLNVG_LOC_OUTERCOL,
GLNVG_LOC_STROKEMULT,
GLNVG_LOC_TEX,
GLNVG_LOC_TEXTYPE,
GLNVG_LOC_TYPE,
GLNVG_MAX_LOCS
};
enum GLNVGshaderType {
NSVG_SHADER_FILLGRAD,
NSVG_SHADER_FILLIMG,
NSVG_SHADER_SIMPLE,
NSVG_SHADER_IMG
};
struct GLNVGshader {
GLuint prog;
GLuint frag;
GLuint vert;
GLint loc[GLNVG_MAX_LOCS];
};
struct GLNVGtexture {
int id;
GLuint tex;
int width, height;
int type;
};
struct GLNVGcontext {
struct GLNVGshader shader;
struct GLNVGtexture* textures;
float viewWidth, viewHeight;
int ntextures;
int ctextures;
int textureId;
GLuint vertArr;
GLuint vertBuf;
int edgeAntiAlias;
};
static struct GLNVGtexture* glnvg__allocTexture(struct GLNVGcontext* gl)
{
struct GLNVGtexture* tex = NULL;
int i;
for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].id == 0) {
tex = &gl->textures[i];
break;
}
}
if (tex == NULL) {
if (gl->ntextures+1 > gl->ctextures) {
gl->ctextures = (gl->ctextures == 0) ? 2 : gl->ctextures*2;
gl->textures = (struct GLNVGtexture*)realloc(gl->textures, sizeof(struct GLNVGtexture)*gl->ctextures);
if (gl->textures == NULL) return NULL;
}
tex = &gl->textures[gl->ntextures++];
}
memset(tex, 0, sizeof(*tex));
tex->id = ++gl->textureId;
return tex;
}
static struct GLNVGtexture* glnvg__findTexture(struct GLNVGcontext* gl, int id)
{
int i;
for (i = 0; i < gl->ntextures; i++)
if (gl->textures[i].id == id)
return &gl->textures[i];
return NULL;
}
static int glnvg__deleteTexture(struct GLNVGcontext* gl, int id)
{
int i;
for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].id == id) {
if (gl->textures[i].tex != 0)
glDeleteTextures(1, &gl->textures[i].tex);
memset(&gl->textures[i], 0, sizeof(gl->textures[i]));
return 1;
}
}
return 0;
}
static void glnvg__dumpShaderError(GLuint shader, const char* name, const char* type)
{
char str[512+1];
int len = 0;
glGetShaderInfoLog(shader, 512, &len, str);
if (len > 512) len = 512;
str[len] = '\0';
printf("Shader %s/%s error:\n%s\n", name, type, str);
}
static void glnvg__dumpProgramError(GLuint prog, const char* name)
{
char str[512+1];
int len = 0;
glGetProgramInfoLog(prog, 512, &len, str);
if (len > 512) len = 512;
str[len] = '\0';
printf("Program %s error:\n%s\n", name, str);
}
static int glnvg__checkError(const char* str)
{
GLenum err = glGetError();
if (err != GL_NO_ERROR) {
printf("Error %08x after %s\n", err, str);
return 1;
}
return 0;
}
static int glnvg__createShader(struct GLNVGshader* shader, const char* name, const char* vshader, const char* fshader)
{
GLint status;
GLuint prog, vert, frag;
memset(shader, 0, sizeof(*shader));
prog = glCreateProgram();
vert = glCreateShader(GL_VERTEX_SHADER);
frag = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vert, 1, &vshader, 0);
glShaderSource(frag, 1, &fshader, 0);
glCompileShader(vert);
glGetShaderiv(vert, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
glnvg__dumpShaderError(vert, name, "vert");
return 0;
}
glCompileShader(frag);
glGetShaderiv(frag, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
glnvg__dumpShaderError(frag, name, "frag");
return 0;
}
glAttachShader(prog, vert);
glAttachShader(prog, frag);
glBindAttribLocation(prog, 0, "vertex");
glBindAttribLocation(prog, 1, "tcoord");
glBindAttribLocation(prog, 2, "color");
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
glnvg__dumpProgramError(prog, name);
return 0;
}
shader->prog = prog;
shader->vert = vert;
shader->frag = frag;
return 1;
}
static void glnvg__deleteShader(struct GLNVGshader* shader)
{
if (shader->prog != 0)
glDeleteProgram(shader->prog);
if (shader->vert != 0)
glDeleteShader(shader->vert);
if (shader->frag != 0)
glDeleteShader(shader->frag);
}
static void glnvg__getUniforms(struct GLNVGshader* shader)
{
shader->loc[GLNVG_LOC_VIEWSIZE] = glGetUniformLocation(shader->prog, "viewSize");
shader->loc[GLNVG_LOC_SCISSORMAT] = glGetUniformLocation(shader->prog, "scissorMat");
shader->loc[GLNVG_LOC_SCISSOREXT] = glGetUniformLocation(shader->prog, "scissorExt");
shader->loc[GLNVG_LOC_SCISSORSCALE] = glGetUniformLocation(shader->prog, "scissorScale");
shader->loc[GLNVG_LOC_PAINTMAT] = glGetUniformLocation(shader->prog, "paintMat");
shader->loc[GLNVG_LOC_EXTENT] = glGetUniformLocation(shader->prog, "extent");
shader->loc[GLNVG_LOC_RADIUS] = glGetUniformLocation(shader->prog, "radius");
shader->loc[GLNVG_LOC_FEATHER] = glGetUniformLocation(shader->prog, "feather");
shader->loc[GLNVG_LOC_INNERCOL] = glGetUniformLocation(shader->prog, "innerCol");
shader->loc[GLNVG_LOC_OUTERCOL] = glGetUniformLocation(shader->prog, "outerCol");
shader->loc[GLNVG_LOC_STROKEMULT] = glGetUniformLocation(shader->prog, "strokeMult");
shader->loc[GLNVG_LOC_TEX] = glGetUniformLocation(shader->prog, "tex");
shader->loc[GLNVG_LOC_TEXTYPE] = glGetUniformLocation(shader->prog, "texType");
shader->loc[GLNVG_LOC_TYPE] = glGetUniformLocation(shader->prog, "type");
}
static int glnvg__renderCreate(void* uptr)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
static const char* fillVertShader =
#ifdef NANOVG_GLES3
"#version 300 es\n"
"precision mediump float;\n"
#else
"#version 150 core\n"
#endif
"uniform vec2 viewSize;\n"
"in vec2 vertex;\n"
"in vec2 tcoord;\n"
"in vec4 color;\n"
"out vec2 ftcoord;\n"
"out vec4 fcolor;\n"
"out vec2 fpos;\n"
"void main(void) {\n"
" ftcoord = tcoord;\n"
" fcolor = color;\n"
" fpos = vertex;\n"
" gl_Position = vec4(2.0*vertex.x/viewSize.x - 1.0, 1.0 - 2.0*vertex.y/viewSize.y, 0, 1);\n"
"}\n";
static const char* fillFragShaderEdgeAA =
#ifdef NANOVG_GLES3
"#version 300 es\n"
"precision mediump float;\n"
#else
"#version 150 core\n"
#endif
"uniform mat3 scissorMat;\n"
"uniform vec2 scissorExt;\n"
"uniform vec2 scissorScale;\n"
"uniform mat3 paintMat;\n"
"uniform vec2 extent;\n"
"uniform float radius;\n"
"uniform float feather;\n"
"uniform vec4 innerCol;\n"
"uniform vec4 outerCol;\n"
"uniform float strokeMult;\n"
"uniform sampler2D tex;\n"
"uniform int texType;\n"
"uniform int type;\n"
"in vec2 ftcoord;\n"
"in vec4 fcolor;\n"
"in vec2 fpos;\n"
"out vec4 outColor;\n"
"\n"
"float sdroundrect(vec2 pt, vec2 ext, float rad) {\n"
" vec2 ext2 = ext - vec2(rad,rad);\n"
" vec2 d = abs(pt) - ext2;\n"
" return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;\n"
"}\n"
"\n"
"// Scissoring\n"
"float scissorMask(vec2 p) {\n"
" vec2 sc = (abs((scissorMat * vec3(p,1.0)).xy) - scissorExt);\n"
" sc = vec2(0.5,0.5) - sc * scissorScale;\n"
" return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n"
"}\n"
"\n"
"// Stroke - from [0..1] to clipped pyramid, where the slope is 1px.\n"
"float strokeMask() {\n"
" return min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * ftcoord.y;\n"
"}\n"
"\n"
"void main(void) {\n"
" if (type == 0) { // Gradient\n"
" float scissor = scissorMask(fpos);\n"
" float strokeAlpha = strokeMask();\n"
" // Calculate gradient color using box gradient\n"
" vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n"
" float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n"
" vec4 color = mix(innerCol,outerCol,d);\n"
" // Combine alpha\n"
" color.w *= strokeAlpha * scissor;\n"
" outColor = color;\n"
" } else if (type == 1) { // Image\n"
" float scissor = scissorMask(fpos);\n"
" float strokeAlpha = strokeMask();\n"
" // Calculate color fron texture\n"
" vec2 pt = (paintMat * vec3(fpos,1.0)).xy / extent;\n"
" vec4 color = texture(tex, pt);\n"
" color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
" // Combine alpha\n"
" color.w *= strokeAlpha * scissor;\n"
" outColor = color;\n"
" } else if (type == 2) { // Stencil fill\n"
" outColor = vec4(1,1,1,1);\n"
" } else if (type == 3) { // Textured tris\n"
" vec4 color = texture(tex, ftcoord);\n"
" color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
" outColor = color * fcolor;\n"
" }\n"
"}\n";
static const char* fillFragShader =
#ifdef NANOVG_GLES3
"#version 300 es\n"
"precision mediump float;\n"
#else
"#version 150 core\n"
#endif
"uniform mat3 scissorMat;\n"
"uniform vec2 scissorExt;\n"
"uniform vec2 scissorScale;\n"
"uniform mat3 paintMat;\n"
"uniform vec2 extent;\n"
"uniform float radius;\n"
"uniform float feather;\n"
"uniform vec4 innerCol;\n"
"uniform vec4 outerCol;\n"
"uniform float strokeMult;\n"
"uniform sampler2D tex;\n"
"uniform int texType;\n"
"uniform int type;\n"
"in vec2 ftcoord;\n"
"in vec4 fcolor;\n"
"in vec2 fpos;\n"
"out vec4 outColor;\n"
"\n"
"float sdroundrect(vec2 pt, vec2 ext, float rad) {\n"
" vec2 ext2 = ext - vec2(rad,rad);\n"
" vec2 d = abs(pt) - ext2;\n"
" return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;\n"
"}\n"
"\n"
"// Scissoring\n"
"float scissorMask(vec2 p) {\n"
" vec2 sc = (abs((scissorMat * vec3(p,1.0)).xy) - scissorExt);\n"
" sc = vec2(0.5,0.5) - sc * scissorScale;\n"
" return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);\n"
"}\n"
"\n"
"void main(void) {\n"
" if (type == 0) { // Gradient\n"
" float scissor = scissorMask(fpos);\n"
" // Calculate gradient color using box gradient\n"
" vec2 pt = (paintMat * vec3(fpos,1.0)).xy;\n"
" float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);\n"
" vec4 color = mix(innerCol,outerCol,d);\n"
" // Combine alpha\n"
" color.w *= scissor;\n"
" outColor = color;\n"
" } else if (type == 1) { // Image\n"
" float scissor = scissorMask(fpos);\n"
" // Calculate color fron texture\n"
" vec2 pt = (paintMat * vec3(fpos,1.0)).xy / extent;\n"
" vec4 color = texture(tex, pt);\n"
" color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
" // Combine alpha\n"
" color.w *= scissor;\n"
" outColor = color;\n"
" } else if (type == 2) { // Stencil fill\n"
" outColor = vec4(1,1,1,1);\n"
" } else if (type == 3) { // Textured tris\n"
" vec4 color = texture(tex, ftcoord);\n"
" color = texType == 0 ? color : vec4(1,1,1,color.x);\n"
" outColor = color * fcolor;\n"
" }\n"
"}\n";
glnvg__checkError("init");
if (gl->edgeAntiAlias) {
if (glnvg__createShader(&gl->shader, "shader", fillVertShader, fillFragShaderEdgeAA) == 0)
return 0;
} else {
if (glnvg__createShader(&gl->shader, "shader", fillVertShader, fillFragShader) == 0)
return 0;
}
glnvg__checkError("uniform locations");
glnvg__getUniforms(&gl->shader);
// Create dynamic vertex array
glGenVertexArrays(1, &gl->vertArr);
glGenBuffers(1, &gl->vertBuf);
glnvg__checkError("done");
return 1;
}
static int glnvg__renderCreateTexture(void* uptr, int type, int w, int h, const unsigned char* data)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
struct GLNVGtexture* tex = glnvg__allocTexture(gl);
if (tex == NULL) return 0;
glGenTextures(1, &tex->tex);
tex->width = w;
tex->height = h;
tex->type = type;
glBindTexture(GL_TEXTURE_2D, tex->tex);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
if (type == NVG_TEXTURE_RGBA)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
else
#ifdef NANOVG_GLES3
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, data);
#endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (glnvg__checkError("create tex"))
return 0;
return tex->id;
}
static int glnvg__renderDeleteTexture(void* uptr, int image)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
return glnvg__deleteTexture(gl, image);
}
static int glnvg__renderUpdateTexture(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
if (tex == NULL) return 0;
glBindTexture(GL_TEXTURE_2D, tex->tex);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, tex->width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
if (tex->type == NVG_TEXTURE_RGBA)
glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RGBA, GL_UNSIGNED_BYTE, data);
else
glTexSubImage2D(GL_TEXTURE_2D, 0, x,y, w,h, GL_RED, GL_UNSIGNED_BYTE, data);
return 1;
}
static int glnvg__renderGetTextureSize(void* uptr, int image, int* w, int* h)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
struct GLNVGtexture* tex = glnvg__findTexture(gl, image);
if (tex == NULL) return 0;
*w = tex->width;
*h = tex->height;
return 1;
}
static void glnvg__xformIdentity(float* t)
{
t[0] = 1.0f; t[1] = 0.0f;
t[2] = 0.0f; t[3] = 1.0f;
t[4] = 0.0f; t[5] = 0.0f;
}
static void glnvg__xformInverse(float* inv, float* t)
{
double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
if (det > -1e-6 && det < 1e-6) {
glnvg__xformIdentity(t);
return;
}
invdet = 1.0 / det;
inv[0] = (float)(t[3] * invdet);
inv[2] = (float)(-t[2] * invdet);
inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
inv[1] = (float)(-t[1] * invdet);
inv[3] = (float)(t[0] * invdet);
inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
}
static void glnvg__xformToMat3x3(float* m3, float* t)
{
m3[0] = t[0];
m3[1] = t[1];
m3[2] = 0.0f;
m3[3] = t[2];
m3[4] = t[3];
m3[5] = 0.0f;
m3[6] = t[4];
m3[7] = t[5];
m3[8] = 1.0f;
}
static int glnvg__setupPaint(struct GLNVGcontext* gl, struct NVGpaint* paint, struct NVGscissor* scissor, float width, float fringe)
{
struct NVGcolor innerCol;
struct NVGcolor outerCol;
struct GLNVGtexture* tex = NULL;
float invxform[6], paintMat[9], scissorMat[9];
float scissorx = 0, scissory = 0;
float scissorsx = 0, scissorsy = 0;
innerCol = paint->innerColor;
outerCol = paint->outerColor;
glnvg__xformInverse(invxform, paint->xform);
glnvg__xformToMat3x3(paintMat, invxform);
if (scissor->extent[0] < 0.5f || scissor->extent[1] < 0.5f) {
memset(scissorMat, 0, sizeof(scissorMat));
scissorx = 1.0f;
scissory = 1.0f;
scissorsx = 1.0f;
scissorsy = 1.0f;
} else {
glnvg__xformInverse(invxform, scissor->xform);
glnvg__xformToMat3x3(scissorMat, invxform);
scissorx = scissor->extent[0];
scissory = scissor->extent[1];
scissorsx = sqrtf(scissor->xform[0]*scissor->xform[0] + scissor->xform[2]*scissor->xform[2]) / fringe;
scissorsy = sqrtf(scissor->xform[1]*scissor->xform[1] + scissor->xform[3]*scissor->xform[3]) / fringe;
}
if (paint->image != 0) {
tex = glnvg__findTexture(gl, paint->image);
if (tex == NULL) return 0;
glUseProgram(gl->shader.prog);
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_FILLIMG);
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat);
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory);
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], scissorsx, scissorsy);
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat);
glUniform2f(gl->shader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]);
glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], (width*0.5f + fringe*0.5f)/fringe);
glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0);
glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1);
glnvg__checkError("tex paint loc");
glBindTexture(GL_TEXTURE_2D, tex->tex);
glnvg__checkError("tex paint tex");
} else {
glUseProgram(gl->shader.prog);
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_FILLGRAD);
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_SCISSORMAT], 1, GL_FALSE, scissorMat);
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSOREXT], scissorx, scissory);
glUniform2f(gl->shader.loc[GLNVG_LOC_SCISSORSCALE], scissorsx, scissorsy);
glUniformMatrix3fv(gl->shader.loc[GLNVG_LOC_PAINTMAT], 1, GL_FALSE, paintMat);
glUniform2f(gl->shader.loc[GLNVG_LOC_EXTENT], paint->extent[0], paint->extent[1]);
glUniform1f(gl->shader.loc[GLNVG_LOC_RADIUS], paint->radius);
glUniform1f(gl->shader.loc[GLNVG_LOC_FEATHER], paint->feather);
glUniform4fv(gl->shader.loc[GLNVG_LOC_INNERCOL], 1, innerCol.rgba);
glUniform4fv(gl->shader.loc[GLNVG_LOC_OUTERCOL], 1, outerCol.rgba);
glUniform1f(gl->shader.loc[GLNVG_LOC_STROKEMULT], (width*0.5f + fringe*0.5f)/fringe);
glnvg__checkError("grad paint loc");
}
return 1;
}
static void glnvg__renderViewport(void* uptr, int width, int height, int alphaBlend)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
gl->viewWidth = (float)width;
gl->viewHeight = (float)height;
if (alphaBlend == NVG_PREMULTIPLIED_ALPHA)
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
static void glnvg__renderFlush(void* uptr, int alphaBlend)
{
// struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
NVG_NOTUSED(uptr);
NVG_NOTUSED(alphaBlend);
}
static int glnvg__maxVertCount(const struct NVGpath* paths, int npaths)
{
int i, count = 0;
for (i = 0; i < npaths; i++) {
count += paths[i].nfill;
count += paths[i].nstroke;
}
return count;
}
static void glnvg__uploadPaths(const struct NVGpath* paths, int npaths)
{
const struct NVGpath* path;
int i, n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
if (path->nfill > 0) {
glBufferSubData(GL_ARRAY_BUFFER, n*sizeof(struct NVGvertex), path->nfill * sizeof(struct NVGvertex), &path->fill[0].x);
n += path->nfill;
}
if (path->nstroke > 0) {
glBufferSubData(GL_ARRAY_BUFFER, n*sizeof(struct NVGvertex), path->nstroke * sizeof(struct NVGvertex), &path->stroke[0].x);
n += path->nstroke;
}
}
}
static void glnvg__renderFill(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, float fringe,
const float* bounds, const struct NVGpath* paths, int npaths)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
const struct NVGpath* path;
int i, n, offset, maxCount;
if (gl->shader.prog == 0)
return;
maxCount = glnvg__maxVertCount(paths, npaths);
glBindVertexArray(gl->vertArr);
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
glBufferData(GL_ARRAY_BUFFER, maxCount * sizeof(struct NVGvertex), NULL, GL_STREAM_DRAW);
glnvg__uploadPaths(paths, npaths);
if (npaths == 1 && paths[0].convex) {
glEnable(GL_CULL_FACE);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glnvg__setupPaint(gl, paint, scissor, fringe, fringe);
glDisable(GL_CULL_FACE);
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = n * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
glDrawArrays(GL_TRIANGLE_FAN, 0, path->nfill);
n += path->nfill + path->nstroke;
}
glEnable(GL_CULL_FACE);
if (gl->edgeAntiAlias) {
// Draw fringes
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = (n + path->nfill) * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
n += path->nfill + path->nstroke;
}
}
glUseProgram(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
} else {
glEnable(GL_CULL_FACE);
glBindVertexArray(gl->vertArr);
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
// Draw shapes
glDisable(GL_BLEND);
glEnable(GL_STENCIL_TEST);
glStencilMask(0xff);
glStencilFunc(GL_ALWAYS, 0, ~0);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glUseProgram(gl->shader.prog);
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_SIMPLE);
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
glnvg__checkError("fill solid loc");
glEnableVertexAttribArray(0);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
glDisable(GL_CULL_FACE);
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = n * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glDrawArrays(GL_TRIANGLE_FAN, 0, path->nfill);
n += path->nfill + path->nstroke;
}
glEnable(GL_CULL_FACE);
// Draw aliased off-pixels
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_BLEND);
glEnableVertexAttribArray(1);
glnvg__setupPaint(gl, paint, scissor, fringe, fringe);
if (gl->edgeAntiAlias) {
glStencilFunc(GL_EQUAL, 0x00, 0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
// Draw fringes
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = (n + path->nfill) * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
n += path->nfill + path->nstroke;
}
}
// Draw fill
glStencilFunc(GL_NOTEQUAL, 0x0, 0xff);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glDisableVertexAttribArray(1);
float quad[6*2] = {
bounds[0], bounds[3], bounds[2], bounds[3], bounds[2], bounds[1],
bounds[0], bounds[3], bounds[2], bounds[1], bounds[0], bounds[1],
};
glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * 2*sizeof(float), quad);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (const GLvoid*)0);
glVertexAttrib2f(1, 0.5f, 1.0f);
glDrawArrays(GL_TRIANGLES, 0, 6);
glUseProgram(0);
glDisableVertexAttribArray(0);
glDisable(GL_STENCIL_TEST);
}
}
static void glnvg__renderStroke(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor, float fringe,
float width, const struct NVGpath* paths, int npaths)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
const struct NVGpath* path;
int i, n, offset, maxCount;
if (gl->shader.prog == 0)
return;
glnvg__setupPaint(gl, paint, scissor, width, fringe);
glEnable(GL_CULL_FACE);
maxCount = glnvg__maxVertCount(paths, npaths);
glBindVertexArray(gl->vertArr);
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
glBufferData(GL_ARRAY_BUFFER, maxCount * sizeof(struct NVGvertex), NULL, GL_STREAM_DRAW);
glnvg__uploadPaths(paths, npaths);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
// Draw Strokes
n = 0;
for (i = 0; i < npaths; i++) {
path = &paths[i];
offset = (n + path->nfill) * sizeof(struct NVGvertex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(size_t)offset);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(offset + 2*sizeof(float)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, path->nstroke);
n += path->nfill + path->nstroke;
}
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glUseProgram(0);
}
static void glnvg__renderTriangles(void* uptr, struct NVGpaint* paint, struct NVGscissor* scissor,
const struct NVGvertex* verts, int nverts)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
struct GLNVGtexture* tex = glnvg__findTexture(gl, paint->image);
struct NVGcolor color;
NVG_NOTUSED(scissor);
if (gl->shader.prog == 0)
return;
if (tex != NULL) {
glBindTexture(GL_TEXTURE_2D, tex->tex);
}
glUseProgram(gl->shader.prog);
glUniform1i(gl->shader.loc[GLNVG_LOC_TYPE], NSVG_SHADER_IMG);
glUniform2f(gl->shader.loc[GLNVG_LOC_VIEWSIZE], gl->viewWidth, gl->viewHeight);
glUniform1i(gl->shader.loc[GLNVG_LOC_TEX], 0);
glUniform1i(gl->shader.loc[GLNVG_LOC_TEXTYPE], tex->type == NVG_TEXTURE_RGBA ? 0 : 1);
glnvg__checkError("tris solid img loc");
glBindVertexArray(gl->vertArr);
glBindBuffer(GL_ARRAY_BUFFER, gl->vertBuf);
glBufferData(GL_ARRAY_BUFFER, nverts * sizeof(struct NVGvertex), verts, GL_STREAM_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(struct NVGvertex), (const GLvoid*)(2 * sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
color = paint->innerColor;
glVertexAttrib4fv(2, color.rgba);
glDrawArrays(GL_TRIANGLES, 0, nverts);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
static void glnvg__renderDelete(void* uptr)
{
struct GLNVGcontext* gl = (struct GLNVGcontext*)uptr;
int i;
if (gl == NULL) return;
glnvg__deleteShader(&gl->shader);
for (i = 0; i < gl->ntextures; i++) {
if (gl->textures[i].tex != 0)
glDeleteTextures(1, &gl->textures[i].tex);
}
free(gl->textures);
free(gl);
}
#ifdef NANOVG_GLES3
struct NVGcontext* nvgCreateGLES3(int atlasw, int atlash, int edgeaa)
#else
struct NVGcontext* nvgCreateGL3(int atlasw, int atlash, int edgeaa)
#endif
{
struct NVGparams params;
struct NVGcontext* ctx = NULL;
struct GLNVGcontext* gl = (struct GLNVGcontext*)malloc(sizeof(struct GLNVGcontext));
if (gl == NULL) goto error;
memset(gl, 0, sizeof(struct GLNVGcontext));
memset(&params, 0, sizeof(params));
params.renderCreate = glnvg__renderCreate;
params.renderCreateTexture = glnvg__renderCreateTexture;
params.renderDeleteTexture = glnvg__renderDeleteTexture;
params.renderUpdateTexture = glnvg__renderUpdateTexture;
params.renderGetTextureSize = glnvg__renderGetTextureSize;
params.renderViewport = glnvg__renderViewport;
params.renderFlush = glnvg__renderFlush;
params.renderFill = glnvg__renderFill;
params.renderStroke = glnvg__renderStroke;
params.renderTriangles = glnvg__renderTriangles;
params.renderDelete = glnvg__renderDelete;
params.userPtr = gl;
params.atlasWidth = atlasw;
params.atlasHeight = atlash;
params.edgeAntiAlias = edgeaa;
gl->edgeAntiAlias = edgeaa;
ctx = nvgCreateInternal(&params);
if (ctx == NULL) goto error;
return ctx;
error:
// 'gl' is freed by nvgDeleteInternal.
if (ctx != NULL) nvgDeleteInternal(ctx);
return NULL;
}
#ifdef NANOVG_GLES3
void nvgDeleteGLES3(struct NVGcontext* ctx)
#else
void nvgDeleteGL3(struct NVGcontext* ctx)
#endif
{
nvgDeleteInternal(ctx);
}
#endif

View File

@ -0,0 +1,6 @@
The files in this folder will be removed in near future.
- nanovg_gl2.h and nanovg_gl3.h
- These were the first GL2 and GL3 backends
- an optimized version of the gl3 backed was build and later GL2 support was added to it
- the new combined backend has superseded the individual backends

254
3rd/nanovg/premake4.lua Normal file
View File

@ -0,0 +1,254 @@
local action = _ACTION or ""
solution "nanovg"
location ( "build" )
configurations { "Debug", "Release" }
platforms {"native", "x64", "x32"}
project "nanovg"
language "C"
kind "StaticLib"
includedirs { "src" }
files { "src/*.c" }
targetdir("build")
defines { "_CRT_SECURE_NO_WARNINGS" } --,"FONS_USE_FREETYPE" } Uncomment to compile with FreeType support
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
project "example_gl2"
kind "ConsoleApp"
language "C"
files { "example/example_gl2.c", "example/demo.c", "example/perf.c" }
includedirs { "src", "example" }
targetdir("build")
links { "nanovg" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW" }
defines { "NANOVG_GLEW" }
configuration { "windows" }
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" }
defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
links { "glfw3" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
project "example_gl3"
kind "ConsoleApp"
language "C"
files { "example/example_gl3.c", "example/demo.c", "example/perf.c" }
includedirs { "src", "example" }
targetdir("build")
links { "nanovg" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW" }
defines { "NANOVG_GLEW" }
configuration { "windows" }
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" }
defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
links { "glfw3" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
project "example_gl2_msaa"
kind "ConsoleApp"
language "C"
defines { "DEMO_MSAA" }
files { "example/example_gl2.c", "example/demo.c", "example/perf.c" }
includedirs { "src", "example" }
targetdir("build")
links { "nanovg" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW" }
defines { "NANOVG_GLEW" }
configuration { "windows" }
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" }
defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
links { "glfw3" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
project "example_gl3_msaa"
kind "ConsoleApp"
language "C"
defines { "DEMO_MSAA" }
files { "example/example_gl3.c", "example/demo.c", "example/perf.c" }
includedirs { "src", "example" }
targetdir("build")
links { "nanovg" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW" }
defines { "NANOVG_GLEW" }
configuration { "windows" }
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" }
defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
links { "glfw3" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
project "example_fbo"
kind "ConsoleApp"
language "C"
files { "example/example_fbo.c", "example/perf.c" }
includedirs { "src", "example" }
targetdir("build")
links { "nanovg" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW" }
configuration { "windows" }
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" }
defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
links { "glfw3" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
project "example_gles2"
kind "ConsoleApp"
language "C"
files { "example/example_gles2.c", "example/demo.c", "example/perf.c" }
includedirs { "src", "example" }
targetdir("build")
links { "nanovg" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW" }
configuration { "windows" }
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" }
defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
links { "glfw3" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
project "example_gles3"
kind "ConsoleApp"
language "C"
files { "example/example_gles3.c", "example/demo.c", "example/perf.c" }
includedirs { "src", "example" }
targetdir("build")
links { "nanovg" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW" }
configuration { "windows" }
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32", "kernel32" }
defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
links { "glfw3" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}
project "sdl"
kind "ConsoleApp"
language "C"
files { "example/sdl.c", "example/demo.c", "example/perf.c" }
includedirs { "src", "example" }
targetdir("build")
links { "nanovg" }
configuration { "linux" }
linkoptions { "`pkg-config --libs glfw3`" }
links { "GL", "GLU", "m", "GLEW" }
defines { "NANOVG_GLEW" }
configuration { "windows" }
links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "SDL2", "glu32","opengl32", "kernel32" }
defines { "NANOVG_GLEW", "_CRT_SECURE_NO_WARNINGS" }
configuration { "macosx" }
links { "glfw3", "SDL2" }
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo", "-framework Carbon" }
configuration "Debug"
defines { "DEBUG" }
flags { "Symbols", "ExtraWarnings"}
configuration "Release"
defines { "NDEBUG" }
flags { "Optimize", "ExtraWarnings"}

1753
3rd/nanovg/src/fontstash.h Normal file

File diff suppressed because it is too large Load Diff

2891
3rd/nanovg/src/nanovg.c Normal file

File diff suppressed because it is too large Load Diff

685
3rd/nanovg/src/nanovg.h Normal file
View File

@ -0,0 +1,685 @@
//
// Copyright (c) 2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_H
#define NANOVG_H
#ifdef __cplusplus
extern "C" {
#endif
#define NVG_PI 3.14159265358979323846264338327f
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union
#endif
typedef struct NVGcontext NVGcontext;
struct NVGcolor {
union {
float rgba[4];
struct {
float r,g,b,a;
};
};
};
typedef struct NVGcolor NVGcolor;
struct NVGpaint {
float xform[6];
float extent[2];
float radius;
float feather;
NVGcolor innerColor;
NVGcolor outerColor;
int image;
};
typedef struct NVGpaint NVGpaint;
enum NVGwinding {
NVG_CCW = 1, // Winding for solid shapes
NVG_CW = 2, // Winding for holes
};
enum NVGsolidity {
NVG_SOLID = 1, // CCW
NVG_HOLE = 2, // CW
};
enum NVGlineCap {
NVG_BUTT,
NVG_ROUND,
NVG_SQUARE,
NVG_BEVEL,
NVG_MITER,
};
enum NVGalign {
// Horizontal align
NVG_ALIGN_LEFT = 1<<0, // Default, align text horizontally to left.
NVG_ALIGN_CENTER = 1<<1, // Align text horizontally to center.
NVG_ALIGN_RIGHT = 1<<2, // Align text horizontally to right.
// Vertical align
NVG_ALIGN_TOP = 1<<3, // Align text vertically to top.
NVG_ALIGN_MIDDLE = 1<<4, // Align text vertically to middle.
NVG_ALIGN_BOTTOM = 1<<5, // Align text vertically to bottom.
NVG_ALIGN_BASELINE = 1<<6, // Default, align text vertically to baseline.
};
enum NVGblendFactor {
NVG_ZERO = 1<<0,
NVG_ONE = 1<<1,
NVG_SRC_COLOR = 1<<2,
NVG_ONE_MINUS_SRC_COLOR = 1<<3,
NVG_DST_COLOR = 1<<4,
NVG_ONE_MINUS_DST_COLOR = 1<<5,
NVG_SRC_ALPHA = 1<<6,
NVG_ONE_MINUS_SRC_ALPHA = 1<<7,
NVG_DST_ALPHA = 1<<8,
NVG_ONE_MINUS_DST_ALPHA = 1<<9,
NVG_SRC_ALPHA_SATURATE = 1<<10,
};
enum NVGcompositeOperation {
NVG_SOURCE_OVER,
NVG_SOURCE_IN,
NVG_SOURCE_OUT,
NVG_ATOP,
NVG_DESTINATION_OVER,
NVG_DESTINATION_IN,
NVG_DESTINATION_OUT,
NVG_DESTINATION_ATOP,
NVG_LIGHTER,
NVG_COPY,
NVG_XOR,
};
struct NVGcompositeOperationState {
int srcRGB;
int dstRGB;
int srcAlpha;
int dstAlpha;
};
typedef struct NVGcompositeOperationState NVGcompositeOperationState;
struct NVGglyphPosition {
const char* str; // Position of the glyph in the input string.
float x; // The x-coordinate of the logical glyph position.
float minx, maxx; // The bounds of the glyph shape.
};
typedef struct NVGglyphPosition NVGglyphPosition;
struct NVGtextRow {
const char* start; // Pointer to the input text where the row starts.
const char* end; // Pointer to the input text where the row ends (one past the last character).
const char* next; // Pointer to the beginning of the next row.
float width; // Logical width of the row.
float minx, maxx; // Actual bounds of the row. Logical with and bounds can differ because of kerning and some parts over extending.
};
typedef struct NVGtextRow NVGtextRow;
enum NVGimageFlags {
NVG_IMAGE_GENERATE_MIPMAPS = 1<<0, // Generate mipmaps during creation of the image.
NVG_IMAGE_REPEATX = 1<<1, // Repeat image in X direction.
NVG_IMAGE_REPEATY = 1<<2, // Repeat image in Y direction.
NVG_IMAGE_FLIPY = 1<<3, // Flips (inverses) image in Y direction when rendered.
NVG_IMAGE_PREMULTIPLIED = 1<<4, // Image data has premultiplied alpha.
NVG_IMAGE_NEAREST = 1<<5, // Image interpolation is Nearest instead Linear
};
// Begin drawing a new frame
// Calls to nanovg drawing API should be wrapped in nvgBeginFrame() & nvgEndFrame()
// nvgBeginFrame() defines the size of the window to render to in relation currently
// set viewport (i.e. glViewport on GL backends). Device pixel ration allows to
// control the rendering on Hi-DPI devices.
// For example, GLFW returns two dimension for an opened window: window size and
// frame buffer size. In that case you would set windowWidth/Height to the window size
// devicePixelRatio to: frameBufferWidth / windowWidth.
void nvgBeginFrame(NVGcontext* ctx, int windowWidth, int windowHeight, float devicePixelRatio);
// Cancels drawing the current frame.
void nvgCancelFrame(NVGcontext* ctx);
// Ends drawing flushing remaining render state.
void nvgEndFrame(NVGcontext* ctx);
//
// Composite operation
//
// The composite operations in NanoVG are modeled after HTML Canvas API, and
// the blend func is based on OpenGL (see corresponding manuals for more info).
// The colors in the blending state have premultiplied alpha.
// Sets the composite operation. The op parameter should be one of NVGcompositeOperation.
void nvgGlobalCompositeOperation(NVGcontext* ctx, int op);
// Sets the composite operation with custom pixel arithmetic. The parameters should be one of NVGblendFactor.
void nvgGlobalCompositeBlendFunc(NVGcontext* ctx, int sfactor, int dfactor);
// Sets the composite operation with custom pixel arithmetic for RGB and alpha components separately. The parameters should be one of NVGblendFactor.
void nvgGlobalCompositeBlendFuncSeparate(NVGcontext* ctx, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha);
//
// Color utils
//
// Colors in NanoVG are stored as unsigned ints in ABGR format.
// Returns a color value from red, green, blue values. Alpha will be set to 255 (1.0f).
NVGcolor nvgRGB(unsigned char r, unsigned char g, unsigned char b);
// Returns a color value from red, green, blue values. Alpha will be set to 1.0f.
NVGcolor nvgRGBf(float r, float g, float b);
// Returns a color value from red, green, blue and alpha values.
NVGcolor nvgRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
// Returns a color value from red, green, blue and alpha values.
NVGcolor nvgRGBAf(float r, float g, float b, float a);
// Linearly interpolates from color c0 to c1, and returns resulting color value.
NVGcolor nvgLerpRGBA(NVGcolor c0, NVGcolor c1, float u);
// Sets transparency of a color value.
NVGcolor nvgTransRGBA(NVGcolor c0, unsigned char a);
// Sets transparency of a color value.
NVGcolor nvgTransRGBAf(NVGcolor c0, float a);
// Returns color value specified by hue, saturation and lightness.
// HSL values are all in range [0..1], alpha will be set to 255.
NVGcolor nvgHSL(float h, float s, float l);
// Returns color value specified by hue, saturation and lightness and alpha.
// HSL values are all in range [0..1], alpha in range [0..255]
NVGcolor nvgHSLA(float h, float s, float l, unsigned char a);
//
// State Handling
//
// NanoVG contains state which represents how paths will be rendered.
// The state contains transform, fill and stroke styles, text and font styles,
// and scissor clipping.
// Pushes and saves the current render state into a state stack.
// A matching nvgRestore() must be used to restore the state.
void nvgSave(NVGcontext* ctx);
// Pops and restores current render state.
void nvgRestore(NVGcontext* ctx);
// Resets current render state to default values. Does not affect the render state stack.
void nvgReset(NVGcontext* ctx);
//
// Render styles
//
// Fill and stroke render style can be either a solid color or a paint which is a gradient or a pattern.
// Solid color is simply defined as a color value, different kinds of paints can be created
// using nvgLinearGradient(), nvgBoxGradient(), nvgRadialGradient() and nvgImagePattern().
//
// Current render style can be saved and restored using nvgSave() and nvgRestore().
// Sets whether to draw antialias for nvgStroke() and nvgFill(). It's enabled by default.
void nvgShapeAntiAlias(NVGcontext* ctx, int enabled);
// Sets current stroke style to a solid color.
void nvgStrokeColor(NVGcontext* ctx, NVGcolor color);
// Sets current stroke style to a paint, which can be a one of the gradients or a pattern.
void nvgStrokePaint(NVGcontext* ctx, NVGpaint paint);
// Sets current fill style to a solid color.
void nvgFillColor(NVGcontext* ctx, NVGcolor color);
// Sets current fill style to a paint, which can be a one of the gradients or a pattern.
void nvgFillPaint(NVGcontext* ctx, NVGpaint paint);
// Sets the miter limit of the stroke style.
// Miter limit controls when a sharp corner is beveled.
void nvgMiterLimit(NVGcontext* ctx, float limit);
// Sets the stroke width of the stroke style.
void nvgStrokeWidth(NVGcontext* ctx, float size);
// Sets how the end of the line (cap) is drawn,
// Can be one of: NVG_BUTT (default), NVG_ROUND, NVG_SQUARE.
void nvgLineCap(NVGcontext* ctx, int cap);
// Sets how sharp path corners are drawn.
// Can be one of NVG_MITER (default), NVG_ROUND, NVG_BEVEL.
void nvgLineJoin(NVGcontext* ctx, int join);
// Sets the transparency applied to all rendered shapes.
// Already transparent paths will get proportionally more transparent as well.
void nvgGlobalAlpha(NVGcontext* ctx, float alpha);
//
// Transforms
//
// The paths, gradients, patterns and scissor region are transformed by an transformation
// matrix at the time when they are passed to the API.
// The current transformation matrix is a affine matrix:
// [sx kx tx]
// [ky sy ty]
// [ 0 0 1]
// Where: sx,sy define scaling, kx,ky skewing, and tx,ty translation.
// The last row is assumed to be 0,0,1 and is not stored.
//
// Apart from nvgResetTransform(), each transformation function first creates
// specific transformation matrix and pre-multiplies the current transformation by it.
//
// Current coordinate system (transformation) can be saved and restored using nvgSave() and nvgRestore().
// Resets current transform to a identity matrix.
void nvgResetTransform(NVGcontext* ctx);
// Premultiplies current coordinate system by specified matrix.
// The parameters are interpreted as matrix as follows:
// [a c e]
// [b d f]
// [0 0 1]
void nvgTransform(NVGcontext* ctx, float a, float b, float c, float d, float e, float f);
// Translates current coordinate system.
void nvgTranslate(NVGcontext* ctx, float x, float y);
// Rotates current coordinate system. Angle is specified in radians.
void nvgRotate(NVGcontext* ctx, float angle);
// Skews the current coordinate system along X axis. Angle is specified in radians.
void nvgSkewX(NVGcontext* ctx, float angle);
// Skews the current coordinate system along Y axis. Angle is specified in radians.
void nvgSkewY(NVGcontext* ctx, float angle);
// Scales the current coordinate system.
void nvgScale(NVGcontext* ctx, float x, float y);
// Stores the top part (a-f) of the current transformation matrix in to the specified buffer.
// [a c e]
// [b d f]
// [0 0 1]
// There should be space for 6 floats in the return buffer for the values a-f.
void nvgCurrentTransform(NVGcontext* ctx, float* xform);
// The following functions can be used to make calculations on 2x3 transformation matrices.
// A 2x3 matrix is represented as float[6].
// Sets the transform to identity matrix.
void nvgTransformIdentity(float* dst);
// Sets the transform to translation matrix matrix.
void nvgTransformTranslate(float* dst, float tx, float ty);
// Sets the transform to scale matrix.
void nvgTransformScale(float* dst, float sx, float sy);
// Sets the transform to rotate matrix. Angle is specified in radians.
void nvgTransformRotate(float* dst, float a);
// Sets the transform to skew-x matrix. Angle is specified in radians.
void nvgTransformSkewX(float* dst, float a);
// Sets the transform to skew-y matrix. Angle is specified in radians.
void nvgTransformSkewY(float* dst, float a);
// Sets the transform to the result of multiplication of two transforms, of A = A*B.
void nvgTransformMultiply(float* dst, const float* src);
// Sets the transform to the result of multiplication of two transforms, of A = B*A.
void nvgTransformPremultiply(float* dst, const float* src);
// Sets the destination to inverse of specified transform.
// Returns 1 if the inverse could be calculated, else 0.
int nvgTransformInverse(float* dst, const float* src);
// Transform a point by given transform.
void nvgTransformPoint(float* dstx, float* dsty, const float* xform, float srcx, float srcy);
// Converts degrees to radians and vice versa.
float nvgDegToRad(float deg);
float nvgRadToDeg(float rad);
//
// Images
//
// NanoVG allows you to load jpg, png, psd, tga, pic and gif files to be used for rendering.
// In addition you can upload your own image. The image loading is provided by stb_image.
// The parameter imageFlags is combination of flags defined in NVGimageFlags.
// Creates image by loading it from the disk from specified file name.
// Returns handle to the image.
int nvgCreateImage(NVGcontext* ctx, const char* filename, int imageFlags);
// Creates image by loading it from the specified chunk of memory.
// Returns handle to the image.
int nvgCreateImageMem(NVGcontext* ctx, int imageFlags, unsigned char* data, int ndata);
// Creates image from specified image data.
// Returns handle to the image.
int nvgCreateImageRGBA(NVGcontext* ctx, int w, int h, int imageFlags, const unsigned char* data);
// Updates image data specified by image handle.
void nvgUpdateImage(NVGcontext* ctx, int image, const unsigned char* data);
// Returns the dimensions of a created image.
void nvgImageSize(NVGcontext* ctx, int image, int* w, int* h);
// Deletes created image.
void nvgDeleteImage(NVGcontext* ctx, int image);
//
// Paints
//
// NanoVG supports four types of paints: linear gradient, box gradient, radial gradient and image pattern.
// These can be used as paints for strokes and fills.
// Creates and returns a linear gradient. Parameters (sx,sy)-(ex,ey) specify the start and end coordinates
// of the linear gradient, icol specifies the start color and ocol the end color.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgLinearGradient(NVGcontext* ctx, float sx, float sy, float ex, float ey,
NVGcolor icol, NVGcolor ocol);
// Creates and returns a box gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
// drop shadows or highlights for boxes. Parameters (x,y) define the top-left corner of the rectangle,
// (w,h) define the size of the rectangle, r defines the corner radius, and f feather. Feather defines how blurry
// the border of the rectangle is. Parameter icol specifies the inner color and ocol the outer color of the gradient.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgBoxGradient(NVGcontext* ctx, float x, float y, float w, float h,
float r, float f, NVGcolor icol, NVGcolor ocol);
// Creates and returns a radial gradient. Parameters (cx,cy) specify the center, inr and outr specify
// the inner and outer radius of the gradient, icol specifies the start color and ocol the end color.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgRadialGradient(NVGcontext* ctx, float cx, float cy, float inr, float outr,
NVGcolor icol, NVGcolor ocol);
// Creates and returns an image patter. Parameters (ox,oy) specify the left-top location of the image pattern,
// (ex,ey) the size of one image, angle rotation around the top-left corner, image is handle to the image to render.
// The gradient is transformed by the current transform when it is passed to nvgFillPaint() or nvgStrokePaint().
NVGpaint nvgImagePattern(NVGcontext* ctx, float ox, float oy, float ex, float ey,
float angle, int image, float alpha);
//
// Scissoring
//
// Scissoring allows you to clip the rendering into a rectangle. This is useful for various
// user interface cases like rendering a text edit or a timeline.
// Sets the current scissor rectangle.
// The scissor rectangle is transformed by the current transform.
void nvgScissor(NVGcontext* ctx, float x, float y, float w, float h);
// Intersects current scissor rectangle with the specified rectangle.
// The scissor rectangle is transformed by the current transform.
// Note: in case the rotation of previous scissor rect differs from
// the current one, the intersection will be done between the specified
// rectangle and the previous scissor rectangle transformed in the current
// transform space. The resulting shape is always rectangle.
void nvgIntersectScissor(NVGcontext* ctx, float x, float y, float w, float h);
// Reset and disables scissoring.
void nvgResetScissor(NVGcontext* ctx);
//
// Paths
//
// Drawing a new shape starts with nvgBeginPath(), it clears all the currently defined paths.
// Then you define one or more paths and sub-paths which describe the shape. The are functions
// to draw common shapes like rectangles and circles, and lower level step-by-step functions,
// which allow to define a path curve by curve.
//
// NanoVG uses even-odd fill rule to draw the shapes. Solid shapes should have counter clockwise
// winding and holes should have counter clockwise order. To specify winding of a path you can
// call nvgPathWinding(). This is useful especially for the common shapes, which are drawn CCW.
//
// Finally you can fill the path using current fill style by calling nvgFill(), and stroke it
// with current stroke style by calling nvgStroke().
//
// The curve segments and sub-paths are transformed by the current transform.
// Clears the current path and sub-paths.
void nvgBeginPath(NVGcontext* ctx);
// Starts new sub-path with specified point as first point.
void nvgMoveTo(NVGcontext* ctx, float x, float y);
// Adds line segment from the last point in the path to the specified point.
void nvgLineTo(NVGcontext* ctx, float x, float y);
// Adds cubic bezier segment from last point in the path via two control points to the specified point.
void nvgBezierTo(NVGcontext* ctx, float c1x, float c1y, float c2x, float c2y, float x, float y);
// Adds quadratic bezier segment from last point in the path via a control point to the specified point.
void nvgQuadTo(NVGcontext* ctx, float cx, float cy, float x, float y);
// Adds an arc segment at the corner defined by the last path point, and two specified points.
void nvgArcTo(NVGcontext* ctx, float x1, float y1, float x2, float y2, float radius);
// Closes current sub-path with a line segment.
void nvgClosePath(NVGcontext* ctx);
// Sets the current sub-path winding, see NVGwinding and NVGsolidity.
void nvgPathWinding(NVGcontext* ctx, int dir);
// Creates new circle arc shaped sub-path. The arc center is at cx,cy, the arc radius is r,
// and the arc is drawn from angle a0 to a1, and swept in direction dir (NVG_CCW, or NVG_CW).
// Angles are specified in radians.
void nvgArc(NVGcontext* ctx, float cx, float cy, float r, float a0, float a1, int dir);
// Creates new rectangle shaped sub-path.
void nvgRect(NVGcontext* ctx, float x, float y, float w, float h);
// Creates new rounded rectangle shaped sub-path.
void nvgRoundedRect(NVGcontext* ctx, float x, float y, float w, float h, float r);
// Creates new rounded rectangle shaped sub-path with varying radii for each corner.
void nvgRoundedRectVarying(NVGcontext* ctx, float x, float y, float w, float h, float radTopLeft, float radTopRight, float radBottomRight, float radBottomLeft);
// Creates new ellipse shaped sub-path.
void nvgEllipse(NVGcontext* ctx, float cx, float cy, float rx, float ry);
// Creates new circle shaped sub-path.
void nvgCircle(NVGcontext* ctx, float cx, float cy, float r);
// Fills the current path with current fill style.
void nvgFill(NVGcontext* ctx);
// Fills the current path with current stroke style.
void nvgStroke(NVGcontext* ctx);
//
// Text
//
// NanoVG allows you to load .ttf files and use the font to render text.
//
// The appearance of the text can be defined by setting the current text style
// and by specifying the fill color. Common text and font settings such as
// font size, letter spacing and text align are supported. Font blur allows you
// to create simple text effects such as drop shadows.
//
// At render time the font face can be set based on the font handles or name.
//
// Font measure functions return values in local space, the calculations are
// carried in the same resolution as the final rendering. This is done because
// the text glyph positions are snapped to the nearest pixels sharp rendering.
//
// The local space means that values are not rotated or scale as per the current
// transformation. For example if you set font size to 12, which would mean that
// line height is 16, then regardless of the current scaling and rotation, the
// returned line height is always 16. Some measures may vary because of the scaling
// since aforementioned pixel snapping.
//
// While this may sound a little odd, the setup allows you to always render the
// same way regardless of scaling. I.e. following works regardless of scaling:
//
// const char* txt = "Text me up.";
// nvgTextBounds(vg, x,y, txt, NULL, bounds);
// nvgBeginPath(vg);
// nvgRoundedRect(vg, bounds[0],bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]);
// nvgFill(vg);
//
// Note: currently only solid color fill is supported for text.
// Creates font by loading it from the disk from specified file name.
// Returns handle to the font.
int nvgCreateFont(NVGcontext* ctx, const char* name, const char* filename);
// Creates font by loading it from the specified memory chunk.
// Returns handle to the font.
int nvgCreateFontMem(NVGcontext* ctx, const char* name, unsigned char* data, int ndata, int freeData);
// Finds a loaded font of specified name, and returns handle to it, or -1 if the font is not found.
int nvgFindFont(NVGcontext* ctx, const char* name);
// Adds a fallback font by handle.
int nvgAddFallbackFontId(NVGcontext* ctx, int baseFont, int fallbackFont);
// Adds a fallback font by name.
int nvgAddFallbackFont(NVGcontext* ctx, const char* baseFont, const char* fallbackFont);
// Sets the font size of current text style.
void nvgFontSize(NVGcontext* ctx, float size);
// Sets the blur of current text style.
void nvgFontBlur(NVGcontext* ctx, float blur);
// Sets the letter spacing of current text style.
void nvgTextLetterSpacing(NVGcontext* ctx, float spacing);
// Sets the proportional line height of current text style. The line height is specified as multiple of font size.
void nvgTextLineHeight(NVGcontext* ctx, float lineHeight);
// Sets the text align of current text style, see NVGalign for options.
void nvgTextAlign(NVGcontext* ctx, int align);
// Sets the font face based on specified id of current text style.
void nvgFontFaceId(NVGcontext* ctx, int font);
// Sets the font face based on specified name of current text style.
void nvgFontFace(NVGcontext* ctx, const char* font);
// Draws text string at specified location. If end is specified only the sub-string up to the end is drawn.
float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char* end);
// Draws multi-line text string at specified location wrapped at the specified width. If end is specified only the sub-string up to the end is drawn.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
void nvgTextBox(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end);
// Measures the specified text string. Parameter bounds should be a pointer to float[4],
// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
// Returns the horizontal advance of the measured text (i.e. where the next character should drawn).
// Measured values are returned in local coordinate space.
float nvgTextBounds(NVGcontext* ctx, float x, float y, const char* string, const char* end, float* bounds);
// Measures the specified multi-text string. Parameter bounds should be a pointer to float[4],
// if the bounding box of the text should be returned. The bounds value are [xmin,ymin, xmax,ymax]
// Measured values are returned in local coordinate space.
void nvgTextBoxBounds(NVGcontext* ctx, float x, float y, float breakRowWidth, const char* string, const char* end, float* bounds);
// Calculates the glyph x positions of the specified text. If end is specified only the sub-string will be used.
// Measured values are returned in local coordinate space.
int nvgTextGlyphPositions(NVGcontext* ctx, float x, float y, const char* string, const char* end, NVGglyphPosition* positions, int maxPositions);
// Returns the vertical metrics based on the current text style.
// Measured values are returned in local coordinate space.
void nvgTextMetrics(NVGcontext* ctx, float* ascender, float* descender, float* lineh);
// Breaks the specified text into lines. If end is specified only the sub-string will be used.
// White space is stripped at the beginning of the rows, the text is split at word boundaries or when new-line characters are encountered.
// Words longer than the max width are slit at nearest character (i.e. no hyphenation).
int nvgTextBreakLines(NVGcontext* ctx, const char* string, const char* end, float breakRowWidth, NVGtextRow* rows, int maxRows);
//
// Internal Render API
//
enum NVGtexture {
NVG_TEXTURE_ALPHA = 0x01,
NVG_TEXTURE_RGBA = 0x02,
};
struct NVGscissor {
float xform[6];
float extent[2];
};
typedef struct NVGscissor NVGscissor;
struct NVGvertex {
float x,y,u,v;
};
typedef struct NVGvertex NVGvertex;
struct NVGpath {
int first;
int count;
unsigned char closed;
int nbevel;
NVGvertex* fill;
int nfill;
NVGvertex* stroke;
int nstroke;
int winding;
int convex;
};
typedef struct NVGpath NVGpath;
struct NVGparams {
void* userPtr;
int edgeAntiAlias;
int (*renderCreate)(void* uptr);
int (*renderCreateTexture)(void* uptr, int type, int w, int h, int imageFlags, const unsigned char* data);
int (*renderDeleteTexture)(void* uptr, int image);
int (*renderUpdateTexture)(void* uptr, int image, int x, int y, int w, int h, const unsigned char* data);
int (*renderGetTextureSize)(void* uptr, int image, int* w, int* h);
void (*renderViewport)(void* uptr, int width, int height, float devicePixelRatio);
void (*renderCancel)(void* uptr);
void (*renderFlush)(void* uptr);
void (*renderFill)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, const float* bounds, const NVGpath* paths, int npaths);
void (*renderStroke)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, float fringe, float strokeWidth, const NVGpath* paths, int npaths);
void (*renderTriangles)(void* uptr, NVGpaint* paint, NVGcompositeOperationState compositeOperation, NVGscissor* scissor, const NVGvertex* verts, int nverts);
void (*renderDelete)(void* uptr);
};
typedef struct NVGparams NVGparams;
// Constructor and destructor, called by the render back-end.
NVGcontext* nvgCreateInternal(NVGparams* params);
void nvgDeleteInternal(NVGcontext* ctx);
NVGparams* nvgInternalParams(NVGcontext* ctx);
// Debug function to dump cached path data.
void nvgDebugDumpPathCache(NVGcontext* ctx);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#define NVG_NOTUSED(v) for (;;) { (void)(1 ? (void)0 : ( (void)(v) ) ); break; }
#ifdef __cplusplus
}
#endif
#endif // NANOVG_H

1649
3rd/nanovg/src/nanovg_gl.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
//
// Copyright (c) 2009-2013 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef NANOVG_GL_UTILS_H
#define NANOVG_GL_UTILS_H
struct NVGLUframebuffer {
NVGcontext* ctx;
GLuint fbo;
GLuint rbo;
GLuint texture;
int image;
};
typedef struct NVGLUframebuffer NVGLUframebuffer;
// Helper function to create GL frame buffer to render to.
void nvgluBindFramebuffer(NVGLUframebuffer* fb);
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags);
void nvgluDeleteFramebuffer(NVGLUframebuffer* fb);
#endif // NANOVG_GL_UTILS_H
#ifdef NANOVG_GL_IMPLEMENTATION
#if defined(NANOVG_GL3) || defined(NANOVG_GLES2) || defined(NANOVG_GLES3)
// FBO is core in OpenGL 3>.
# define NANOVG_FBO_VALID 1
#elif defined(NANOVG_GL2)
// On OS X including glext defines FBO on GL2 too.
# ifdef __APPLE__
# include <OpenGL/glext.h>
# define NANOVG_FBO_VALID 1
# endif
#endif
static GLint defaultFBO = -1;
NVGLUframebuffer* nvgluCreateFramebuffer(NVGcontext* ctx, int w, int h, int imageFlags)
{
#ifdef NANOVG_FBO_VALID
GLint defaultFBO;
GLint defaultRBO;
NVGLUframebuffer* fb = NULL;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glGetIntegerv(GL_RENDERBUFFER_BINDING, &defaultRBO);
fb = (NVGLUframebuffer*)malloc(sizeof(NVGLUframebuffer));
if (fb == NULL) goto error;
memset(fb, 0, sizeof(NVGLUframebuffer));
fb->image = nvgCreateImageRGBA(ctx, w, h, imageFlags | NVG_IMAGE_FLIPY | NVG_IMAGE_PREMULTIPLIED, NULL);
#if defined NANOVG_GL2
fb->texture = nvglImageHandleGL2(ctx, fb->image);
#elif defined NANOVG_GL3
fb->texture = nvglImageHandleGL3(ctx, fb->image);
#elif defined NANOVG_GLES2
fb->texture = nvglImageHandleGLES2(ctx, fb->image);
#elif defined NANOVG_GLES3
fb->texture = nvglImageHandleGLES3(ctx, fb->image);
#endif
fb->ctx = ctx;
// frame buffer object
glGenFramebuffers(1, &fb->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
// render buffer object
glGenRenderbuffers(1, &fb->rbo);
glBindRenderbuffer(GL_RENDERBUFFER, fb->rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, w, h);
// combine all
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
#ifdef GL_DEPTH24_STENCIL8
// If GL_STENCIL_INDEX8 is not supported, try GL_DEPTH24_STENCIL8 as a fallback.
// Some graphics cards require a depth buffer along with a stencil.
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb->texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->rbo);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
#endif // GL_DEPTH24_STENCIL8
goto error;
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
return fb;
error:
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glBindRenderbuffer(GL_RENDERBUFFER, defaultRBO);
nvgluDeleteFramebuffer(fb);
return NULL;
#else
NVG_NOTUSED(ctx);
NVG_NOTUSED(w);
NVG_NOTUSED(h);
NVG_NOTUSED(imageFlags);
return NULL;
#endif
}
void nvgluBindFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (defaultFBO == -1) glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glBindFramebuffer(GL_FRAMEBUFFER, fb != NULL ? fb->fbo : defaultFBO);
#else
NVG_NOTUSED(fb);
#endif
}
void nvgluDeleteFramebuffer(NVGLUframebuffer* fb)
{
#ifdef NANOVG_FBO_VALID
if (fb == NULL) return;
if (fb->fbo != 0)
glDeleteFramebuffers(1, &fb->fbo);
if (fb->rbo != 0)
glDeleteRenderbuffers(1, &fb->rbo);
if (fb->image >= 0)
nvgDeleteImage(fb->ctx, fb->image);
fb->ctx = NULL;
fb->fbo = 0;
fb->rbo = 0;
fb->texture = 0;
fb->image = -1;
free(fb);
#else
NVG_NOTUSED(fb);
#endif
}
#endif // NANOVG_GL_IMPLEMENTATION

6614
3rd/nanovg/src/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1549
3rd/nanovg/src/tags Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
import os
import platform
OS_NAME=platform.system()
LFTK_ROOT = os.path.normpath(os.getcwd())
LFTK_SRC = os.path.join(LFTK_ROOT, 'src')
LFTK_3RD_ROOT = os.path.join(LFTK_ROOT, '3rd')
@ -8,39 +10,67 @@ GTEST_ROOT = os.path.join(LFTK_ROOT, '3rd/gtest/googletest')
BIN_DIR=os.path.join(LFTK_ROOT, 'bin')
LIB_DIR=os.path.join(LFTK_ROOT, 'lib')
if os.name == 'posix':
OS_FLAGS='-g -Wall -DLUA_USE_POSIX -DLUA_COMPAT_MODULE -DHAS_STD_MALLOC'
OS_LINKFLAGS=''
OS_LIBPATH=[]
OS_CPPPATH=[]
OS_LIBS=['stdc++', 'pthread', 'm']
OS_SUBSYSTEM_CONSOLE=''
OS_SUBSYSTEM_WINDOWS=''
elif os.name == 'nt':
OS_FLAGS='-DWIN32 -DWINDOWS /EHsc -D_CONSOLE /DEBUG /INCREMENTA -DUNICODE -D_UNICODE -DLUA_COMPAT_MODULE'
OS_LINKFLAGS='/MACHINE:X64 '
OS_LIBPATH=[LFTK_3RD_ROOT+'/SDL2-2.0.7/lib/x64']
OS_CPPPATH=[LFTK_3RD_ROOT+'/SDL2-2.0.7/']
OS_LIBS=[]
OS_SUBSYSTEM_CONSOLE='/SUBSYSTEM:CONSOLE '
OS_SUBSYSTEM_WINDOWS='/SUBSYSTEM:WINDOWS '
if OS_NAME == 'Windows':
LCD='SDL'
else:
LCD='NANOVG'
os.environ['LCD'] = LCD
os.environ['BIN_DIR'] = BIN_DIR;
os.environ['LIB_DIR'] = LIB_DIR;
os.environ['LFTK_ROOT'] = LFTK_ROOT;
os.environ['GTEST_ROOT'] = GTEST_ROOT;
CCFLAGS=OS_FLAGS + ' -DLFTK_ROOT=\\\"'+LFTK_ROOT+'\\\" -DWITH_STB_IMAGE -DWITH_STB_FONT -DSDL2'
COMMON_CCFLAGS=' -DLFTK_ROOT=\\\"'+LFTK_ROOT+'\\\" -DLUA_COMPAT_MODULE -DHAS_STD_MALLOC -DSTBTT_STATIC -DSTB_IMAGE_STATIC'
if LCD == 'NANOVG':
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -DWITH_NANOVG -DNANOVG_GL2'
else:
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -DWITH_STB_IMAGE -DWITH_STB_FONT -DSDL2'
OS_LIBPATH=[]
OS_CPPPATH=[]
OS_FLAGS='-g -Wall'
OS_SUBSYSTEM_CONSOLE=''
OS_SUBSYSTEM_WINDOWS=''
OS_LINKFLAGS=''
OS_LIBS=['SDL2', 'stdc++', 'pthread', 'm']
if OS_NAME == 'Darwin':
OS_LINKFLAGS='-framework OpenGL'
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -DLUA_USE_POSIX '
print("Macos");
elif OS_NAME == 'Linux':
OS_LIBS = ['GL'] + OS_LIBS
COMMON_CCFLAGS = COMMON_CCFLAGS + ' -DLUA_USE_POSIX '
print("Linux");
elif OS_NAME == 'Windows':
OS_LIBS=[]
OS_FLAGS='-DWIN32 -DWINDOWS /EHsc -D_CONSOLE /DEBUG /INCREMENTA -DUNICODE -D_UNICODE'
OS_LINKFLAGS='/MACHINE:X64 '
OS_LIBPATH=[LFTK_3RD_ROOT+'/SDL2-2.0.7/lib/x64']
OS_CPPPATH=[LFTK_3RD_ROOT+'/SDL2-2.0.7/']
OS_SUBSYSTEM_CONSOLE='/SUBSYSTEM:CONSOLE '
OS_SUBSYSTEM_WINDOWS='/SUBSYSTEM:WINDOWS '
LIBS=['lftk', 'agg', 'nanovg'] + OS_LIBS
CCFLAGS=OS_FLAGS + COMMON_CCFLAGS
CPPPATH=[LFTK_ROOT, LFTK_SRC, LFTK_3RD_ROOT, os.path.join(LFTK_3RD_ROOT, 'nanovg/src'), os.path.join(LFTK_3RD_ROOT, 'agg-2.5/include'), LFTK_TOOLS_ROOT] + OS_CPPPATH
DefaultEnvironment(CCFLAGS = CCFLAGS,
CPPPATH = [LFTK_ROOT, LFTK_SRC, LFTK_3RD_ROOT, os.path.join(LFTK_3RD_ROOT, 'agg-2.5/include'), LFTK_TOOLS_ROOT] + OS_CPPPATH,
LIBS=['lftk', 'agg', 'SDL2'] + OS_LIBS,
CPPPATH = CPPPATH,
LIBS=LIBS,
LINKFLAGS=OS_LINKFLAGS,
OS_SUBSYSTEM_CONSOLE=OS_SUBSYSTEM_CONSOLE,
OS_SUBSYSTEM_WINDOWS=OS_SUBSYSTEM_WINDOWS,
LIBPATH=[os.path.join(LFTK_ROOT, 'lib')] + OS_LIBPATH)
SConscript([
'3rd/agg-2.5/SConscript',
'3rd/nanovg/SConscript',
'src/SConscript',
'tools/common/SConscript',
'tools/theme_gen/SConscript',
@ -53,6 +83,5 @@ SConscript([
'demos/SConscript',
'tests/SConscript',
'3rd/lua/SConscript',
'3rd/agg-2.5/SConscript',
'lua/SConscript'
])

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~确定取消
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~确定取消

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -157,4 +157,4 @@ const unsigned char image_slider_drag[] = {
0x51,0x51,0x51,0xc0,0x51,0x51,0x51,0xff,0x51,0x51,0x51,0xff,0x51,0x51,0x51,0xff,0x51,0x51,0x51,0xff,
0x51,0x51,0x51,0xd0,0x50,0x50,0x50,0xa0,0x50,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};/*3176*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x7f,0x00,0x00,};/*3176*/

View File

@ -36,4 +36,4 @@ const unsigned char ui_window1[] = {
0x00,0x64,0x69,0x61,0x6c,0x6f,0x67,0x00,0x74,0x65,0x78,0x74,0x00,0x44,0x69,0x61,0x6c,0x6f,0x67,0x00,
0x00,0x00,0x01,0x00,0x0a,0x00,0x03,0x00,0x01,0x00,0x0a,0x00,0x00,0x00,0x04,0x01,0x00,0x00,0x28,0x00,
0x00,0x00,0x1e,0x00,0x00,0x00,0x6e,0x61,0x6d,0x65,0x00,0x64,0x69,0x61,0x6c,0x6f,0x67,0x32,0x00,0x74,
0x65,0x78,0x74,0x00,0x44,0x69,0x61,0x6c,0x6f,0x67,0x32,0x00,0x00,0x00,0x00,0x79,0xff,0x7f,0x00,};/*759*/
0x65,0x78,0x74,0x00,0x44,0x69,0x61,0x6c,0x6f,0x67,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};/*759*/

View File

@ -2,6 +2,7 @@
#include "base/resource_manager.h"
#include "res/src/fonts/ap.data"
#include "res/src/fonts/default.data"
#include "res/src/fonts/default_ttf.data"
#include "res/src/images/bricks.data"
#include "res/src/images/checked.data"
#include "res/src/images/dialog_title.data"
@ -41,6 +42,7 @@ ret_t resource_init() {
resource_manager_add(font_ap);
resource_manager_add(font_default);
resource_manager_add(font_default_ttf);
resource_manager_add(image_bricks);
resource_manager_add(image_checked);
resource_manager_add(image_dialog_title);

View File

@ -1,15 +1,21 @@
import os
import copy
BIN_DIR=os.environ['BIN_DIR'];
LIB_DIR=os.environ['LIB_DIR'];
sources=Glob('base/*.c') +\
Glob('font/*.c') + \
Glob('image_loader/*.c') + \
Glob('ui_loader/*.c') + \
Glob('xml/*.c') + \
Glob('vgcanvas/vgcanvas_agg.cpp') + \
['lcd/lcd_sdl2.c', 'lcd/lcd_mem_rgba.c', 'main_loop/main_loop_sdl2.c', 'platforms/platform_default.c', 'lftk.c']
Glob('font/*.c') + \
Glob('image_loader/*.c') + \
['platforms/platform_default.c', 'lftk.c'];
if os.environ['LCD'] == 'NANOVG':
sources += ['lcd/lcd_nanovg.c', 'main_loop/main_loop_nanovg.c'];
else:
sources += Glob('vgcanvas/vgcanvas_agg.cpp')
sources += ['lcd/lcd_sdl2.c', 'lcd/lcd_mem_rgba.c', 'main_loop/main_loop_sdl2.c']
env=DefaultEnvironment().Clone()
env.Library(os.path.join(LIB_DIR, 'lftk'), sources)

View File

@ -63,10 +63,18 @@ wh_t canvas_get_height(canvas_t* c) {
ret_t canvas_set_clip_rect(canvas_t* c, rect_t* r) {
return_value_if_fail(c != NULL, RET_BAD_PARAMS);
if (r) {
c->clip_left = r->x;
c->clip_top = r->y;
c->clip_right = r->x + r->w;
c->clip_bottom = r->y + r->h;
if (c->lcd->set_clip_rect != NULL) {
c->clip_left = 0;
c->clip_top = 0;
c->clip_right = c->lcd->w;
c->clip_bottom = c->lcd->h;
lcd_set_clip_rect(c->lcd, r);
} else {
c->clip_left = r->x;
c->clip_top = r->y;
c->clip_right = r->x + r->w;
c->clip_bottom = r->y + r->h;
}
} else {
c->clip_left = 0;
c->clip_top = 0;
@ -80,7 +88,8 @@ ret_t canvas_set_clip_rect(canvas_t* c, rect_t* r) {
ret_t canvas_set_fill_color(canvas_t* c, color_t color) {
return_value_if_fail(c != NULL, RET_BAD_PARAMS);
lcd_set_fill_color(c->lcd, color);;
lcd_set_fill_color(c->lcd, color);
;
return RET_OK;
}
@ -110,16 +119,21 @@ ret_t canvas_set_global_alpha(canvas_t* c, uint8_t alpha) {
}
ret_t canvas_set_font(canvas_t* c, const char* name, uint16_t size) {
return_value_if_fail(c != NULL, RET_BAD_PARAMS);
return_value_if_fail(c != NULL && c->lcd != NULL, RET_BAD_PARAMS);
c->font_name = name;
c->font_size = size;
c->font = font_manager_find(c->font_manager, name, size);
if (c->lcd->set_font_name != NULL) {
lcd_set_font_name(c->lcd, name);
lcd_set_font_size(c->lcd, size);
} else {
c->font = font_manager_find(c->font_manager, name, size);
}
return RET_OK;
}
wh_t canvas_measure_text(canvas_t* c, wchar_t* str, int32_t nr) {
static wh_t canvas_measure_text_default(canvas_t* c, wchar_t* str, int32_t nr) {
glyph_t g;
wh_t w = 0;
int32_t i = 0;
@ -141,6 +155,16 @@ wh_t canvas_measure_text(canvas_t* c, wchar_t* str, int32_t nr) {
return w;
}
wh_t canvas_measure_text(canvas_t* c, wchar_t* str, int32_t nr) {
return_value_if_fail(c != NULL && c->lcd != NULL && str != NULL, 0);
if (c->lcd->measure_text) {
return lcd_measure_text(c->lcd, str, nr);
} else {
return canvas_measure_text_default(c, str, nr);
}
}
ret_t canvas_begin_frame(canvas_t* c, rect_t* dirty_rect) {
return_value_if_fail(c != NULL && dirty_rect != NULL, RET_BAD_PARAMS);
@ -310,12 +334,16 @@ ret_t canvas_fill_rect(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h) {
}
static ret_t canvas_stroke_rect_impl(canvas_t* c, xy_t x, xy_t y, wh_t w, wh_t h) {
return_value_if_fail(c != NULL && w > 0 && h > 0, RET_BAD_PARAMS);
return_value_if_fail(c != NULL && c->lcd != NULL && w > 0 && h > 0, RET_BAD_PARAMS);
canvas_draw_hline_impl(c, x, y, w);
canvas_draw_hline_impl(c, x, y + h - 1, w);
canvas_draw_vline_impl(c, x, y, h);
canvas_draw_vline_impl(c, x + w - 1, y, h);
if (c->lcd->stroke_rect != NULL) {
lcd_stroke_rect(c->lcd, x, y, w, h);
} else {
canvas_draw_hline_impl(c, x, y, w);
canvas_draw_hline_impl(c, x, y + h - 1, w);
canvas_draw_vline_impl(c, x, y, h);
canvas_draw_vline_impl(c, x + w - 1, y, h);
}
return RET_OK;
}
@ -404,9 +432,12 @@ static ret_t canvas_draw_text_impl(canvas_t* c, wchar_t* str, int32_t nr, xy_t x
}
ret_t canvas_draw_text(canvas_t* c, wchar_t* str, int32_t nr, xy_t x, xy_t y) {
return_value_if_fail(c != NULL && str != NULL, RET_BAD_PARAMS);
return canvas_draw_text_impl(c, str, nr, c->ox + x, c->oy + y);
return_value_if_fail(c != NULL && c->lcd != NULL && str != NULL, RET_BAD_PARAMS);
if (c->lcd->draw_text != NULL) {
return lcd_draw_text(c->lcd, str, nr, c->ox + x, c->oy + y);
} else {
return canvas_draw_text_impl(c, str, nr, c->ox + x, c->oy + y);
}
}
static ret_t canvas_do_draw_image(canvas_t* c, bitmap_t* img, rect_t* s, rect_t* d) {

View File

@ -123,7 +123,7 @@ widget_t* dialog_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
widget_move_resize(widget, x, y, w, h);
return_value_if_fail(window_manager_add_child(parent, widget) == RET_OK, NULL);
dialog->margin = 1;
dialog->margin = 0;
dialog->title = dialog_title_create(widget, 0, 0, 0, 0);
dialog->client = dialog_client_create(widget, 0, 0, 0, 0);
dialog_relayout_children(widget);

View File

@ -19,8 +19,8 @@
*
*/
#include "base/font_manager.h"
#include "base/mem.h"
#include "base/font_manager.h"
font_manager_t* font_manager_create() {
font_manager_t* fm = MEM_ZALLOC(font_manager_t);

View File

@ -43,8 +43,6 @@ font_t* font_manager_find(font_manager_t* fm, const char* name, uint16_t size);
ret_t font_manager_deinit(font_manager_t* fm);
ret_t font_manager_destroy(font_manager_t* fm);
#define STR_DEFAULT_FONT "default"
END_C_DECLS
#endif /*LFTK_FONT_MANAGER_H*/

View File

@ -27,11 +27,17 @@ ret_t lcd_begin_frame(lcd_t* lcd, rect_t* dirty_rect) {
return lcd->begin_frame(lcd, dirty_rect);
}
ret_t lcd_set_clip_rect(lcd_t* lcd, rect_t* rect) {
return_value_if_fail(lcd != NULL && lcd->set_clip_rect != NULL, RET_BAD_PARAMS);
return lcd->set_clip_rect(lcd, rect);
}
ret_t lcd_set_global_alpha(lcd_t* lcd, uint8_t alpha) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->global_alpha = alpha;
if(lcd->set_global_alpha != NULL) {
if (lcd->set_global_alpha != NULL) {
lcd->set_global_alpha(lcd, alpha);
}
@ -42,7 +48,7 @@ ret_t lcd_set_text_color(lcd_t* lcd, color_t color) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->text_color = color;
if(lcd->set_text_color != NULL) {
if (lcd->set_text_color != NULL) {
lcd->set_text_color(lcd, color);
}
@ -51,9 +57,9 @@ ret_t lcd_set_text_color(lcd_t* lcd, color_t color) {
ret_t lcd_set_stroke_color(lcd_t* lcd, color_t color) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->stroke_color = color;
if(lcd->set_stroke_color != NULL) {
if (lcd->set_stroke_color != NULL) {
lcd->set_stroke_color(lcd, color);
}
@ -62,12 +68,34 @@ ret_t lcd_set_stroke_color(lcd_t* lcd, color_t color) {
ret_t lcd_set_fill_color(lcd_t* lcd, color_t color) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->fill_color = color;
if(lcd->set_fill_color != NULL) {
if (lcd->set_fill_color != NULL) {
lcd->set_fill_color(lcd, color);
}
return RET_OK;
}
ret_t lcd_set_font_name(lcd_t* lcd, const char* name) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->font_name = name;
if (lcd->set_font_name != NULL) {
lcd->set_font_name(lcd, name);
}
return RET_OK;
}
ret_t lcd_set_font_size(lcd_t* lcd, uint32_t size) {
return_value_if_fail(lcd != NULL, RET_BAD_PARAMS);
lcd->font_size = size;
if (lcd->set_font_size != NULL) {
lcd->set_font_size(lcd, size);
}
return RET_OK;
}
@ -89,6 +117,12 @@ ret_t lcd_fill_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
return lcd->fill_rect(lcd, x, y, w, h);
}
ret_t lcd_stroke_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
return_value_if_fail(lcd != NULL && lcd->stroke_rect != NULL, RET_BAD_PARAMS);
return lcd->stroke_rect(lcd, x, y, w, h);
}
ret_t lcd_draw_points(lcd_t* lcd, point_t* points, uint32_t nr) {
return_value_if_fail(lcd != NULL && lcd->draw_points != NULL && points != NULL, RET_BAD_PARAMS);
@ -109,6 +143,18 @@ ret_t lcd_draw_glyph(lcd_t* lcd, glyph_t* glyph, rect_t* src, xy_t x, xy_t y) {
return lcd->draw_glyph(lcd, glyph, src, x, y);
}
wh_t lcd_measure_text(lcd_t* lcd, wchar_t* str, int32_t nr) {
return_value_if_fail(lcd != NULL && lcd->measure_text != NULL && str != NULL, 0);
return lcd->measure_text(lcd, str, nr);
}
ret_t lcd_draw_text(lcd_t* lcd, wchar_t* str, int32_t nr, xy_t x, xy_t y) {
return_value_if_fail(lcd != NULL && lcd->draw_text != NULL && str != NULL, 0);
return lcd->draw_text(lcd, str, nr, x, y);
}
ret_t lcd_end_frame(lcd_t* lcd) {
return_value_if_fail(lcd != NULL && lcd->end_frame != NULL, RET_BAD_PARAMS);

View File

@ -33,17 +33,25 @@ struct _lcd_t;
typedef struct _lcd_t lcd_t;
typedef ret_t (*lcd_begin_frame_t)(lcd_t* lcd, rect_t* dirty_rect);
typedef ret_t (*lcd_set_clip_rect_t)(lcd_t* lcd, rect_t* rect);
typedef ret_t (*lcd_set_global_alpha_t)(lcd_t* lcd, uint8_t alpha);
typedef ret_t (*lcd_set_text_color_t)(lcd_t* lcd, color_t color);
typedef ret_t (*lcd_set_stroke_color_t)(lcd_t* lcd, color_t color);
typedef ret_t (*lcd_set_fill_color_t)(lcd_t* lcd, color_t color);
typedef ret_t (*lcd_set_font_name_t)(lcd_t* lcd, const char* name);
typedef ret_t (*lcd_set_font_size_t)(lcd_t* lcd, uint32_t size);
typedef ret_t (*lcd_draw_vline_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t h);
typedef ret_t (*lcd_draw_hline_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t w);
typedef ret_t (*lcd_draw_points_t)(lcd_t* lcd, point_t* points, uint32_t nr);
typedef ret_t (*lcd_fill_rect_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
typedef ret_t (*lcd_stroke_rect_t)(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
typedef ret_t (*lcd_draw_glyph_t)(lcd_t* lcd, glyph_t* glyph, rect_t* src, xy_t x, xy_t y);
typedef wh_t (*lcd_measure_text_t)(lcd_t* lcd, wchar_t* str, int32_t nr);
typedef ret_t (*lcd_draw_text_t)(lcd_t* lcd, wchar_t* str, int32_t nr, xy_t x, xy_t y);
typedef ret_t (*lcd_draw_image_t)(lcd_t* lcd, bitmap_t* img, rect_t* src, rect_t* dst);
typedef vgcanvas_t* (*lcd_get_vgcanvas_t)(lcd_t* lcd);
@ -51,20 +59,26 @@ typedef ret_t (*lcd_end_frame_t)(lcd_t* lcd);
typedef ret_t (*lcd_destroy_t)(lcd_t* lcd);
/**
* @class lcd_t
* @class lcd_t
*
*/
struct _lcd_t {
lcd_begin_frame_t begin_frame;
lcd_set_clip_rect_t set_clip_rect;
lcd_set_global_alpha_t set_global_alpha;
lcd_set_text_color_t set_text_color;
lcd_set_stroke_color_t set_stroke_color;
lcd_set_fill_color_t set_fill_color;
lcd_set_font_name_t set_font_name;
lcd_set_font_size_t set_font_size;
lcd_draw_vline_t draw_vline;
lcd_draw_hline_t draw_hline;
lcd_fill_rect_t fill_rect;
lcd_stroke_rect_t stroke_rect;
lcd_draw_image_t draw_image;
lcd_draw_glyph_t draw_glyph;
lcd_draw_text_t draw_text;
lcd_measure_text_t measure_text;
lcd_draw_points_t draw_points;
lcd_end_frame_t end_frame;
lcd_get_vgcanvas_t get_vgcanvas;
@ -76,13 +90,13 @@ struct _lcd_t {
* @readonly
*
*/
wh_t w;
wh_t w;
/**
* @property {wh_t} height
* @readonly
*
*/
wh_t h;
wh_t h;
/**
* @property {uint8_t} global_alpha
* @readonly
@ -107,6 +121,19 @@ struct _lcd_t {
* 线
*/
color_t stroke_color;
/**
* @property {char*} font_name
* @readonly
*
*/
const char* font_name;
/**
* @property {uint32_t} font_size
* @readonly
*
*/
uint32_t font_size;
rect_t* dirty_rect;
};
@ -120,6 +147,16 @@ struct _lcd_t {
*/
ret_t lcd_begin_frame(lcd_t* lcd, rect_t* dirty_rect);
/**
* @method lcd_set_clip_rect
*
* @param {lcd_t*} lcd lcd对象
* @param {rect_t*} rect
*
* @return {ret_t} RET_OK表示成功
*/
ret_t lcd_set_clip_rect(lcd_t* lcd, rect_t* rect);
/**
* @method lcd_set_global_alpha
* alpha
@ -160,6 +197,26 @@ ret_t lcd_set_stroke_color(lcd_t* lcd, color_t color);
*/
ret_t lcd_set_fill_color(lcd_t* lcd, color_t color);
/**
* @method lcd_set_font_name
*
* @param {lcd_t*} lcd lcd对象
* @param {const char*} name
*
* @return {ret_t} RET_OK表示成功
*/
ret_t lcd_set_font_name(lcd_t* lcd, const char* name);
/**
* @method lcd_set_font_size
*
* @param {lcd_t*} lcd lcd对象
* @param {uint32_t} font_size
*
* @return {ret_t} RET_OK表示成功
*/
ret_t lcd_set_font_size(lcd_t* lcd, uint32_t font_size);
/**
* @method lcd_draw_vline
* 线
@ -208,9 +265,22 @@ ret_t lcd_draw_points(lcd_t* lcd, point_t* points, uint32_t nr);
*/
ret_t lcd_fill_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method lcd_stroke_rect
*
* @param {lcd_t*} lcd lcd对象
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
* @param {wh_t} w
* @param {wh_t} h
*
* @return {ret_t} RET_OK表示成功
*/
ret_t lcd_stroke_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
/**
* @method lcd_draw_glyph
*
* measure_text/draw_text则不需要实现本函数
* @param {lcd_t*} lcd lcd对象
* @param {glyph_t*} glyph
* @param {rect_t*} src
@ -221,11 +291,35 @@ ret_t lcd_fill_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h);
*/
ret_t lcd_draw_glyph(lcd_t* lcd, glyph_t* glyph, rect_t* src, xy_t x, xy_t y);
/**
* @method lcd_measure_text
*
* @param {lcd_t*} lcd lcd对象
* @param {wchar_t*} str
* @param {int32_t} nr
*
* @return {ret_t}
*/
wh_t lcd_measure_text(lcd_t* lcd, wchar_t* str, int32_t nr);
/**
* @method lcd_draw_text
*
* @param {lcd_t*} lcd lcd对象
* @param {wchar_t*} str
* @param {int32_t} nr
* @param {xy_t} x x坐标
* @param {xy_t} y y坐标
*
* @return {ret_t} RET_OK表示成功
*/
ret_t lcd_draw_text(lcd_t* lcd, wchar_t* str, int32_t nr, xy_t x, xy_t y);
/**
* @method lcd_draw_image
*
* @param {lcd_t*} lcd lcd对象
* @param {bitmap_t*} img
* @param {bitmap_t*} img
* @param {rect_t*} src
* @param {rect_t*} dst
*

View File

@ -22,6 +22,7 @@
#include "base/mem.h"
#include "base/utils.h"
#include "base/progress_bar.h"
#include "base/widget_vtable.h"
#include "base/image_manager.h"
static ret_t progress_bar_on_paint_self(widget_t* widget, canvas_t* c) {
@ -194,9 +195,12 @@ static ret_t progress_bar_set_prop(widget_t* widget, const char* name, const val
return RET_NOT_FOUND;
}
static const widget_vtable_t s_progress_bar_vtable = {.on_paint_self = progress_bar_on_paint_self,
.get_prop = progress_bar_get_prop,
.set_prop = progress_bar_set_prop};
static const widget_vtable_t s_progress_bar_vtable = {
.on_paint_self = progress_bar_on_paint_self,
.on_paint_background = widget_on_paint_background_null,
.on_paint_done = widget_on_paint_done_null,
.get_prop = progress_bar_get_prop,
.set_prop = progress_bar_set_prop};
widget_t* progress_bar_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
widget_t* widget = NULL;

View File

@ -23,6 +23,7 @@
#include "base/rect.h"
#include "base/utils.h"
#include "base/slider.h"
#include "base/widget_vtable.h"
#include "base/image_manager.h"
static ret_t slider_set_value_internal(widget_t* widget, uint16_t value, event_type_t etype);
@ -328,10 +329,13 @@ static ret_t slider_set_prop(widget_t* widget, const char* name, const value_t*
return RET_NOT_FOUND;
}
static const widget_vtable_t s_slider_vtable = {.on_event = slider_on_event,
.on_paint_self = slider_on_paint_self,
.get_prop = slider_get_prop,
.set_prop = slider_set_prop};
static const widget_vtable_t s_slider_vtable = {
.on_event = slider_on_event,
.on_paint_background = widget_on_paint_background_null,
.on_paint_self = slider_on_paint_self,
.on_paint_done = widget_on_paint_done_null,
.get_prop = slider_get_prop,
.set_prop = slider_set_prop};
widget_t* slider_create(widget_t* parent, xy_t x, xy_t y, wh_t w, wh_t h) {
widget_t* widget = NULL;

View File

@ -190,4 +190,10 @@ enum { NAME_LEN = 15 };
typedef float float_t;
#ifdef WITH_NANOVG
#define STR_DEFAULT_FONT "default_ttf"
#else
#define STR_DEFAULT_FONT "default"
#endif /*WITH_NANOVG*/
#endif /*TYPES_DEF_H*/

View File

@ -410,7 +410,7 @@ ret_t vgcanvas_reset(vgcanvas_t* vg);
/**
* @method vgcanvas_flush
* flush
* flush
* @param {vgcanvas_t*} vg vgcanvas对象
*
* @return {ret_t} RET_OK表示成功
@ -429,11 +429,12 @@ ret_t vgcanvas_flush(vgcanvas_t* vg);
*
* @return {ret_t} RET_OK表示成功
*/
ret_t vgcanvas_clear_rect(vgcanvas_t* vg, float_t x, float_t y, float_t w, float_t h, color_t color);
ret_t vgcanvas_clear_rect(vgcanvas_t* vg, float_t x, float_t y, float_t w, float_t h,
color_t color);
/**
* @method vgcanvas_rotate
* rotate
* rotate
* @param {vgcanvas_t*} vg vgcanvas对象
* @param {float_t} rad
*
@ -443,9 +444,9 @@ ret_t vgcanvas_rotate(vgcanvas_t* vg, float_t rad);
/**
* @method vgcanvas_scale
* scale
* scale
* @param {vgcanvas_t*} vg vgcanvas对象
* @param {float_t} x x方向缩放比例
* @param {float_t} x x方向缩放比例
* @param {float_t} y y方向缩放比例
*
* @return {ret_t} RET_OK表示成功
@ -454,9 +455,9 @@ ret_t vgcanvas_scale(vgcanvas_t* vg, float_t x, float_t y);
/**
* @method vgcanvas_translate
* scale
* scale
* @param {vgcanvas_t*} vg vgcanvas对象
* @param {float_t} x x方向偏移
* @param {float_t} x x方向偏移
* @param {float_t} y y方向偏移
*
* @return {ret_t} RET_OK表示成功
@ -476,7 +477,8 @@ ret_t vgcanvas_translate(vgcanvas_t* vg, float_t x, float_t y);
*
* @return {ret_t} RET_OK表示成功
*/
ret_t vgcanvas_transform(vgcanvas_t* vg, float_t a, float_t b, float_t c, float_t d, float_t e, float_t f);
ret_t vgcanvas_transform(vgcanvas_t* vg, float_t a, float_t b, float_t c, float_t d, float_t e,
float_t f);
/**
* @method vgcanvas_set_transform
@ -505,7 +507,7 @@ ret_t vgcanvas_fill(vgcanvas_t* vg);
/**
* @method vgcanvas_clip
* clip
* clip
* @param {vgcanvas_t*} vg vgcanvas对象
*
* @return {ret_t} RET_OK表示成功
@ -523,7 +525,7 @@ ret_t vgcanvas_stroke(vgcanvas_t* vg);
/**
* @method vgcanvas_set_font
* set font
* set font
* @param {vgcanvas_t*} vg vgcanvas对象
* @param {char*} font
*
@ -579,11 +581,11 @@ uint32_t vgcanvas_measure_text(vgcanvas_t* vg, const char* text);
* draw image
* @param {vgcanvas_t*} vg vgcanvas对象
* @param {bitmap_t*} img
* @param {float_t} sx sx
* @param {float_t} sx sx
* @param {float_t} sy sy
* @param {float_t} sw sw
* @param {float_t} sh sh
* @param {float_t} dx dx
* @param {float_t} dx dx
* @param {float_t} dy dy
* @param {float_t} dw dw
* @param {float_t} dh dh
@ -703,4 +705,3 @@ ret_t vgcanvas_destroy(vgcanvas_t* vg);
END_C_DECLS
#endif /*LFTK_VG_CANVAS_H*/

View File

@ -329,7 +329,7 @@ ret_t widget_off_by_func(widget_t* widget, event_type_t type, event_func_t on_ev
return emitter_off_by_func(widget->emitter, type, on_event, ctx);
}
ret_t widget_paint_helper(widget_t* widget, canvas_t* c, const char* icon, wstr_t* text) {
ret_t widget_draw_icon_text(widget_t* widget, canvas_t* c, const char* icon, wstr_t* text) {
xy_t x = 0;
xy_t y = 0;
wh_t w = 0;
@ -337,38 +337,16 @@ ret_t widget_paint_helper(widget_t* widget, canvas_t* c, const char* icon, wstr_
bitmap_t img;
style_t* style = &(widget->style);
color_t trans = color_init(0, 0, 0, 0);
const char* image_name = style_get_str(style, STYLE_ID_BG_IMAGE, NULL);
color_t bg = style_get_color(style, STYLE_ID_BG_COLOR, trans);
color_t bd = style_get_color(style, STYLE_ID_BORDER_COLOR, trans);
uint16_t font_size = style_get_int(style, STYLE_ID_FONT_SIZE, 20);
if (icon == NULL) {
icon = style_get_str(style, STYLE_ID_ICON, NULL);
}
if (bg.rgba.a) {
canvas_set_fill_color(c, bg);
canvas_fill_rect(c, 0, 0, widget->w, widget->h);
}
if (bd.rgba.a) {
canvas_set_stroke_color(c, bd);
canvas_stroke_rect(c, 0, 0, widget->w, widget->h);
}
if (image_name != NULL) {
if (image_manager_load(default_im(), image_name, &img) == RET_OK) {
rect_init(dst, 0, 0, widget->w, widget->h);
image_draw_type_t draw_type =
(image_draw_type_t)style_get_int(style, STYLE_ID_BG_IMAGE_DRAW_TYPE, IMAGE_DRAW_CENTER);
canvas_draw_image_ex(c, &img, draw_type, &dst);
}
}
if (text == NULL) {
text = &(widget->text);
}
if (icon == NULL) {
icon = style_get_str(style, STYLE_ID_ICON, NULL);
}
if (text != NULL && text->size > 0) {
color_t tc = style_get_color(style, STYLE_ID_TEXT_COLOR, trans);
const char* font_name = style_get_str(style, STYLE_ID_FONT_NAME, NULL);
@ -435,6 +413,50 @@ ret_t widget_paint_helper(widget_t* widget, canvas_t* c, const char* icon, wstr_
return RET_OK;
}
ret_t widget_draw_background(widget_t* widget, canvas_t* c) {
rect_t dst;
bitmap_t img;
style_t* style = &(widget->style);
color_t trans = color_init(0, 0, 0, 0);
const char* image_name = style_get_str(style, STYLE_ID_BG_IMAGE, NULL);
color_t bg = style_get_color(style, STYLE_ID_BG_COLOR, trans);
if (bg.rgba.a) {
canvas_set_fill_color(c, bg);
canvas_fill_rect(c, 0, 0, widget->w, widget->h);
}
if (image_name != NULL) {
if (image_manager_load(default_im(), image_name, &img) == RET_OK) {
rect_init(dst, 0, 0, widget->w, widget->h);
image_draw_type_t draw_type =
(image_draw_type_t)style_get_int(style, STYLE_ID_BG_IMAGE_DRAW_TYPE, IMAGE_DRAW_CENTER);
canvas_draw_image_ex(c, &img, draw_type, &dst);
}
}
return RET_OK;
}
ret_t widget_draw_border(widget_t* widget, canvas_t* c) {
style_t* style = &(widget->style);
color_t trans = color_init(0, 0, 0, 0);
color_t bd = style_get_color(style, STYLE_ID_BORDER_COLOR, trans);
if (bd.rgba.a) {
canvas_set_stroke_color(c, bd);
canvas_stroke_rect(c, 0, 0, widget->w, widget->h);
}
return RET_OK;
}
ret_t widget_paint_helper(widget_t* widget, canvas_t* c, const char* icon, wstr_t* text) {
widget_draw_icon_text(widget, c, icon, text);
return RET_OK;
}
ret_t widget_paint(widget_t* widget, canvas_t* c) {
return_value_if_fail(widget != NULL && c != NULL, RET_BAD_PARAMS);
@ -450,12 +472,16 @@ ret_t widget_paint(widget_t* widget, canvas_t* c) {
canvas_fill_rect(c, 0, 0, widget->w, widget->h);
}
widget_on_paint_background(widget, c);
widget_on_paint_self(widget, c);
}
#else
widget_on_paint_background(widget, c);
widget_on_paint_self(widget, c);
#endif
widget_on_paint_children(widget, c);
widget_on_paint_done(widget, c);
canvas_untranslate(c, widget->x, widget->y);
widget->dirty = FALSE;
@ -539,6 +565,22 @@ ret_t widget_get_prop(widget_t* widget, const char* name, value_t* v) {
return ret;
}
ret_t widget_on_paint_background(widget_t* widget, canvas_t* c) {
ret_t ret = RET_OK;
return_value_if_fail(widget != NULL && c != NULL, RET_BAD_PARAMS);
return_value_if_fail(widget->vt != NULL, RET_BAD_PARAMS);
if (widget->vt->on_paint_background) {
ret = widget->vt->on_paint_background(widget, c);
} else {
if (widget->style.data) {
widget_draw_background(widget, c);
}
}
return ret;
}
ret_t widget_on_paint_self(widget_t* widget, canvas_t* c) {
ret_t ret = RET_OK;
return_value_if_fail(widget != NULL && c != NULL, RET_BAD_PARAMS);
@ -572,6 +614,22 @@ ret_t widget_on_paint_children(widget_t* widget, canvas_t* c) {
return ret;
}
ret_t widget_on_paint_done(widget_t* widget, canvas_t* c) {
ret_t ret = RET_OK;
return_value_if_fail(widget != NULL && c != NULL, RET_BAD_PARAMS);
return_value_if_fail(widget->vt != NULL, RET_BAD_PARAMS);
if (widget->vt->on_paint_done) {
ret = widget->vt->on_paint_done(widget, c);
} else {
if (widget->style.data) {
ret = widget_draw_border(widget, c);
}
}
return ret;
}
ret_t widget_on_keydown(widget_t* widget, key_event_t* e) {
ret_t ret = RET_OK;
return_value_if_fail(widget != NULL && e != NULL, RET_BAD_PARAMS);

View File

@ -212,8 +212,10 @@ typedef struct _widget_t widget_t;
typedef ret_t (*widget_invalidate_t)(widget_t* widget, rect_t* r);
typedef ret_t (*widget_on_event_t)(widget_t* widget, event_t* e);
typedef ret_t (*widget_on_paint_background_t)(widget_t* widget, canvas_t* c);
typedef ret_t (*widget_on_paint_self_t)(widget_t* widget, canvas_t* c);
typedef ret_t (*widget_on_paint_children_t)(widget_t* widget, canvas_t* c);
typedef ret_t (*widget_on_paint_done_t)(widget_t* widget, canvas_t* c);
typedef ret_t (*widget_on_keydown_t)(widget_t* widget, key_event_t* e);
typedef ret_t (*widget_on_keyup_t)(widget_t* widget, key_event_t* e);
typedef ret_t (*widget_on_click_t)(widget_t* widget, pointer_event_t* e);
@ -233,8 +235,10 @@ typedef struct _widget_vtable_t {
widget_on_click_t on_click;
widget_on_keyup_t on_keyup;
widget_on_keydown_t on_keydown;
widget_on_paint_background_t on_paint_background;
widget_on_paint_self_t on_paint_self;
widget_on_paint_children_t on_paint_children;
widget_on_paint_done_t on_paint_done;
widget_on_pointer_down_t on_pointer_down;
widget_on_pointer_move_t on_pointer_move;
widget_on_pointer_up_t on_pointer_up;
@ -736,9 +740,6 @@ ret_t widget_paint(widget_t* widget, canvas_t* c);
*/
ret_t widget_dispatch(widget_t* widget, event_t* e);
ret_t widget_on_paint_self(widget_t* widget, canvas_t* c);
ret_t widget_on_paint_children(widget_t* widget, canvas_t* c);
/**
* @method widget_get_prop
*
@ -761,14 +762,6 @@ ret_t widget_get_prop(widget_t* widget, const char* name, value_t* v);
*/
ret_t widget_set_prop(widget_t* widget, const char* name, const value_t* v);
ret_t widget_on_paint(widget_t* widget, canvas_t* c);
ret_t widget_on_keydown(widget_t* widget, key_event_t* e);
ret_t widget_on_keyup(widget_t* widget, key_event_t* e);
ret_t widget_on_click(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_down(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_move(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_up(widget_t* widget, pointer_event_t* e);
/**
* @method widget_grab
*
@ -789,6 +782,19 @@ ret_t widget_grab(widget_t* widget, widget_t* child);
*/
ret_t widget_ungrab(widget_t* widget, widget_t* child);
/*虚函数的包装*/
ret_t widget_on_paint(widget_t* widget, canvas_t* c);
ret_t widget_on_keydown(widget_t* widget, key_event_t* e);
ret_t widget_on_keyup(widget_t* widget, key_event_t* e);
ret_t widget_on_click(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_down(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_move(widget_t* widget, pointer_event_t* e);
ret_t widget_on_pointer_up(widget_t* widget, pointer_event_t* e);
ret_t widget_on_paint_background(widget_t* widget, canvas_t* c);
ret_t widget_on_paint_self(widget_t* widget, canvas_t* c);
ret_t widget_on_paint_children(widget_t* widget, canvas_t* c);
ret_t widget_on_paint_done(widget_t* widget, canvas_t* c);
/**
* @method widget_destroy
*

View File

@ -164,6 +164,18 @@ ret_t widget_destroy_default(widget_t* widget) {
return RET_OK;
}
ret_t widget_on_paint_background_null(widget_t* widget, canvas_t* c) {
(void)widget;
(void)c;
return RET_OK;
}
ret_t widget_on_paint_done_null(widget_t* widget, canvas_t* c) {
(void)widget;
(void)c;
return RET_OK;
}
static const widget_vtable_t s_vtable = {.invalidate = widget_invalidate_default,
.on_event = widget_on_event_default,
.on_paint_self = widget_on_paint_self_default,

View File

@ -45,6 +45,9 @@ ret_t widget_grab_default(widget_t* widget, widget_t* child);
ret_t widget_ungrab_default(widget_t* widget, widget_t* child);
ret_t widget_destroy_default(widget_t* widget);
ret_t widget_on_paint_background_null(widget_t* widget, canvas_t* c);
ret_t widget_on_paint_done_null(widget_t* widget, canvas_t* c);
END_C_DECLS
#endif /*LFTK_WIDGET_VTABLE_H*/

View File

@ -19,10 +19,10 @@
*
*/
#define STB_TRUETYPE_IMPLEMENTATION
#include "base/mem.h"
#include "font/font_stb.h"
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb/stb_truetype.h"
typedef struct _font_stb_t {

View File

@ -21,9 +21,9 @@
#define STB_IMAGE_IMPLEMENTATION
#include "image_loader/image_loader_stb.h"
#include "base/mem.h"
#include "stb/stb_image.h"
#include "image_loader/image_loader_stb.h"
static ret_t image_stb_destroy(bitmap_t* image) {
stbi_image_free((uint8_t*)(image->data));

341
src/lcd/lcd_nanovg.c Normal file
View File

@ -0,0 +1,341 @@
/**
* File: lcd.c
* Author: Li XianJing <xianjimli@hotmail.com>
* Brief: lcd interface
*
* Copyright (c) 2018 - 2018 Li XianJing <xianjimli@hotmail.com>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-04-11 Li XianJing <xianjimli@hotmail.com> created
*
*/
#define GL_GLEXT_PROTOTYPES
#define NANOVG_GL2_IMPLEMENTATION
#include "base/lcd.h"
#include "base/utf8.h"
#include "lcd/lcd_nanovg.h"
#include "base/resource_manager.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_opengl_glext.h>
#include "nanovg.h"
#include "nanovg_gl.h"
#define MAX_IMAGE_NR 256
typedef struct _lcd_nanovg_t {
lcd_t base;
NVGcontext* vg;
SDL_Window* sdl_window;
rect_t dirty_rect;
int font_id;
float ratio;
const uint8_t* images[MAX_IMAGE_NR];
} lcd_nanovg_t;
static ret_t lcd_nanovg_set_font_name(lcd_t* lcd, const char* name) {
lcd_nanovg_t* nano = (lcd_nanovg_t*)lcd;
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
int font_id = nvgFindFont(vg, name);
if (name == NULL) {
name = STR_DEFAULT_FONT;
}
if (font_id < 0) {
const resource_info_t* r = resource_manager_ref(RESOURCE_TYPE_FONT, name);
if (r == NULL || r->subtype != RESOURCE_TYPE_FONT_TTF) {
name = "default_ttf";
r = resource_manager_ref(RESOURCE_TYPE_FONT, name);
}
if (r != NULL && r->subtype == RESOURCE_TYPE_FONT_TTF) {
nano->font_id = nvgCreateFontMem(vg, name, (unsigned char*)r->data, r->size, 0);
}
} else {
nano->font_id = font_id;
}
lcd->font_name = name;
return RET_OK;
}
static ret_t lcd_nanovg_set_font_size(lcd_t* lcd, uint32_t size) { return RET_OK; }
static ret_t lcd_nanovg_sync_fill_color(lcd_t* lcd, NVGcontext* vg) {
color_t color = lcd->fill_color;
nvgFillColor(vg, nvgRGBA(color.rgba.r, color.rgba.g, color.rgba.b, color.rgba.a));
return RET_OK;
}
static ret_t lcd_nanovg_sync_text_color(lcd_t* lcd, NVGcontext* vg) {
color_t color = lcd->text_color;
nvgFillColor(vg, nvgRGBA(color.rgba.r, color.rgba.g, color.rgba.b, color.rgba.a));
return RET_OK;
}
static ret_t lcd_nanovg_sync_stroke_color(lcd_t* lcd, NVGcontext* vg) {
color_t color = lcd->stroke_color;
lcd_nanovg_t* nano = (lcd_nanovg_t*)lcd;
nvgStrokeWidth(vg, 1);
nvgStrokeColor(vg, nvgRGBA(color.rgba.r, color.rgba.g, color.rgba.b, color.rgba.a));
return RET_OK;
}
static ret_t lcd_nanovg_begin_frame(lcd_t* lcd, rect_t* dirty_rect) {
int ww = 0;
int wh = 0;
int fw = 0;
int fh = 0;
lcd_nanovg_t* nano = (lcd_nanovg_t*)lcd;
NVGcontext* vg = nano->vg;
SDL_Window* sdl_window = nano->sdl_window;
if (dirty_rect) {
nano->dirty_rect = *dirty_rect;
}
SDL_GetWindowSize(sdl_window, &ww, &wh);
SDL_GL_GetDrawableSize(sdl_window, &fw, &fh);
nano->ratio = (float)fw / (float)ww;
glViewport(0, 0, fw, fh);
glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
nvgBeginFrame(vg, ww, wh, nano->ratio);
return RET_OK;
}
static ret_t lcd_nanovg_set_clip_rect(lcd_t* lcd, rect_t* rect) { return RET_OK; }
static ret_t lcd_nanovg_set_global_alpha(lcd_t* lcd, uint8_t alpha) {
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
nvgGlobalAlpha(vg, (float)alpha / 255.0);
return RET_OK;
}
static ret_t lcd_nanovg_draw_vline(lcd_t* lcd, xy_t x, xy_t y, wh_t h) {
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
lcd_nanovg_sync_stroke_color(lcd, vg);
nvgBeginPath(vg);
nvgMoveTo(vg, x, y);
nvgLineTo(vg, x, y + h);
nvgStroke(vg);
return RET_OK;
}
static ret_t lcd_nanovg_draw_hline(lcd_t* lcd, xy_t x, xy_t y, wh_t w) {
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
lcd_nanovg_sync_stroke_color(lcd, vg);
nvgBeginPath(vg);
nvgMoveTo(vg, x, y);
nvgLineTo(vg, x + w, y);
nvgStroke(vg);
return RET_OK;
}
static ret_t lcd_nanovg_fill_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
lcd_nanovg_sync_fill_color(lcd, vg);
nvgBeginPath(vg);
nvgRect(vg, x, y, w, h);
nvgFill(vg);
return RET_OK;
}
static ret_t lcd_nanovg_stroke_rect(lcd_t* lcd, xy_t x, xy_t y, wh_t w, wh_t h) {
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
lcd_nanovg_sync_stroke_color(lcd, vg);
nvgBeginPath(vg);
nvgRect(vg, x, y, w, h);
nvgStroke(vg);
return RET_OK;
}
static ret_t lcd_nanovg_draw_points(lcd_t* lcd, point_t* points, uint32_t nr) {
uint32_t i = 0;
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
lcd_nanovg_sync_stroke_color(lcd, vg);
nvgBeginPath(vg);
for (i = 0; i < nr; i++) {
float x = points[i].x;
float y = points[i].y;
nvgMoveTo(vg, x, y);
nvgLineTo(vg, x, y);
}
nvgStroke(vg);
return RET_OK;
}
static int lcd_nanovg_ensure_image(lcd_nanovg_t* nano, bitmap_t* img) {
int32_t i = 0;
NVGcontext* vg = nano->vg;
for (i = 0; i < MAX_IMAGE_NR; i++) {
if (nano->images[i] == (img->data)) {
return i;
}
}
i = nvgCreateImageRGBA(vg, img->w, img->h, NVG_IMAGE_NEAREST, img->data);
if (i >= 0) {
assert(i < MAX_IMAGE_NR);
nano->images[i] = img->data;
}
return i;
}
static ret_t lcd_nanovg_draw_image(lcd_t* lcd, bitmap_t* img, rect_t* src, rect_t* dst) {
int sx = src->x;
int sy = src->y;
int sw = src->w;
int sh = src->h;
int dx = dst->x;
int dy = dst->y;
int dw = dst->w;
int dh = dst->h;
int iw = img->w;
int ih = img->h;
NVGpaint imgPaint;
float scaleX = (float)dw / sw;
float scaleY = (float)dh / sh;
lcd_nanovg_t* nano = (lcd_nanovg_t*)lcd;
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
int id = lcd_nanovg_ensure_image(nano, img);
return_value_if_fail(id >= 0, RET_BAD_PARAMS);
imgPaint = nvgImagePattern(vg, 0, 0, iw, ih, 0, id, 1);
nvgSave(vg);
nvgBeginPath(vg);
nvgTranslate(vg, dx - (sx * scaleX), dy - (sy * scaleY));
nvgScale(vg, scaleX, scaleY);
nvgRect(vg, sx, sy, sw, sh);
nvgFillPaint(vg, imgPaint);
nvgClosePath(vg);
nvgFill(vg);
nvgRestore(vg);
return RET_OK;
}
wh_t lcd_nanovg_measure_text(lcd_t* lcd, wchar_t* str, int32_t nr) {
wh_t w = 0;
int ret = 0;
float bounds[4];
char text[1024];
lcd_nanovg_t* nano = (lcd_nanovg_t*)lcd;
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
nvgFontFaceId(vg, nano->font_id);
nvgFontSize(vg, lcd->font_size);
nvgFontSize(vg, lcd->font_size);
utf8_from_utf16(str, text, sizeof(text));
ret = nvgTextBounds(vg, 0, 0, text, text + strlen(text), bounds);
w = bounds[2];
return ret;
}
static ret_t lcd_nanovg_draw_text(lcd_t* lcd, wchar_t* str, int32_t nr, xy_t x, xy_t y) {
char text[1024];
lcd_nanovg_t* nano = (lcd_nanovg_t*)lcd;
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
nvgFontFaceId(vg, nano->font_id);
nvgFontSize(vg, lcd->font_size);
lcd_nanovg_sync_text_color(lcd, vg);
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP);
utf8_from_utf16(str, text, sizeof(text));
nvgText(vg, x, y, text, text + strlen(text));
return RET_OK;
}
static ret_t lcd_nanovg_end_frame(lcd_t* lcd) {
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
SDL_Window* sdl_window = ((lcd_nanovg_t*)lcd)->sdl_window;
nvgEndFrame(vg);
SDL_GL_SwapWindow(sdl_window);
return RET_OK;
}
static ret_t lcd_nanovg_destroy(lcd_t* lcd) {
NVGcontext* vg = ((lcd_nanovg_t*)lcd)->vg;
(void)vg;
return RET_OK;
}
vgcanvas_t* lcd_nanovg_get_vgcanvas(lcd_t* lcd) { return NULL; }
lcd_t* lcd_nanovg_init(SDL_Window* sdl_window) {
int w = 0;
int h = 0;
static lcd_nanovg_t lcd;
lcd_t* base = &(lcd.base);
return_value_if_fail(sdl_window != NULL, NULL);
memset(&lcd, 0x00, sizeof(lcd_nanovg_t));
lcd.sdl_window = sdl_window;
base->begin_frame = lcd_nanovg_begin_frame;
base->set_clip_rect = lcd_nanovg_set_clip_rect;
base->draw_vline = lcd_nanovg_draw_vline;
base->draw_hline = lcd_nanovg_draw_hline;
base->fill_rect = lcd_nanovg_fill_rect;
base->stroke_rect = lcd_nanovg_stroke_rect;
base->draw_image = lcd_nanovg_draw_image;
base->draw_points = lcd_nanovg_draw_points;
base->draw_text = lcd_nanovg_draw_text;
base->measure_text = lcd_nanovg_measure_text;
base->end_frame = lcd_nanovg_end_frame;
base->get_vgcanvas = lcd_nanovg_get_vgcanvas;
base->set_font_name = lcd_nanovg_set_font_name;
base->set_font_size = lcd_nanovg_set_font_size;
base->set_global_alpha = lcd_nanovg_set_global_alpha;
base->destroy = lcd_nanovg_destroy;
SDL_GetWindowSize(sdl_window, &w, &h);
base->w = (wh_t)w;
base->h = (wh_t)h;
lcd.vg = nvgCreateGL2(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
return base;
}

34
src/lcd/lcd_nanovg.h Normal file
View File

@ -0,0 +1,34 @@
/**
* File: lcd_nanovg.h
* Author: Li XianJing <xianjimli@hotmail.com>
* Brief: nanovg implemented lcd interface
*
* Copyright (c) 2018 - 2018 Li XianJing <xianjimli@hotmail.com>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-04-11 Li XianJing <xianjimli@hotmail.com> created
*
*/
#ifndef LCD_NANOVG_H
#define LCD_NANOVG_H
#include "base/lcd.h"
#include <SDL2/SDL.h>
BEGIN_C_DECLS
lcd_t* lcd_nanovg_init(SDL_Window* window);
END_C_DECLS
#endif /*LCD_NANOVG_H*/

View File

@ -29,6 +29,7 @@
#include "base/image_manager.h"
#include "base/resource_manager.h"
#ifndef WITH_NANOVG
#ifdef WITH_STB_FONT
#include "font/font_stb.h"
#endif /*WITH_STB_FONT*/
@ -36,18 +37,26 @@
#ifdef WITH_STB_IMAGE
#include "image_loader/image_loader_stb.h"
#endif /*WITH_STB_IMAGE*/
#define WITH_BITMAP_FONT 1
#else
#undef WITH_NANOVG
#undef WITH_STB_FONT
#undef WITH_BITMAP_FONT
#undef WITH_STB_IMAGE
#endif /*WITH_NANOVG*/
static ret_t lftk_add_font(const resource_info_t* res) {
if (res->subtype == RESOURCE_TYPE_FONT_BMP) {
#ifdef WITH_BITMAP_FONT
font_manager_add(default_fm(), font_bitmap_create(res->name, res->data, res->size));
#ifdef WITH_STB_FONT
#endif
} else if (res->subtype == RESOURCE_TYPE_FONT_TTF) {
#ifdef WITH_STB_FONT
font_manager_add(default_fm(), font_stb_create(res->name, res->data, res->size));
#endif /*WITH_STB_FONT*/
} else {
log_debug("not support font type\n");
log_debug("not support font type:%d\n", res->subtype);
}
return RET_OK;
}

View File

@ -0,0 +1,8 @@
#include "base/main_loop.h"
/*for test program.*/
main_loop_t* main_loop_init(int w, int h) {
(void)w;
(void)h;
return NULL;
}

View File

@ -0,0 +1,237 @@
/**
* file: main_loop_nanovg.c
* author: li xianjing <xianjimli@hotmail.com>
* brief: nanovg implemented main_loop interface
*
* copyright (c) 2018 - 2018 li xianjing <xianjimli@hotmail.com>
*
* this program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. see the
* license file for more details.
*
*/
/**
* history:
* ================================================================
* 2018-04-11 li xianjing <xianjimli@hotmail.com> created
*
*/
#define GL_GLEXT_PROTOTYPES
#include "main_loop/main_loop_nanovg.h"
#include "base/font_manager.h"
#include "base/window_manager.h"
#include "lcd/lcd_nanovg.h"
#include "base/timer.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_opengl_glext.h>
typedef struct _main_loop_nanovg_t {
main_loop_t base;
int w;
int h;
widget_t* wm;
canvas_t canvas;
uint16_t pressed : 1;
SDL_Window* sdl_window;
SDL_GLContext gl_context;
} main_loop_nanovg_t;
static ret_t main_loop_nanovg_dispatch_key_event(main_loop_nanovg_t* loop, SDL_Event* sdl_event) {
key_event_t event;
int type = sdl_event->type;
widget_t* widget = loop->wm;
event.key = sdl_event->key.keysym.sym;
switch (type) {
case SDL_KEYDOWN: {
event.e.type = EVT_KEY_DOWN;
window_manager_dispatch_input_event(widget, (event_t*)&event);
break;
}
case SDL_KEYUP: {
event.e.type = EVT_KEY_UP;
window_manager_dispatch_input_event(widget, (event_t*)&event);
break;
}
default:
break;
}
return RET_OK;
}
static ret_t main_loop_nanovg_dispatch_mouse_event(main_loop_nanovg_t* loop, SDL_Event* sdl_event) {
pointer_event_t event;
int type = sdl_event->type;
widget_t* widget = loop->wm;
switch (type) {
case SDL_MOUSEBUTTONDOWN: {
loop->pressed = 1;
event.e.type = EVT_POINTER_DOWN;
event.x = sdl_event->button.x;
event.y = sdl_event->button.y;
event.button = sdl_event->button.button;
event.pressed = loop->pressed;
window_manager_dispatch_input_event(widget, (event_t*)&event);
break;
}
case SDL_MOUSEBUTTONUP: {
event.e.type = EVT_POINTER_UP;
event.x = sdl_event->button.x;
event.y = sdl_event->button.y;
event.button = sdl_event->button.button;
event.pressed = loop->pressed;
window_manager_dispatch_input_event(widget, (event_t*)&event);
loop->pressed = 0;
break;
}
case SDL_MOUSEMOTION: {
event.e.type = EVT_POINTER_MOVE;
event.x = sdl_event->motion.x;
event.y = sdl_event->motion.y;
event.button = 0;
event.pressed = loop->pressed;
window_manager_dispatch_input_event(widget, (event_t*)&event);
break;
}
default:
break;
}
return RET_OK;
}
static ret_t main_loop_nanovg_dispatch(main_loop_nanovg_t* loop) {
SDL_Event event;
ret_t ret = RET_OK;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP: {
ret = main_loop_nanovg_dispatch_key_event(loop, &event);
break;
}
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP: {
ret = main_loop_nanovg_dispatch_mouse_event(loop, &event);
break;
}
case SDL_QUIT: {
ret = main_loop_quit(&(loop->base));
break;
}
}
}
return ret;
}
static ret_t main_loop_nanovg_paint(main_loop_nanovg_t* loop) {
ret_t ret = window_manager_paint(loop->wm, &(loop->canvas));
return ret;
}
static ret_t main_loop_nanovg_run(main_loop_t* l) {
main_loop_nanovg_t* loop = (main_loop_nanovg_t*)l;
while (l->running) {
timer_check();
main_loop_nanovg_dispatch(loop);
main_loop_nanovg_paint(loop);
SDL_Delay(30);
}
return RET_OK;
}
static ret_t main_loop_nanovg_quit(main_loop_t* l) { return RET_OK; }
static ret_t main_loop_nanovg_destroy(main_loop_t* l) {
const char* errMsg = SDL_GetError();
main_loop_nanovg_t* loop = (main_loop_nanovg_t*)l;
if (errMsg && strlen(errMsg)) {
SDL_Log("Error : %s\n", errMsg);
}
if (loop->sdl_window) {
SDL_DestroyWindow(loop->sdl_window);
SDL_GL_DeleteContext(loop->gl_context);
loop->sdl_window = NULL;
}
SDL_Quit();
return RET_OK;
}
static ret_t main_loop_nanovg_create_window(main_loop_nanovg_t* l, font_manager_t* fm, int w,
int h) {
int32_t x = SDL_WINDOWPOS_UNDEFINED;
int32_t y = SDL_WINDOWPOS_UNDEFINED;
uint32_t flags = SDL_WINDOW_OPENGL | SDL_WINDOW_ALLOW_HIGHDPI;
l->w = w;
l->h = h;
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
return RET_FAIL;
}
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
//SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
l->sdl_window = SDL_CreateWindow("LFTK Simulator", x, y, w, h, flags);
return_value_if_fail(l->sdl_window != NULL, RET_FAIL);
l->gl_context = SDL_GL_CreateContext(l->sdl_window);
SDL_GL_MakeCurrent(l->sdl_window, l->gl_context);
SDL_GL_SetSwapInterval(0);
glEnable(GL_ALPHA_TEST);
glEnable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
canvas_init(&(l->canvas), lcd_nanovg_init(l->sdl_window), fm);
return RET_OK;
}
static main_loop_nanovg_t loop;
main_loop_t* main_loop_init(int w, int h) {
widget_t* wm = default_wm();
font_manager_t* fm = default_fm();
main_loop_t* base = &(loop.base);
memset(&loop, 0x00, sizeof(loop));
base->run = main_loop_nanovg_run;
base->quit = main_loop_nanovg_quit;
base->destroy = main_loop_nanovg_destroy;
loop.wm = wm;
window_manager_resize(wm, w, h);
main_loop_nanovg_create_window(&loop, fm, w, h);
main_loop_set_default(base);
log_debug("%s:%s\n", __FILE__, __func__);
return base;
}

View File

@ -0,0 +1,33 @@
/**
* file: main_loop_nanovg.h
* author: li xianjing <xianjimli@hotmail.com>
* brief: nanovg implemented main_loop interface
*
* copyright (c) 2018 - 2018 li xianjing <xianjimli@hotmail.com>
*
* this program is distributed in the hope that it will be useful,
* but without any warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose. see the
* license file for more details.
*
*/
/**
* history:
* ================================================================
* 2018-04-11 li xianjing <xianjimli@hotmail.com> created
*
*/
#ifndef LFTK_MAIN_LOOP_NANOVG_H
#define LFTK_MAIN_LOOP_NANOVG_H
#include "base/main_loop.h"
BEGIN_C_DECLS
main_loop_t* main_loop_init(int w, int h);
END_C_DECLS
#endif /*LFTK_MAIN_LOOP_NANOVG_H*/

View File

@ -210,5 +210,7 @@ main_loop_t* main_loop_init(int w, int h) {
main_loop_sdl2_create_window(&loop, fm, w, h);
main_loop_set_default(base);
log_debug("%s:%s\n", __FILE__, __func__);
return base;
}

View File

@ -19,6 +19,7 @@
*
*/
#include <wctype.h>
#include "base/mem.h"
#include "base/utf8.h"
#include "common/utils.h"
@ -78,6 +79,10 @@ uint32_t font_gen_buff(font_t* font, uint16_t font_size, const char* str, uint8_
iter->c = c;
iter->offset = p - output_buff;
if(iswspace(c)) {
continue;
}
printf("%d/%d: 0x%04x\n", i, size, c);
if (font_find_glyph(font, c, &g, font_size) == RET_OK) {
uint32_t data_size = g.w * g.h;

View File

@ -6,7 +6,7 @@ int main(int argc, char* argv[]) {
FILE* fp = fopen("ascii.txt", "wb+");
if (fp != NULL) {
for (c = 0; c < 128; c++) {
if (isprint(c)) {
if (isprint(c) && !isspace(c)) {
printf("%c", c);
fprintf(fp, "%c", c);
}

View File

@ -51,11 +51,12 @@ int main(int argc, char** argv) {
ttf_buff = (uint8_t*)read_file(ttf_filename, &size);
return_value_if_fail(ttf_buff != NULL, 0);
font = font_stb_create("default", ttf_buff, size);
str_buff = read_file(str_filename, &size);
return_value_if_fail(str_buff != NULL, 0);
font = font_stb_create("default", ttf_buff, size);
if (font != NULL) {
font_gen(font, (uint16_t)font_size, str_buff, output_filename);
}

View File

@ -11,6 +11,7 @@ mkdir -p $SRC_DIR/fonts
mkdir -p $SRC_DIR/ui
$BIN_DIR/themegen $RAW_DIR/theme/theme.xml $SRC_DIR/theme/default.data
$BIN_DIR/resgen $RAW_DIR/fonts/font.ttf $SRC_DIR/fonts/default_ttf.data
$BIN_DIR/resgen $RAW_DIR/fonts/action_protocol.ttf $SRC_DIR/fonts/ap.data
$BIN_DIR/fontgen $RAW_DIR/fonts/font.ttf $RAW_DIR/fonts/text.txt $SRC_DIR/fonts/default.data 20