bl_demo_pattern.cpp (8694B)
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 #include "../bench/images_data.h" 9 10 class MainWindow : public QWidget { 11 Q_OBJECT 12 13 public: 14 QTimer _timer; 15 QComboBox _renderer_select; 16 QComboBox _extend_mode_select; 17 QCheckBox _limit_fps_check; 18 QCheckBox _bilinear_check_box; 19 QCheckBox _fill_path_check_box; 20 QSlider _frac_x; 21 QSlider _frac_y; 22 QSlider _angle; 23 QSlider _scale; 24 QBLCanvas _canvas; 25 BLImage _sprites_blend2d[4]; 26 QImage _sprites_qt[4]; 27 28 MainWindow() { 29 QVBoxLayout* vBox = new QVBoxLayout(); 30 vBox->setContentsMargins(0, 0, 0, 0); 31 vBox->setSpacing(0); 32 33 QGridLayout* grid = new QGridLayout(); 34 grid->setContentsMargins(5, 5, 5, 5); 35 grid->setSpacing(5); 36 37 QBLCanvas::init_renderer_select_box(&_renderer_select); 38 _limit_fps_check.setText(QLatin1String("Limit FPS")); 39 _bilinear_check_box.setText(QLatin1String("Bilinear")); 40 _fill_path_check_box.setText(QLatin1String("Fill Path")); 41 42 static const char* extendModeNames[] = { 43 "PAD", 44 "REPEAT", 45 "REFLECT", 46 "PAD-X PAD-Y", 47 "PAD-X REPEAT-Y", 48 "PAD-X REFLECT-Y", 49 "REPEAT-X PAD-Y", 50 "REPEAT-X REPEAT-Y", 51 "REPEAT-X REFLECT-Y", 52 "REFLECT-X PAD-Y", 53 "REFLECT-X REPEAT-Y", 54 "REFLECT-X REFLECT-Y" 55 }; 56 57 static const BLExtendMode extendModeValues[] = { 58 BL_EXTEND_MODE_PAD, 59 BL_EXTEND_MODE_REPEAT, 60 BL_EXTEND_MODE_REFLECT, 61 BL_EXTEND_MODE_PAD_X_PAD_Y, 62 BL_EXTEND_MODE_PAD_X_REPEAT_Y, 63 BL_EXTEND_MODE_PAD_X_REFLECT_Y, 64 BL_EXTEND_MODE_REPEAT_X_PAD_Y, 65 BL_EXTEND_MODE_REPEAT_X_REPEAT_Y, 66 BL_EXTEND_MODE_REPEAT_X_REFLECT_Y, 67 BL_EXTEND_MODE_REFLECT_X_PAD_Y, 68 BL_EXTEND_MODE_REFLECT_X_REPEAT_Y, 69 BL_EXTEND_MODE_REFLECT_X_REFLECT_Y 70 }; 71 72 for (uint32_t i = 0; i < 12; i++) { 73 QString s = extendModeNames[i]; 74 _extend_mode_select.addItem(s, QVariant(int(extendModeValues[i]))); 75 } 76 _extend_mode_select.setCurrentIndex(1); 77 78 _frac_x.setMinimum(0); 79 _frac_x.setMaximum(255); 80 _frac_x.setValue(0); 81 _frac_x.setOrientation(Qt::Horizontal); 82 83 _frac_y.setMinimum(0); 84 _frac_y.setMaximum(255); 85 _frac_y.setValue(0); 86 _frac_y.setOrientation(Qt::Horizontal); 87 88 _angle.setMinimum(0); 89 _angle.setMaximum(3600); 90 _angle.setValue(0); 91 _angle.setOrientation(Qt::Horizontal); 92 93 _scale.setMinimum(0); 94 _scale.setMaximum(1000); 95 _scale.setValue(0); 96 _scale.setOrientation(Qt::Horizontal); 97 98 connect(&_renderer_select, SIGNAL(activated(int)), SLOT(onRendererChanged(int))); 99 connect(&_limit_fps_check, SIGNAL(stateChanged(int)), SLOT(onLimitFpsChanged(int))); 100 connect(&_bilinear_check_box, SIGNAL(valueChanged(int)), SLOT(onSliderChanged(int))); 101 connect(&_fill_path_check_box, SIGNAL(valueChanged(int)), SLOT(onSliderChanged(int))); 102 connect(&_extend_mode_select, SIGNAL(activated(int)), SLOT(onSliderChanged(int))); 103 connect(&_frac_x, SIGNAL(valueChanged(int)), SLOT(onSliderChanged(int))); 104 connect(&_frac_y, SIGNAL(valueChanged(int)), SLOT(onSliderChanged(int))); 105 connect(&_angle, SIGNAL(valueChanged(int)), SLOT(onSliderChanged(int))); 106 connect(&_scale, SIGNAL(valueChanged(int)), SLOT(onSliderChanged(int))); 107 108 grid->addWidget(new QLabel("Renderer:"), 0, 0); 109 grid->addWidget(&_renderer_select, 0, 1); 110 111 grid->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding), 0, 4); 112 grid->addWidget(&_limit_fps_check, 0, 5); 113 114 grid->addWidget(new QLabel("Extend Mode:"), 1, 0); 115 grid->addWidget(&_extend_mode_select, 1, 1); 116 117 grid->addWidget(new QLabel("Fx Offset:"), 0, 2); 118 grid->addWidget(&_frac_x, 0, 3, 1, 2); 119 120 grid->addItem(new QSpacerItem(1, 0, QSizePolicy::Expanding), 0, 4); 121 grid->addWidget(&_bilinear_check_box, 1, 5); 122 123 grid->addItem(new QSpacerItem(2, 0, QSizePolicy::Expanding), 0, 4); 124 grid->addWidget(&_fill_path_check_box, 2, 5); 125 126 grid->addWidget(new QLabel("Fy Offset:"), 1, 2); 127 grid->addWidget(&_frac_y, 1, 3, 1, 2); 128 129 grid->addWidget(new QLabel("Angle:"), 2, 0); 130 grid->addWidget(&_angle, 2, 1, 1, 4); 131 132 grid->addWidget(new QLabel("Scale:"), 3, 0); 133 grid->addWidget(&_scale, 3, 1, 1, 4); 134 135 _canvas.on_render_blend2d = std::bind(&MainWindow::on_render_blend2d, this, std::placeholders::_1); 136 _canvas.on_render_qt = std::bind(&MainWindow::on_render_qt, this, std::placeholders::_1); 137 138 vBox->addItem(grid); 139 vBox->addWidget(&_canvas); 140 setLayout(vBox); 141 142 connect(&_timer, SIGNAL(timeout()), this, SLOT(onTimer())); 143 onInit(); 144 } 145 146 void showEvent(QShowEvent* event) override { _timer.start(); } 147 void hideEvent(QHideEvent* event) override { _timer.stop(); } 148 void keyPressEvent(QKeyEvent* event) override {} 149 150 void onInit() { 151 _limit_fps_check.setChecked(true); 152 _bilinear_check_box.setChecked(true); 153 154 _sprites_blend2d[0].read_from_data(_resource_babelfish_png, sizeof(_resource_babelfish_png)); 155 _sprites_blend2d[1].read_from_data(_resource_ksplash_png , sizeof(_resource_ksplash_png )); 156 _sprites_blend2d[2].read_from_data(_resource_ktip_png , sizeof(_resource_ktip_png )); 157 _sprites_blend2d[3].read_from_data(_resource_firewall_png , sizeof(_resource_firewall_png )); 158 159 for (uint32_t i = 0; i < 4; i++) { 160 const BLImage& sprite = _sprites_blend2d[i]; 161 162 BLImageData sprite_data; 163 sprite.get_data(&sprite_data); 164 165 _sprites_qt[i] = QImage( 166 static_cast<unsigned char*>(sprite_data.pixel_data), 167 sprite_data.size.w, 168 sprite_data.size.h, 169 int(sprite_data.stride), QImage::Format_ARGB32_Premultiplied); 170 } 171 172 _updateTitle(); 173 } 174 175 Q_SLOT void onRendererChanged(int index) { _canvas.set_renderer_type(_renderer_select.itemData(index).toInt()); } 176 Q_SLOT void onLimitFpsChanged(int value) { _timer.setInterval(value ? 1000 / 120 : 0); } 177 178 Q_SLOT void onSliderChanged(int value) { _canvas.update_canvas(true); } 179 180 Q_SLOT void onTimer() { 181 _canvas.update_canvas(true); 182 _updateTitle(); 183 } 184 185 inline double tx() const { return 256.0 + double(_frac_x.value()) / 256.0; } 186 inline double ty() const { return 256.0 + double(_frac_y.value()) / 256.0; } 187 inline double angle_in_radians() const { return (double(_angle.value()) / (3600.0 / 2)) * M_PI; } 188 inline double scale() const { return double(_scale.value() + 100) / 100.0; } 189 190 void on_render_blend2d(BLContext& ctx) noexcept { 191 int rx = _canvas.image_width() / 2; 192 int ry = _canvas.image_height() / 2; 193 194 BLPattern pattern(_sprites_blend2d[0], BLExtendMode(_extend_mode_select.currentData().toInt())); 195 pattern.rotate(angle_in_radians(), rx, ry); 196 pattern.translate(tx(), ty()); 197 pattern.scale(scale()); 198 199 ctx.set_pattern_quality( 200 _bilinear_check_box.isChecked() 201 ? BL_PATTERN_QUALITY_BILINEAR 202 : BL_PATTERN_QUALITY_NEAREST); 203 204 ctx.set_comp_op(BL_COMP_OP_SRC_COPY); 205 206 if (_fill_path_check_box.isChecked()) { 207 ctx.clear_all(); 208 ctx.fill_circle(rx, ry, bl_min(rx, ry), pattern); 209 } 210 else { 211 ctx.fill_all(pattern); 212 } 213 } 214 215 void on_render_qt(QPainter& ctx) noexcept { 216 int rx = _canvas.image_width() / 2; 217 int ry = _canvas.image_height() / 2; 218 219 QTransform tr; 220 tr.translate(rx, ry); 221 tr.rotateRadians(angle_in_radians()); 222 tr.translate(-rx + tx(), -ry + ty()); 223 tr.scale(scale(), scale()); 224 225 QBrush brush(_sprites_qt[0]); 226 brush.setTransform(tr); 227 228 ctx.setRenderHint(QPainter::SmoothPixmapTransform, _bilinear_check_box.isChecked()); 229 ctx.setRenderHint(QPainter::Antialiasing, true); 230 ctx.setCompositionMode(QPainter::CompositionMode_Source); 231 232 if (_fill_path_check_box.isChecked()) { 233 double r = bl_min(rx, ry); 234 ctx.fillRect(QRect(0, 0, _canvas.image_width(), _canvas.image_height()), QColor(0, 0, 0, 0)); 235 ctx.setBrush(brush); 236 ctx.setPen(Qt::NoPen); 237 ctx.drawEllipse(QPointF(qreal(rx), qreal(ry)), qreal(r), qreal(r)); 238 } 239 else { 240 ctx.fillRect(QRect(0, 0, _canvas.image_width(), _canvas.image_height()), brush); 241 } 242 } 243 244 void _updateTitle() { 245 char buf[256]; 246 247 snprintf(buf, 256, "Patterns [%dx%d] [RenderTime=%.2fms FPS=%.1f]", 248 _canvas.image_width(), 249 _canvas.image_height(), 250 _canvas.average_render_time(), 251 _canvas.fps()); 252 253 QString title = QString::fromUtf8(buf); 254 if (title != windowTitle()) 255 setWindowTitle(title); 256 } 257 }; 258 259 int main(int argc, char *argv[]) { 260 QApplication app(argc, argv); 261 MainWindow win; 262 263 win.setMinimumSize(QSize(20 + (128 + 10) * 4 + 20, 20 + (128 + 10) * 4 + 20)); 264 win.resize(QSize(580, 520)); 265 win.show(); 266 267 return app.exec(); 268 } 269 270 #include "bl_demo_pattern.moc"