odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

bl_demo_circles.cpp (4875B)


      1 #include <stdlib.h>
      2 #include <cmath>
      3 #include <vector>
      4 
      5 #include "bl_qt_headers.h"
      6 #include "bl_qt_canvas.h"
      7 
      8 class MainWindow : public QWidget {
      9   Q_OBJECT
     10 
     11 public:
     12   QTimer _timer;
     13   QComboBox _renderer_select;
     14   QCheckBox _limit_fps_check;
     15   QSlider _count_slider;
     16   QBLCanvas _canvas;
     17 
     18   bool _animate = true;
     19   double _angle {};
     20   int _count {};
     21 
     22   MainWindow() {
     23     QVBoxLayout* vBox = new QVBoxLayout();
     24     vBox->setContentsMargins(0, 0, 0, 0);
     25     vBox->setSpacing(0);
     26 
     27     QGridLayout* grid = new QGridLayout();
     28     grid->setContentsMargins(5, 5, 5, 5);
     29     grid->setSpacing(5);
     30 
     31     QBLCanvas::init_renderer_select_box(&_renderer_select);
     32     _limit_fps_check.setText(QLatin1String("Limit FPS"));
     33 
     34     _count_slider.setMinimum(100);
     35     _count_slider.setMaximum(2000);
     36     _count_slider.setValue(500);
     37     _count_slider.setOrientation(Qt::Horizontal);
     38 
     39     connect(&_renderer_select, SIGNAL(activated(int)), SLOT(onRendererChanged(int)));
     40     connect(&_limit_fps_check, SIGNAL(stateChanged(int)), SLOT(onLimitFpsChanged(int)));
     41 
     42     grid->addWidget(new QLabel("Renderer:"), 0, 0);
     43     grid->addWidget(&_renderer_select, 0, 1);
     44 
     45     grid->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding), 0, 2);
     46     grid->addWidget(&_limit_fps_check, 0, 3, Qt::AlignRight);
     47 
     48     grid->addWidget(new QLabel("Count:"), 1, 0, Qt::AlignRight);
     49     grid->addWidget(&_count_slider, 1, 1, 1, 4);
     50 
     51     _canvas.on_render_blend2d = std::bind(&MainWindow::on_render_blend2d, this, std::placeholders::_1);
     52     _canvas.on_render_qt = std::bind(&MainWindow::on_render_qt, this, std::placeholders::_1);
     53 
     54     vBox->addItem(grid);
     55     vBox->addWidget(&_canvas);
     56     setLayout(vBox);
     57 
     58     connect(&_timer, SIGNAL(timeout()), this, SLOT(onTimer()));
     59     connect(new QShortcut(QKeySequence(Qt::Key_P), this), SIGNAL(activated()), SLOT(onToggleAnimate()));
     60 
     61     onInit();
     62   }
     63 
     64   void showEvent(QShowEvent* event) override { _timer.start(); }
     65   void hideEvent(QHideEvent* event) override { _timer.stop(); }
     66   void keyPressEvent(QKeyEvent* event) override {}
     67 
     68   void onInit() {
     69     _angle = 0;
     70     _count = 0;
     71     _limit_fps_check.setChecked(true);
     72     _updateTitle();
     73   }
     74 
     75   Q_SLOT void onToggleAnimate() { _animate = !_animate; }
     76   Q_SLOT void onRendererChanged(int index) { _canvas.set_renderer_type(_renderer_select.itemData(index).toInt()); }
     77   Q_SLOT void onLimitFpsChanged(int value) { _timer.setInterval(value ? 1000 / 120 : 0); }
     78 
     79   Q_SLOT void onTimer() {
     80     if (_animate) {
     81       _angle += 0.05;
     82       if (_angle >= 360)
     83         _angle -= 360;
     84     }
     85 
     86     _canvas.update_canvas(true);
     87     _updateTitle();
     88   }
     89 
     90   // The idea is based on:
     91   //   https://github.com/fogleman/gg/blob/master/examples/spiral.go
     92 
     93   void on_render_blend2d(BLContext& ctx) noexcept {
     94     ctx.fill_all(BLRgba32(0xFF000000u));
     95 
     96     BLPath p;
     97 
     98     int count = _count_slider.value();
     99     double PI = 3.14159265359;
    100 
    101     double cx = _canvas.image_width() / 2;
    102     double cy = _canvas.image_height() / 2;
    103     double maxDist = 1000.0;
    104     double baseAngle = _angle / 180.0 * PI;
    105 
    106     for (int i = 0; i < count; i++) {
    107       double t = double(i) * 1.01 / 1000;
    108       double d = t * 1000.0 * 0.4 + 10;
    109       double a = baseAngle + t * PI * 2 * 20;
    110       double x = cx + std::cos(a) * d;
    111       double y = cy + std::sin(a) * d;
    112       double r = std::min(t * 8 + 0.5, 10.0);
    113       p.add_circle(BLCircle(x, y, r));
    114     }
    115 
    116     ctx.fill_path(p, BLRgba32(0xFFFFFFFFu));
    117   }
    118 
    119   void on_render_qt(QPainter& ctx) noexcept {
    120     ctx.fillRect(0, 0, _canvas.image_width(), _canvas.image_height(), QColor(0, 0, 0));
    121     ctx.setRenderHint(QPainter::Antialiasing, true);
    122 
    123     QPainterPath p;
    124     QBrush brush(QColor(qRgb(255, 255, 255)));
    125 
    126     int count = _count_slider.value();
    127     double PI = 3.14159265359;
    128 
    129     double cx = _canvas.image_width() / 2;
    130     double cy = _canvas.image_height() / 2;
    131     double baseAngle = _angle / 180.0 * PI;
    132 
    133     for (int i = 0; i < count; i++) {
    134       double t = double(i) * 1.01 / 1000;
    135       double d = t * 1000.0 * 0.4 + 10;
    136       double a = baseAngle + t * PI * 2 * 20;
    137       double x = cx + std::cos(a) * d;
    138       double y = cy + std::sin(a) * d;
    139       double r = std::min(t * 8 + 0.5, 10.0);
    140       p.addEllipse(x - r, y - r, r * 2.0, r * 2.0);
    141     }
    142 
    143     ctx.fillPath(p, brush);
    144   }
    145 
    146   void _updateTitle() {
    147     char buf[256];
    148     snprintf(buf, 256, "Circles [%dx%d] [Count=%d] [RenderTime=%.2fms FPS=%.1f]",
    149       _canvas.image_width(),
    150       _canvas.image_height(),
    151       _count_slider.value(),
    152       _canvas.average_render_time(),
    153       _canvas.fps());
    154 
    155     QString title = QString::fromUtf8(buf);
    156     if (title != windowTitle())
    157       setWindowTitle(title);
    158   }
    159 };
    160 
    161 int main(int argc, char *argv[]) {
    162   QApplication app(argc, argv);
    163   MainWindow win;
    164 
    165   win.setMinimumSize(QSize(400, 320));
    166   win.resize(QSize(580, 520));
    167   win.show();
    168 
    169   return app.exec();
    170 }
    171 
    172 #include "bl_demo_circles.moc"