void vsDropShadow(NVGcontext *ctx, float x, float y, float w, float h, float r, float feather, float alpha) { nvgBeginPath(ctx); y += feather; h -= feather; nvgMoveTo(ctx, x - feather, y - feather); nvgLineTo(ctx, x, y - feather); nvgLineTo(ctx, x, y + h - feather); nvgArcTo(ctx, x, y + h, x + r, y + h, r); nvgArcTo(ctx, x + w, y + h, x + w, y + h - r, r); nvgLineTo(ctx, x + w, y - feather); nvgLineTo(ctx, x + w + feather, y - feather); nvgLineTo(ctx, x + w + feather, y + h + feather); nvgLineTo(ctx, x - feather, y + h + feather); nvgClosePath(ctx); nvgFillPaint(ctx, nvgBoxGradient(ctx, x - feather * 0.5f, y - feather * 0.5f, w + feather, h + feather, r + feather * 0.5f, feather, nvgRGBAf(0, 0, 0, alpha * alpha), nvgRGBAf(0, 0, 0, 0))); nvgFill(ctx); }
void TextNode::renderItself(RenderContext& renderContext) { NVGcontext& nanoVgContext = renderContext.getNanoVgContext(); nvgSave(&nanoVgContext); setupContext(nanoVgContext); Color finalColor = mFontColor.getBlendedColor(renderContext.getBlendColors()); nvgFillColor(&nanoVgContext, nvgRGBAf(finalColor.getRed(), finalColor.getGreen(), finalColor.getBlue(), finalColor.getAlpha())); for(const Text& text : mTexts) { const char* charArray = text.getString().getCharArray(); float positionX = text.getPosition().getX(); float positionY = text.getPosition().getY(); if(isPositive(text.getBoxWidth())) { nvgTextBox(&nanoVgContext, positionX, positionY, text.getBoxWidth(), charArray, nullptr); } else { nvgText(&nanoVgContext, positionX, positionY, charArray, nullptr); } } nvgRestore(&nanoVgContext); Node::renderItself(renderContext); }
NVGcolor nvgOffsetColour(const Colour& colour, float delta) { float offset = delta / 255.0f; return nvgRGBAf( clamp(colour.r() + offset, 0, 1), clamp(colour.g() + offset, 0, 1), clamp(colour.b() + offset, 0, 1), colour.a()); }
static void applyTextFormat(VectorTextFormat *format, lmscalar alpha) { format->ensureFontId(); if (format->fontId >= 0) nvgFontFaceId(nvg, format->fontId); if (format->color >= 0) { unsigned int rgb = format->color; float cr = ((rgb >> 16) & 0xff) / 255.0f; float cg = ((rgb >> 8) & 0xff) / 255.0f; float cb = ((rgb >> 0) & 0xff) / 255.0f; nvgFillColor(nvg, nvgRGBAf(cr, cg, cb, (float)alpha)); }
void ImageNode::renderItself(RenderContext& renderContext) { NVGcontext& nanoVgContext = renderContext.getNanoVgContext(); NVGpaint paint = nvgImagePattern(&nanoVgContext, mImagePatternRect.getX(), mImagePatternRect.getY(), mImagePatternRect.getWidth(), mImagePatternRect.getHeight(), 0, mImage.getHandle(), 1); nvgBeginPath(&nanoVgContext); nvgRect(&nanoVgContext, mRect.getX(), mRect.getY(), mRect.getWidth(), mRect.getHeight()); nvgFillPaint(&nanoVgContext, paint); nvgFill(&nanoVgContext); if(! renderContext.getBlendColors().empty()) { std::pair<Color, float> blendResult = renderContext.getBlendResult(); const Color& blendColor = blendResult.first; nvgBeginPath(&nanoVgContext); nvgRect(&nanoVgContext, mRect.getX(), mRect.getY(), mRect.getWidth(), mRect.getHeight()); nvgFillColor(&nanoVgContext, nvgRGBAf(blendColor.getRed(), blendColor.getGreen(), blendColor.getBlue(), blendColor.getAlpha() * blendResult.second)); nvgFill(&nanoVgContext); } Node::renderItself(renderContext); }
void drawUI(NVGcontext *vg, int item, int corners) { const UIData *head = (const UIData *)uiGetHandle(item); UIrect rect = uiGetRect(item); if (uiGetState(item) == UI_FROZEN) { nvgGlobalAlpha(vg, BND_DISABLED_ALPHA); } if (head) { switch(head->subtype) { default: { testrect(vg,rect); drawUIItems(vg,item,corners); } break; case ST_HBOX: { drawUIItemsHbox(vg, item); } break; case ST_VBOX: { drawUIItemsVbox(vg, item); } break; case ST_PANEL: { bndBevel(vg,rect.x,rect.y,rect.w,rect.h); drawUIItems(vg,item,corners); } break; case ST_LABEL: { assert(head); const UIButtonData *data = (UIButtonData*)head; bndLabel(vg,rect.x,rect.y,rect.w,rect.h, data->iconid,data->label); } break; case ST_BUTTON: { const UIButtonData *data = (UIButtonData*)head; bndToolButton(vg,rect.x,rect.y,rect.w,rect.h, corners,(BNDwidgetState)uiGetState(item), data->iconid,data->label); } break; case ST_CHECK: { const UICheckData *data = (UICheckData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); if (*data->option) state = BND_ACTIVE; bndOptionButton(vg,rect.x,rect.y,rect.w,rect.h, state, data->label); } break; case ST_RADIO:{ const UIRadioData *data = (UIRadioData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); if (*data->value == item) state = BND_ACTIVE; bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h, corners,state, data->iconid,data->label); } break; case ST_SLIDER:{ const UISliderData *data = (UISliderData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); static char value[32]; sprintf(value,"%.0f%%",(*data->progress)*100.0f); bndSlider(vg,rect.x,rect.y,rect.w,rect.h, corners,state, *data->progress,data->label,value); } break; case ST_TEXT: { const UITextData *data = (UITextData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); int idx = strlen(data->text); bndTextField(vg,rect.x,rect.y,rect.w,rect.h, corners,state, -1, data->text, idx, idx); } break; case ST_DEMOSTUFF: { draw_demostuff(vg, rect.x, rect.y, rect.w, rect.h); } break; case ST_RECT: { const UIRectData *data = (UIRectData*)head; if (rect.w && rect.h) { BNDwidgetState state = (BNDwidgetState)uiGetState(item); nvgSave(vg); nvgStrokeColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.9f)); if (state != BND_DEFAULT) { nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.5f)); } else { nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.1f)); } nvgStrokeWidth(vg,2); nvgBeginPath(vg); #if 0 nvgRect(vg,rect.x,rect.y,rect.w,rect.h); #else nvgRoundedRect(vg,rect.x,rect.y,rect.w,rect.h,3); #endif nvgFill(vg); nvgStroke(vg); if (state != BND_DEFAULT) { nvgFillColor(vg, nvgRGBAf(0.0f,0.0f,0.0f,1.0f)); nvgFontSize(vg, 15.0f); nvgBeginPath(vg); nvgTextAlign(vg, NVG_ALIGN_TOP|NVG_ALIGN_CENTER); nvgTextBox(vg, rect.x, rect.y+rect.h*0.3f, rect.w, data->label, NULL); } nvgRestore(vg); } nvgSave(vg); nvgIntersectScissor(vg, rect.x, rect.y, rect.w, rect.h); drawUIItems(vg,item,corners); nvgRestore(vg); } break; } } else { testrect(vg,rect); drawUIItems(vg,item,corners); } if (uiGetState(item) == UI_FROZEN) { nvgGlobalAlpha(vg, 1.0); } }
void draw(NVGcontext *vg, float w, float h) { bndBackground(vg, 0, 0, w, h); // some OUI stuff uiBeginLayout(); int root = panel(); // position root element uiSetSize(0,w,h); ((UIData*)uiGetHandle(root))->handler = roothandler; uiSetEvents(root, UI_SCROLL|UI_BUTTON0_DOWN); uiSetBox(root, UI_COLUMN); static int choice = -1; int menu = uiItem(); uiSetLayout(menu, UI_HFILL|UI_TOP); uiSetBox(menu, UI_ROW); uiInsert(root, menu); int opt_blendish_demo = add_menu_option(menu, "Blendish Demo", &choice); int opt_oui_demo = add_menu_option(menu, "OUI Demo", &choice); int opt_layouts = add_menu_option(menu, "UI_LAYOUT", &choice); int opt_row = add_menu_option(menu, "UI_ROW", &choice); int opt_column = add_menu_option(menu, "UI_COLUMN", &choice); int opt_wrap = add_menu_option(menu, "UI_WRAP", &choice); if (choice < 0) choice = opt_blendish_demo; int content = uiItem(); uiSetLayout(content, UI_FILL); uiInsert(root, content); if (choice == opt_blendish_demo) { int democontent = uiItem(); uiSetLayout(democontent, UI_FILL); uiInsert(content, democontent); UIData *data = (UIData *)uiAllocHandle(democontent, sizeof(UIData)); data->handler = 0; data->subtype = ST_DEMOSTUFF; } else if (choice == opt_oui_demo) { int democontent = uiItem(); uiSetLayout(democontent, UI_TOP); uiSetSize(democontent, 250, 0); uiInsert(content, democontent); build_democontent(democontent); } else if (choice == opt_layouts) { build_layoutdemo(content); } else if (choice == opt_row) { build_rowdemo(content); } else if (choice == opt_column) { build_columndemo(content); } else if (choice == opt_wrap) { build_wrapdemo(content); } uiEndLayout(); drawUI(vg, 0, BND_CORNER_NONE); #if 0 for (int i = 0; i < uiGetLastItemCount(); ++i) { if (uiRecoverItem(i) == -1) { UIitem *pitem = uiLastItemPtr(i); nvgBeginPath(vg); nvgRect(vg,pitem->margins[0],pitem->margins[1],pitem->size[0],pitem->size[1]); nvgStrokeWidth(vg, 2); nvgStrokeColor(vg, nvgRGBAf(1.0f,0.0f,0.0f,0.5f)); nvgStroke(vg); } } #endif if (choice == opt_blendish_demo) { UIvec2 cursor = uiGetCursor(); cursor.x -= w/2; cursor.y -= h/2; if (abs(cursor.x) > (w/3)) { bndJoinAreaOverlay(vg, 0, 0, w, h, 0, (cursor.x > 0)); } else if (abs(cursor.y) > (h/3)) { bndJoinAreaOverlay(vg, 0, 0, w, h, 1, (cursor.y > 0)); } } uiProcess((int)(glfwGetTime()*1000.0)); }
JNIEXPORT void JNICALL Java_org_lwjgl_nanovg_NanoVG_nnvgRGBAf(JNIEnv *__env, jclass clazz, jfloat r, jfloat g, jfloat b, jfloat a, jlong __result) { UNUSED_PARAMS(__env, clazz) *((NVGcolor*)(intptr_t)__result) = nvgRGBAf(r, g, b, a); }
int main() { constexpr auto width = 1200u; constexpr auto height = 800u; // init ny app auto& backend = ny::Backend::choose(); if(!backend.vulkan()) { dlg_error("ny backend has no vulkan support!"); return 0; } auto ac = backend.createAppContext(); // basic vpp init auto iniExtensions = ac->vulkanExtensions(); iniExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); vk::ApplicationInfo appInfo ("vpp-intro", 1, "vpp", 1, VK_API_VERSION_1_0); vk::InstanceCreateInfo instanceInfo; instanceInfo.pApplicationInfo = &appInfo; instanceInfo.enabledExtensionCount = iniExtensions.size(); instanceInfo.ppEnabledExtensionNames = iniExtensions.data(); #ifdef WithLayers constexpr auto layer = "VK_LAYER_LUNARG_standard_validation"; instanceInfo.enabledLayerCount = 1; instanceInfo.ppEnabledLayerNames = &layer; #endif vpp::Instance instance(instanceInfo); #ifdef WithLayers vpp::DebugCallback debugCallback(instance); #endif // ny init auto run = true; auto listener = MyWindowListener {}; listener.run = &run; auto vkSurface = vk::SurfaceKHR {}; auto ws = ny::WindowSettings {}; ws.surface = ny::SurfaceType::vulkan; ws.listener = &listener; ws.size = {width, height}; ws.vulkan.instance = (VkInstance) instance.vkHandle(); ws.vulkan.storeSurface = &(std::uintptr_t&) (vkSurface); auto wc = ac->createWindowContext(ws); // further vpp init const vpp::Queue* presentQueue; vpp::Device device(instance, vkSurface, presentQueue); vpp::Swapchain swapchain(device, vkSurface, {width, height}, {}); // vvg setup auto nvgContext = vvg::createContext(swapchain); auto font = nvgCreateFont(nvgContext, "sans", "Roboto-Regular.ttf"); using Clock = std::chrono::high_resolution_clock; auto lastFrameTimer = Clock::now(); unsigned int framesCount = 0; std::string fpsString = "420 fps"; // main loop while(run) { if(!ac->dispatchEvents()) break; nvgBeginFrame(nvgContext, width, height, width / (float) height); nvgBeginPath(nvgContext); nvgMoveTo(nvgContext, 10, 10); nvgLineTo(nvgContext, 10, 400); nvgLineTo(nvgContext, 100, 400); nvgQuadTo(nvgContext, 100, 50, 400, 120); nvgLineTo(nvgContext, 450, 10); nvgClosePath(nvgContext); nvgFillColor(nvgContext, nvgRGBAf(0.5, 0.8, 0.7, 1.0)); nvgFill(nvgContext); nvgBeginPath(nvgContext); nvgFontFaceId(nvgContext, font); nvgFontSize(nvgContext, 100.f); nvgFontBlur(nvgContext, .8f); nvgFillColor(nvgContext, nvgRGBAf(1.0, 1.0, 1.0, 1.0)); nvgTextBox(nvgContext, 200, 200, width - 200, "Hello Vulkan Vector Graphics World", nullptr); nvgFontSize(nvgContext, 30.f); nvgFontBlur(nvgContext, .2f); nvgText(nvgContext, 10, height - 20, fpsString.c_str(), nullptr); nvgBeginPath(nvgContext); nvgRect(nvgContext, 700, 400, 300, 300); nvgPathWinding(nvgContext, NVG_HOLE); nvgRect(nvgContext, 750, 450, 50, 50); // auto paint = nvgRadialGradient(nvgContext, 750, 425,20, 50, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0)); // auto paint = nvgRadialGradient(nvgContext, 0.0, 0.0, 0.2, 100.0, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0)); auto paint = nvgLinearGradient(nvgContext, 700, 400, 800, 450, nvgRGB(0, 0, 200), nvgRGB(200, 200, 0)); nvgFillPaint(nvgContext, paint); // nvgFillColor(nvgContext, nvgRGBA(200, 200, 0, 200)); nvgClosePath(nvgContext); nvgFill(nvgContext); nvgEndFrame(nvgContext); // only refresh frame timer every second framesCount++; if(Clock::now() - lastFrameTimer >= std::chrono::seconds(1)) { fpsString = std::to_string(framesCount) + " fps"; lastFrameTimer = Clock::now(); framesCount = 0; } } vvg::destroyContext(*nvgContext); }
JNIEXPORT void Java_firststep_internal_NVG_00024Color_putRGBA(JNIEnv *e, jobject o, jfloat r, jfloat g, jfloat b, jfloat a) { NVGcolor c = nvgRGBAf(r, g, b, a); void *ptr = getBuffPtr(e, o); memcpy(ptr, &c, sizeof(NVGcolor)); }
JNIEXPORT void JNICALL Java_firststep_internal_NVG_strokeColorf (JNIEnv *e, jclass c, jlong ctx, jfloat r, jfloat g, jfloat b, jfloat a) { nvgStrokeColor((NVGcontext*)ctx, nvgRGBAf(r,g,b,a)); }
void VectorRenderer::fillColor(float r, float g, float b, float a) { nvgFillColor(nvg, nvgRGBAf(r, g, b, a)); currentTextFormatApplied = false; }
void VectorRenderer::strokeColor(float r, float g, float b, float a) { nvgStrokeColor(nvg, nvgRGBAf(r, g, b, a)); }
NVGcolor nvgColour(const Colour& colour) { return nvgRGBAf(colour.r(), colour.g(), colour.b(), colour.a()); }