box2px TreeItem::update(AlloyContext* context, const pixel2& offset) { NVGcontext* nvg = context->nvgContext; nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); nvgFontSize(nvg, fontSize); nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); spaceWidth = fontSize + PADDING * 2; float textWidth = nvgTextBounds(nvg, 0, 0, name.c_str(), nullptr, nullptr); nvgFontFaceId(nvg, context->getFontHandle(FontType::Icon)); float iconWidth = (iconCodeString.length() == 0) ? 0 : nvgTextBounds(nvg, 0, 0, iconCodeString.c_str(), nullptr, nullptr) + PADDING * 2; float th = (name.length() > 0) ? fontSize + PADDING * 2 : 0; selectionBounds = box2px(offset, pixel2(textWidth + iconWidth + spaceWidth + PADDING, th)); bounds = selectionBounds; if (isExpanded()) { pixel2 pt = offset + pixel2((name.length() > 0) ? spaceWidth : 0, th); for (TreeItemPtr& item : children) { box2px cdims = item->update(context, pt); bounds.dimensions = aly::max(bounds.max(), cdims.max()) - aly::min(bounds.min(), cdims.min()); pt += pixel2(0.0f, cdims.dimensions.y); } } return bounds; }
void TreeItem::draw(ExpandTree* tree, AlloyContext* context, const pixel2& offset) { box2px bounds = getBounds(); NVGcontext* nvg = context->nvgContext; nvgFontFaceId(nvg, context->getFontHandle(FontType::Icon)); float spaceWidth = fontSize + PADDING * 2; float iconWidth = 0; static const std::string rightArrow = CodePointToUTF8(0xf0da); static const std::string downArrow = CodePointToUTF8(0xf0d7); pixel2 pt = bounds.position + offset; bool selected = (tree->getSelectedItem() == this)&&!tree->isOverArrow(); nvgFontSize(nvg, fontSize); if (iconCodeString.length() > 0) { iconWidth = nvgTextBounds(nvg, 0, 0, iconCodeString.c_str(), nullptr, nullptr) + PADDING * 2; if (children.size() > 0 || onExpand) { nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_TOP); if (tree->isOverArrow()) { nvgFillColor(nvg, context->theme.LIGHTEST); } else { nvgFillColor(nvg, context->theme.LIGHTER); } nvgText(nvg, pt.x + spaceWidth * 0.5f, pt.y + PADDING, (expanded) ? downArrow.c_str() : rightArrow.c_str(), nullptr); } if (selected) { nvgFillColor(nvg, context->theme.LIGHTEST); } else { nvgFillColor(nvg, context->theme.LIGHTER); } nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); nvgText(nvg, pt.x + spaceWidth, pt.y + PADDING, iconCodeString.c_str(), nullptr); } if (name.length() > 0) { if (selected) { nvgFillColor(nvg, context->theme.LIGHTEST); } else { nvgFillColor(nvg, context->theme.LIGHTER); } nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); nvgText(nvg, pt.x + iconWidth + spaceWidth, pt.y + PADDING, name.c_str(), nullptr); } if (expanded) { for (TreeItemPtr& item : children) { item->draw(tree, context, offset); } } }
void Renderer2D::drawText( const attributes_2d& attributes,Font2D font, const char* text, const float32_t& fontSize, const color_argb& color, const float32_t& blur, const float32_t& spacing, const float32_t& lineHeight, const TextAlignment& alignment ) { Context2D* context = _context2D; nvgSave( context ); nvgBeginPath( context ); nvgRotate( context, attributes.rotation ); nvgFontSize( context, fontSize * attributes.scale ); nvgFontBlur( context, blur ); nvgTextLetterSpacing(context, spacing); nvgTextLineHeight(context, lineHeight); nvgTextAlign(context, alignment.value ); nvgFontFaceId(context, font); nvgFillColor( context, nvgRGBA( color.r, color.g, color.b, color.a) ); nvgFill(context); nvgText(context, attributes.position[0], attributes.position[1], text, NULL); nvgRestore( context ); }
void AwesomeGlyph::draw(const box2px& bounds, const Color& fgColor, const Color& bgColor, AlloyContext* context) { NVGcontext* nvg = context->nvgContext; nvgFontFaceId(nvg, context->getFontHandle(FontType::Icon)); nvgFontSize(nvg, height); nvgTextAlign(nvg, NVG_ALIGN_MIDDLE | NVG_ALIGN_CENTER); drawText(nvg, bounds.position + HALF_PIX(bounds.dimensions), name, style, fgColor, bgColor, nullptr); }
void IterationRunWork::output(run::World& run) { // draw background demo::background( batb, run ); if ( item_ ) { switch ( item_->mode ) { case WorkItem::Mode::Definite: { //tb_widget_->set( item_->alpha, item_->tag ); const auto& tag = item_->tag; auto alpha = item_->alpha; // draw progressbar. FIXME auto nvg = batb.gl.nanovg_begin( run.scene ); float_t w = 512; float_t h = 22; float_t x = 0.5 * (run.scene.wth - w); float_t y = 0.5 * run.scene.hth + 112; float_t r = 11; nvgBeginPath( nvg ); nvgRoundedRect( nvg, x, y, w, h, r ); nvgFillColor( nvg, nvgRGBf( 1.0, 1.0, 1.0 ) ); nvgFill( nvg ); nvgBeginPath( nvg ); nvgRoundedRect( nvg, x, y, alpha * w, h, r ); nvgFillColor( nvg, nvgRGBf( 1.0, 0.22, 0.0 ) ); nvgFill( nvg ); static int font = -1; if ( font == -1 ) { font = batb.gl.nanovg_font( "sans", file::static_data( "batb/Ubuntu-Title.ttf" ) ); } nvgFontSize( nvg, 20 ); nvgTextAlign( nvg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE ); nvgFontFaceId( nvg, font ); nvgFillColor( nvg, nvgRGBf( 0.0, 0.0, 0.0 ) ); //nvgFillColor( nvg, nvgRGBf( 0.11, 0.64, 0.04 ) ); nvgText( nvg, x + 0.5 * w, y + 0.5 * h, tag.c_str(), nullptr ); batb.gl.nanovg_end(); } break; case WorkItem::Mode::Indefinite: // FIXME: draw a finite progressbar/spinner break; } } }
AwesomeGlyph::AwesomeGlyph(int codePoint, AlloyContext* context, const FontStyle& style, pixel height) : Glyph(CodePointToUTF8(codePoint), GlyphType::Awesome, 0, height), codePoint( codePoint), style(style) { NVGcontext* nvg = context->nvgContext; nvgFontSize(nvg, height); nvgFontFaceId(nvg, context->getFontHandle(FontType::Icon)); width = nvgTextBounds(nvg, 0, 0, name.c_str(), nullptr, nullptr); }
void TextNode::setupContext(NVGcontext& nanoVgContext) const { nvgFontFaceId(&nanoVgContext, mFontHandle); nvgFontSize(&nanoVgContext, mFontSize); nvgFontBlur(&nanoVgContext, mFontBlur); nvgTextLetterSpacing(&nanoVgContext, mFontLetterSpacing); nvgTextLineHeight(&nanoVgContext, mFontLineHeight); int alignment = static_cast<int>(mHorizontalAlignment) | static_cast<int>(mVerticalAlignment); nvgTextAlign(&nanoVgContext, alignment); }
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)); }
size_t NvgFont::get_cursor_location(const std::string & text, float fontSize, int xCoord) const { std::vector<NVGglyphPosition> positions(text.size()); nvgFontSize(nvg, fontSize); nvgFontFaceId(nvg, id); nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); positions.resize(nvgTextGlyphPositions(nvg, 0, 0, text.data(), text.data() + (int) text.size(), positions.data(), (int) positions.size())); for (size_t i = 0; i<positions.size(); ++i) { if(xCoord < positions[i].maxx) return i; } return positions.size(); }
int Font::getCursorPosition(const std::string & text, float fontSize, int xCoord) const { std::vector<NVGglyphPosition> positions(text.size()); nvgFontSize(nvg, fontSize); nvgFontFaceId(nvg, handle); nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); positions.resize( nvgTextGlyphPositions(nvg, 0, 0, text.data(), text.data() + text.size(), positions.data(), (int) positions.size())); for (size_t i = 0; i < positions.size(); ++i) { if (xCoord < positions[i].maxx) { return static_cast<int>(i); } } return static_cast<int>(positions.size()); }
void Cursor::draw(AlloyContext* context) const { pixel2 cursor = context->cursorPosition; if (fontSize > 0.0f && context->hasFocus && cursor.x >= 0 && cursor.y >= 0 && cursor.x < context->getScreenWidth() && cursor.y < context->getScreenHeight()) { NVGcontext* nvg = context->nvgContext; nvgTextAlign(nvg, align); nvgSave(nvg); nvgFontFaceId(nvg, context->getFontHandle(fontType)); nvgFontSize(nvg, fontSize); nvgFillColor(nvg, Color(255, 255, 255)); nvgTranslate(nvg, cursor.x+nudge.x, cursor.y+nudge.y); nvgRotate(nvg, angle); const float shift = 1.0f; const char* txt = codeString.c_str(); nvgFillColor(nvg, Color(0, 0, 0)); nvgText(nvg, +shift, 0, txt, nullptr); nvgText(nvg, -shift, 0, txt, nullptr); nvgText(nvg, 0, +shift, txt, nullptr); nvgText(nvg, 0, -shift, txt, nullptr); nvgFillColor(nvg, Color(255, 255, 255)); nvgText(nvg, 0, 0, txt, nullptr); nvgRestore(nvg); } }
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); }
void Application::drawDebugUI() { NVGcontext* nvg = context->nvgContext; nvgBeginFrame(nvg, context->getScreenWidth(), context->getScreenHeight(),1.0f); nvgResetScissor(nvg); rootRegion.drawDebug(context.get()); Region* onTop = context->getOnTopRegion(); if (onTop != nullptr) { onTop->drawDebug(context.get()); } float cr = context->theme.CORNER_RADIUS; if (context->getViewport().contains(context->cursorPosition)) { nvgFontSize(nvg, 15); nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); /* int alignment = 0; if (context->cursorPosition.x < context->width() * 0.5f) { alignment = NVG_ALIGN_LEFT; } else { alignment = NVG_ALIGN_RIGHT; } if (context->cursorPosition.y < context->height() * 0.5f) { alignment |= NVG_ALIGN_TOP; } else { alignment |= NVG_ALIGN_BOTTOM; } std::string txt = MakeString() << std::setprecision(4) << " " << context->cursorPosition; nvgTextAlign(nvg, alignment); nvgFillColor(nvg, Color(0, 0, 0, 128)); if (context->hasFocus) { drawText(nvg, context->cursorPosition, txt, FontStyle::Outline, Color(255), Color(64, 64, 64)); } */ nvgTextAlign(nvg, NVG_ALIGN_TOP); float yoffset = 5; std::string txt = context->hasFocus ? "Window Has Focus" : "Window Lost Focus"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; if (context->mouseOverRegion != nullptr) { txt = MakeString() << "Mouse Over [" << context->mouseOverRegion->name << "] " << context->cursorPosition; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->mouseDownRegion != nullptr) { txt = MakeString() << "Mouse Down [" << context->mouseDownRegion->name << "] " << context->cursorDownPosition; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->mouseFocusRegion != nullptr) { txt = MakeString() << "Mouse Focus [" << context->mouseFocusRegion->name << "]"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->onTopRegion != nullptr) { txt = MakeString() << "On Top [" << context->onTopRegion->name << ": " << (context->onTopRegion->isVisible() ? "Visible" : "Hidden") << "]"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->leftMouseButton) { txt = "Left Mouse Button Down"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->rightMouseButton) { txt = "Right Mouse Button Down"; drawText(nvg, 5, yoffset, txt.c_str(), FontStyle::Outline, Color(255), Color(64, 64, 64)); yoffset += 16; } if (context->hasFocus) { nvgBeginPath(nvg); nvgLineCap(nvg, NVG_ROUND); nvgStrokeWidth(nvg, 2.0f); nvgStrokeColor(nvg, Color(255, 255, 255, 255)); nvgMoveTo(nvg, context->cursorPosition.x - cr, context->cursorPosition.y); nvgLineTo(nvg, context->cursorPosition.x + cr, context->cursorPosition.y); nvgMoveTo(nvg, context->cursorPosition.x, context->cursorPosition.y - cr); nvgLineTo(nvg, context->cursorPosition.x, context->cursorPosition.y + cr); nvgStroke(nvg); nvgBeginPath(nvg); nvgFillColor(nvg, Color(255, 255, 255, 255)); nvgCircle(nvg, context->cursorPosition.x, context->cursorPosition.y, 3.0f); nvgFill(nvg); nvgBeginPath(nvg); nvgFillColor(nvg, Color(255, 64, 32, 255)); nvgCircle(nvg, context->cursorPosition.x, context->cursorPosition.y, 1.5f); nvgFill(nvg); } } nvgEndFrame(nvg); }
void GraphPane::draw(AlloyContext* context) { Region::draw(context); box2px rbounds = getBounds(); NVGcontext* nvg = context->nvgContext; box2px gbounds = rbounds; const float LARGE_TEXT = 18.0f; const float MEDIUM_TEXT = 16.0f; const float SMALL_TEXT = 12.0f; float2 gpos(-1, -1); gbounds.position = pixel2(rbounds.position.x + GRAPH_PADDING, rbounds.position.y + GRAPH_PADDING); gbounds.dimensions = pixel2(rbounds.dimensions.x - GRAPH_PADDING * 2, rbounds.dimensions.y - GRAPH_PADDING * 2); if (graphBounds.dimensions.x < 0 || graphBounds.dimensions.y < 0) { updateGraphBounds(); } nvgBeginPath(nvg); nvgRoundedRect(nvg, gbounds.position.x - 2, gbounds.position.y - 2, gbounds.dimensions.x + 4, gbounds.dimensions.y + 4, context->theme.CORNER_RADIUS); nvgFillColor(nvg, context->theme.LIGHTEST); nvgFill(nvg); //Draw vertical line for x=0 if (graphBounds.position.x < 0 && graphBounds.position.x + graphBounds.dimensions.x > 0) { float xpos = -graphBounds.position.x / graphBounds.dimensions.x; nvgBeginPath(nvg); nvgMoveTo(nvg, xpos * gbounds.dimensions.x + gbounds.position.x, gbounds.position.y); nvgLineTo(nvg, xpos * gbounds.dimensions.x + gbounds.position.x, gbounds.position.y + gbounds.dimensions.y); nvgStrokeWidth(nvg, 2.0f); nvgStrokeColor(nvg, context->theme.DARK.toSemiTransparent(0.75f)); nvgStroke(nvg); } //Draw horizontal line for y=0 if (graphBounds.position.y < 0 && graphBounds.position.y + graphBounds.dimensions.y > 0) { float ypos = -graphBounds.position.y / graphBounds.dimensions.y; nvgBeginPath(nvg); nvgMoveTo(nvg, gbounds.position.x, ypos * gbounds.dimensions.y + gbounds.position.y); nvgLineTo(nvg, gbounds.position.x + gbounds.dimensions.x, ypos * gbounds.dimensions.y + gbounds.position.y); nvgStrokeWidth(nvg, 2.0f); nvgStrokeColor(nvg, context->theme.DARK.toSemiTransparent(0.75f)); nvgStroke(nvg); } if (gbounds.contains(cursorPosition)) { context->setCursor(&Cursor::CrossHairs); gpos = (cursorPosition - gbounds.position) / gbounds.dimensions; gpos.y = 1 - gpos.y; gpos = gpos * graphBounds.dimensions + graphBounds.position; nvgBeginPath(nvg); nvgMoveTo(nvg, cursorPosition.x, gbounds.position.y); nvgLineTo(nvg, cursorPosition.x, gbounds.position.y + gbounds.dimensions.y); nvgStrokeWidth(nvg, 1.0f); nvgStrokeColor(nvg, context->theme.DARK.toSemiTransparent(0.25f)); nvgStroke(nvg); nvgBeginPath(nvg); nvgMoveTo(nvg, gbounds.position.x, cursorPosition.y); nvgLineTo(nvg, gbounds.position.x + gbounds.dimensions.x, cursorPosition.y); nvgStrokeWidth(nvg, 1.0f); nvgStrokeColor(nvg, context->theme.DARK.toSemiTransparent(0.25f)); nvgStroke(nvg); } for (GraphDataPtr& curve : curves) { std::vector<float2> points = curve->points; if (points.size() > 1 && graphBounds.dimensions.x > 0.0f && graphBounds.dimensions.y > 0.0f) { NVGcontext* nvg = context->nvgContext; float2 last = points[0]; last = (last - graphBounds.position) / graphBounds.dimensions; last.y = 1.0f - last.y; last = last * gbounds.dimensions + gbounds.position; nvgBeginPath(nvg); nvgMoveTo(nvg, last.x, last.y); for (int i = 1; i < (int)points.size(); i++) { float2 pt = points[i]; pt = (pt - graphBounds.position) / graphBounds.dimensions; pt.y = 1.0f - pt.y; pt = pt * gbounds.dimensions + gbounds.position; nvgLineTo(nvg, pt.x, pt.y); last = pt; } nvgStrokeWidth(nvg, 2.0f); nvgStrokeColor(nvg, curve->color); nvgStroke(nvg); } } nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); nvgFontSize(nvg, LARGE_TEXT); nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_TOP); drawText(nvg, rbounds.position + float2(rbounds.dimensions.x / 2, 2.0f), name, FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); nvgFontSize(nvg, MEDIUM_TEXT); nvgFontFaceId(nvg, context->getFontHandle(FontType::Bold)); nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM); drawText(nvg, rbounds.position + float2(rbounds.dimensions.x / 2, rbounds.dimensions.y - 4.0f), xAxisLabel, FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_CENTER | NVG_ALIGN_TOP); nvgSave(nvg); pixel2 center = rbounds.position + float2(2.0f, rbounds.dimensions.y * 0.5f); nvgTranslate(nvg, center.x, center.y); nvgRotate(nvg, -ALY_PI * 0.5f); drawText(nvg, pixel2(0, 2), yAxisLabel, FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); nvgRestore(nvg); nvgFontSize(nvg, SMALL_TEXT); nvgTextAlign(nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP); drawText(nvg, rbounds.position + float2(GRAPH_PADDING, GRAPH_PADDING), MakeString() << std::setprecision(2) << (graphBounds.position.y + graphBounds.dimensions.y), FontStyle::Outline, context->theme.LIGHTER, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM); drawText(nvg, rbounds.position + float2(GRAPH_PADDING, rbounds.dimensions.y - GRAPH_PADDING), MakeString() << std::setprecision(2) << graphBounds.position.y, FontStyle::Outline, context->theme.LIGHTER, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP); drawText(nvg, rbounds.position + float2(rbounds.dimensions.x - GRAPH_PADDING, rbounds.dimensions.y - GRAPH_PADDING + 2), MakeString() << std::setprecision(2) << (graphBounds.position.x + graphBounds.dimensions.x), FontStyle::Outline, context->theme.LIGHTER, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_TOP); drawText(nvg, rbounds.position + float2(GRAPH_PADDING, rbounds.dimensions.y - GRAPH_PADDING + 2), MakeString() << std::setprecision(2) << graphBounds.position.x, FontStyle::Outline, context->theme.LIGHTER, context->theme.DARK); if (cursorPosition.x >= 0) { float minDist = 1E30f; float bestY = 0; GraphDataPtr closestCurve; for (GraphDataPtr& curve : curves) { float y = curve->interpolate(gpos.x); if (y != GraphData::NO_INTERSECT) { if (std::abs(y - gpos.y) < minDist) { minDist = std::abs(y - gpos.y); bestY = y; closestCurve = curve; } } } if (closestCurve.get() != nullptr) { nvgBeginPath(nvg); nvgStrokeWidth(nvg, 2.0f); nvgFillColor(nvg, closestCurve->color); nvgStrokeColor(nvg, context->theme.LIGHTER); float2 pt(gpos.x, bestY); pt = (pt - graphBounds.position) / graphBounds.dimensions; pt.y = 1.0f - pt.y; pt = pt * gbounds.dimensions + gbounds.position; nvgCircle(nvg, pt.x, pt.y, 4); nvgFill(nvg); nvgStroke(nvg); nvgBeginPath(nvg); nvgFillColor(nvg, context->theme.DARK); nvgCircle(nvg, cursorPosition.x, cursorPosition.y, 2); nvgFill(nvg); nvgTextAlign(nvg, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE); nvgFontSize(nvg, MEDIUM_TEXT); drawText(nvg, float2(pt.x - 8, pt.y), closestCurve->name, FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); nvgTextAlign(nvg, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); drawText(nvg, float2(pt.x + 8, pt.y), MakeString() << "(" << std::setprecision(2) << gpos.x << ", " << std::setprecision(2) << bestY << ")", FontStyle::Outline, context->theme.LIGHTEST, context->theme.DARK); } else { nvgBeginPath(nvg); nvgFillColor(nvg, context->theme.DARK); nvgCircle(nvg, cursorPosition.x, cursorPosition.y, 2); nvgFill(nvg); } } }
void NVGRenderer::fontFaceId(int font) { nvgFontFaceId(m_context, font); }
void QNanoPainter::setFont(QNanoFont &font) { font.setParentPainter(this); nvgFontFaceId(nvgCtx(), font.getID(nvgCtx())); m_fontSet = true; }
JNIEXPORT void JNICALL Java_firststep_internal_NVG_fontFaceId (JNIEnv *e, jclass c, jlong ctx, jint fid) { nvgFontFaceId((NVGcontext*)ctx, fid); }