add nanovg lcd
28
3rd/nanovg/.gitignore
vendored
Normal 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
@ -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
@ -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
@ -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'))
|
||||
|
116
3rd/nanovg/example/.clang-format
Normal 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
|
||||
...
|
||||
|
92
3rd/nanovg/example/LICENSE_OFL.txt
Normal 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.
|
BIN
3rd/nanovg/example/NotoEmoji-Regular.ttf
Normal file
BIN
3rd/nanovg/example/Roboto-Bold.ttf
Executable file
BIN
3rd/nanovg/example/Roboto-Light.ttf
Executable file
BIN
3rd/nanovg/example/Roboto-Regular.ttf
Executable file
1226
3rd/nanovg/example/demo.c
Normal file
26
3rd/nanovg/example/demo.h
Normal 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
|
BIN
3rd/nanovg/example/entypo.ttf
Normal file
272
3rd/nanovg/example/example_fbo.c
Normal 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;
|
||||
}
|
163
3rd/nanovg/example/example_gl2.c
Normal 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;
|
||||
}
|
198
3rd/nanovg/example/example_gl3.c
Normal 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;
|
||||
}
|
155
3rd/nanovg/example/example_gles2.c
Normal 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;
|
||||
}
|
155
3rd/nanovg/example/example_gles3.c
Normal 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
@ -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 {} \;
|
||||
|
13
3rd/nanovg/example/images.txt
Normal 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/
|
BIN
3rd/nanovg/example/images/image1.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
3rd/nanovg/example/images/image10.jpg
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
3rd/nanovg/example/images/image11.jpg
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
3rd/nanovg/example/images/image12.jpg
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
3rd/nanovg/example/images/image2.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
3rd/nanovg/example/images/image3.jpg
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
3rd/nanovg/example/images/image4.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
3rd/nanovg/example/images/image5.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
3rd/nanovg/example/images/image6.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
3rd/nanovg/example/images/image7.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
3rd/nanovg/example/images/image8.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
3rd/nanovg/example/images/image9.jpg
Normal file
After Width: | Height: | Size: 3.9 KiB |
186
3rd/nanovg/example/perf.c
Normal 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
@ -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
|
BIN
3rd/nanovg/example/screenshot-01.png
Normal file
After Width: | Height: | Size: 966 KiB |
BIN
3rd/nanovg/example/screenshot-02.png
Normal file
After Width: | Height: | Size: 224 KiB |
137
3rd/nanovg/example/sdl-ok.c
Normal 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
@ -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
|
511
3rd/nanovg/example/stb_image_write.h
Normal 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
|
||||
*/
|
952
3rd/nanovg/obsolete/nanovg_gl2.h
Normal 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(¶ms, 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(¶ms);
|
||||
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
|
957
3rd/nanovg/obsolete/nanovg_gl3.h
Normal 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(¶ms, 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(¶ms);
|
||||
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
|
6
3rd/nanovg/obsolete/obsolete.md
Normal 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
@ -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
2891
3rd/nanovg/src/nanovg.c
Normal file
685
3rd/nanovg/src/nanovg.h
Normal 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
154
3rd/nanovg/src/nanovg_gl_utils.h
Normal 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
3249
3rd/nanovg/src/stb_truetype.h
Normal file
1549
3rd/nanovg/src/tags
Normal file
73
SConstruct
@ -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'
|
||||
])
|
||||
|
BIN
demos/res/raw/fonts/NotoEmoji-Regular.ttf
Normal file
BIN
demos/res/raw/fonts/Roboto-Bold.ttf
Executable file
BIN
demos/res/raw/fonts/Roboto-Light.ttf
Executable file
BIN
demos/res/raw/fonts/Roboto-Regular.ttf
Executable file
BIN
demos/res/raw/fonts/entypo.ttf
Normal file
@ -1 +1 @@
|
||||
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~确定取消
|
||||
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~确定取消
|
||||
|
4975
demos/res/src/fonts/default_ttf.data
Normal 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*/
|
||||
|
@ -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*/
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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*/
|
||||
|
@ -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);
|
||||
|
||||
|
104
src/base/lcd.h
@ -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 绘制到目标区域。
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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*/
|
||||
|
@ -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*/
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
* 销毁控件。
|
||||
|
@ -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,
|
||||
|
@ -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*/
|
||||
|
@ -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 {
|
||||
|
@ -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
@ -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
@ -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*/
|
15
src/lftk.c
@ -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;
|
||||
}
|
||||
|
||||
|
8
src/main_loop/main_loop_dummy.c
Normal 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;
|
||||
}
|
237
src/main_loop/main_loop_nanovg.c
Normal 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;
|
||||
}
|
33
src/main_loop/main_loop_nanovg.h
Normal 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*/
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|