bl_bench_backend_qt.cpp (20355B)
1 // This file is part of Blend2D project <https://blend2d.com> 2 // 3 // See LICENSE.md for license and copyright information 4 // SPDX-License-Identifier: Zlib 5 6 #ifdef BL_BENCH_ENABLE_QT 7 8 #include "bl_bench_app.h" 9 #include "bl_bench_backend.h" 10 11 #include <QtCore> 12 #include <QtGui> 13 14 namespace blbench { 15 16 static inline QColor to_qt_color(const BLRgba32& rgba) { 17 return QColor(rgba.r(), rgba.g(), rgba.b(), rgba.a()); 18 } 19 20 static uint32_t to_qt_format(BLFormat format) { 21 switch (format) { 22 case BL_FORMAT_PRGB32: return QImage::Format_ARGB32_Premultiplied; 23 case BL_FORMAT_XRGB32: return QImage::Format_RGB32; 24 25 default: 26 return 0xFFFFFFFFu; 27 } 28 } 29 30 static uint32_t to_qt_operator(BLCompOp comp_op) { 31 switch (comp_op) { 32 case BL_COMP_OP_SRC_OVER : return QPainter::CompositionMode_SourceOver; 33 case BL_COMP_OP_SRC_COPY : return QPainter::CompositionMode_Source; 34 case BL_COMP_OP_SRC_IN : return QPainter::CompositionMode_SourceIn; 35 case BL_COMP_OP_SRC_OUT : return QPainter::CompositionMode_SourceOut; 36 case BL_COMP_OP_SRC_ATOP : return QPainter::CompositionMode_SourceAtop; 37 case BL_COMP_OP_DST_OVER : return QPainter::CompositionMode_DestinationOver; 38 case BL_COMP_OP_DST_COPY : return QPainter::CompositionMode_Destination; 39 case BL_COMP_OP_DST_IN : return QPainter::CompositionMode_DestinationIn; 40 case BL_COMP_OP_DST_OUT : return QPainter::CompositionMode_DestinationOut; 41 case BL_COMP_OP_DST_ATOP : return QPainter::CompositionMode_DestinationAtop; 42 case BL_COMP_OP_XOR : return QPainter::CompositionMode_Xor; 43 case BL_COMP_OP_CLEAR : return QPainter::CompositionMode_Clear; 44 case BL_COMP_OP_PLUS : return QPainter::CompositionMode_Plus; 45 case BL_COMP_OP_MULTIPLY : return QPainter::CompositionMode_Multiply; 46 case BL_COMP_OP_SCREEN : return QPainter::CompositionMode_Screen; 47 case BL_COMP_OP_OVERLAY : return QPainter::CompositionMode_Overlay; 48 case BL_COMP_OP_DARKEN : return QPainter::CompositionMode_Darken; 49 case BL_COMP_OP_LIGHTEN : return QPainter::CompositionMode_Lighten; 50 case BL_COMP_OP_COLOR_DODGE: return QPainter::CompositionMode_ColorDodge; 51 case BL_COMP_OP_COLOR_BURN : return QPainter::CompositionMode_ColorBurn; 52 case BL_COMP_OP_HARD_LIGHT : return QPainter::CompositionMode_HardLight; 53 case BL_COMP_OP_SOFT_LIGHT : return QPainter::CompositionMode_SoftLight; 54 case BL_COMP_OP_DIFFERENCE : return QPainter::CompositionMode_Difference; 55 case BL_COMP_OP_EXCLUSION : return QPainter::CompositionMode_Exclusion; 56 57 default: 58 return 0xFFFFFFFFu; 59 } 60 } 61 62 struct QtModule : public Backend { 63 QImage* _qt_surface {}; 64 QImage* _qt_sprites[kBenchNumSprites] {}; 65 QPainter* _qt_context {}; 66 67 // Initialized by before_run(). 68 uint32_t _gradient_spread {}; 69 70 QtModule(); 71 ~QtModule() override; 72 73 void serialize_info(JSONBuilder& json) const override; 74 75 template<typename RectT> 76 inline QBrush create_brush(StyleKind style, const RectT& rect); 77 78 bool supports_comp_op(BLCompOp comp_op) const override; 79 bool supports_style(StyleKind style) const override; 80 81 void before_run() override; 82 void flush() override; 83 void after_run() override; 84 85 void render_rect_a(RenderOp op) override; 86 void render_rect_f(RenderOp op) override; 87 void render_rect_rotated(RenderOp op) override; 88 void render_round_f(RenderOp op) override; 89 void render_round_rotated(RenderOp op) override; 90 void render_polygon(RenderOp op, uint32_t complexity) override; 91 void render_shape(RenderOp op, ShapeData shape) override; 92 }; 93 94 QtModule::QtModule() { 95 strcpy(_name, "Qt6"); 96 } 97 QtModule::~QtModule() {} 98 99 void QtModule::serialize_info(JSONBuilder& json) const { 100 json.before_record() 101 .add_key("version") 102 .add_string(qVersion()); 103 } 104 105 template<typename RectT> 106 inline QBrush QtModule::create_brush(StyleKind style, const RectT& rect) { 107 switch (style) { 108 case StyleKind::kLinearPad: 109 case StyleKind::kLinearRepeat: 110 case StyleKind::kLinearReflect: { 111 double x0 = rect.x + rect.w * 0.2; 112 double y0 = rect.y + rect.h * 0.2; 113 double x1 = rect.x + rect.w * 0.8; 114 double y1 = rect.y + rect.h * 0.8; 115 116 QLinearGradient g((qreal)x0, (qreal)y0, (qreal)x1, (qreal)y1); 117 g.setColorAt(qreal(0.0), to_qt_color(_rnd_color.next_rgba32())); 118 g.setColorAt(qreal(0.5), to_qt_color(_rnd_color.next_rgba32())); 119 g.setColorAt(qreal(1.0), to_qt_color(_rnd_color.next_rgba32())); 120 g.setSpread(static_cast<QGradient::Spread>(_gradient_spread)); 121 return QBrush(g); 122 } 123 124 case StyleKind::kRadialPad: 125 case StyleKind::kRadialRepeat: 126 case StyleKind::kRadialReflect: { 127 double cx = rect.x + rect.w / 2; 128 double cy = rect.y + rect.h / 2; 129 double cr = (rect.w + rect.h) / 4; 130 double fx = cx - cr / 2; 131 double fy = cy - cr / 2; 132 133 QRadialGradient g(qreal(cx), qreal(cy), qreal(cr), qreal(fx), qreal(fy), qreal(0)); 134 g.setColorAt(qreal(0.0), to_qt_color(_rnd_color.next_rgba32())); 135 g.setColorAt(qreal(0.5), to_qt_color(_rnd_color.next_rgba32())); 136 g.setColorAt(qreal(1.0), to_qt_color(_rnd_color.next_rgba32())); 137 g.setSpread(static_cast<QGradient::Spread>(_gradient_spread)); 138 return QBrush(g); 139 } 140 141 case StyleKind::kConic: { 142 double cx = rect.x + rect.w / 2; 143 double cy = rect.y + rect.h / 2; 144 QColor c(to_qt_color(_rnd_color.next_rgba32())); 145 146 QConicalGradient g(qreal(cx), qreal(cy), qreal(0)); 147 g.setColorAt(qreal(0.00), c); 148 g.setColorAt(qreal(0.33), to_qt_color(_rnd_color.next_rgba32())); 149 g.setColorAt(qreal(0.66), to_qt_color(_rnd_color.next_rgba32())); 150 g.setColorAt(qreal(1.00), c); 151 return QBrush(g); 152 } 153 154 case StyleKind::kPatternNN: 155 case StyleKind::kPatternBI: 156 default: { 157 QBrush brush(*_qt_sprites[nextSpriteId()]); 158 159 // FIXME: It seems that Qt will never use subpixel filtering when drawing 160 // an unscaled image. The test suite, however, expects that path to be 161 // triggered. To fix this, we scale the image slightly (it should have no 162 // visual impact) to prevent Qt using nearest-neighbor fast-path. 163 qreal scale = style == StyleKind::kPatternNN ? 1.0 : 1.00001; 164 165 brush.setTransform(QTransform(scale, qreal(0), qreal(0), scale, qreal(rect.x), qreal(rect.y))); 166 return brush; 167 } 168 } 169 } 170 171 bool QtModule::supports_comp_op(BLCompOp comp_op) const { 172 return to_qt_operator(comp_op) != 0xFFFFFFFFu; 173 } 174 175 bool QtModule::supports_style(StyleKind style) const { 176 return style == StyleKind::kSolid || 177 style == StyleKind::kLinearPad || 178 style == StyleKind::kLinearRepeat || 179 style == StyleKind::kLinearReflect || 180 style == StyleKind::kRadialPad || 181 style == StyleKind::kRadialRepeat || 182 style == StyleKind::kRadialReflect || 183 style == StyleKind::kConic || 184 style == StyleKind::kPatternNN || 185 style == StyleKind::kPatternBI ; 186 } 187 188 void QtModule::before_run() { 189 int w = int(_params.screen_w); 190 int h = int(_params.screen_h); 191 StyleKind style = _params.style; 192 193 // Initialize the sprites. 194 for (uint32_t i = 0; i < kBenchNumSprites; i++) { 195 const BLImage& sprite = _sprites[i]; 196 197 BLImageData sprite_data; 198 sprite.get_data(&sprite_data); 199 200 QImage* qt_sprite = new QImage( 201 static_cast<unsigned char*>(sprite_data.pixel_data), 202 sprite_data.size.w, 203 sprite_data.size.h, 204 int(sprite_data.stride), QImage::Format_ARGB32_Premultiplied); 205 206 _qt_sprites[i] = qt_sprite; 207 } 208 209 // Initialize the surface and the context. 210 BLImageData surface_data; 211 _surface.create(w, h, _params.format); 212 _surface.make_mutable(&surface_data); 213 214 int stride = int(surface_data.stride); 215 int qtFormat = to_qt_format(BLFormat(surface_data.format)); 216 217 _qt_surface = new QImage( 218 (unsigned char*)surface_data.pixel_data, w, h, 219 stride, static_cast<QImage::Format>(qtFormat)); 220 221 if (_qt_surface == nullptr) { 222 return; 223 } 224 225 _qt_context = new QPainter(_qt_surface); 226 227 if (_qt_context == nullptr) { 228 return; 229 } 230 231 // Setup the context. 232 _qt_context->setCompositionMode(QPainter::CompositionMode_Source); 233 _qt_context->fillRect(0, 0, w, h, QColor(0, 0, 0, 0)); 234 235 _qt_context->setCompositionMode( 236 static_cast<QPainter::CompositionMode>( 237 to_qt_operator(_params.comp_op))); 238 239 _qt_context->setRenderHint(QPainter::Antialiasing, true); 240 _qt_context->setRenderHint(QPainter::SmoothPixmapTransform, _params.style != StyleKind::kPatternNN); 241 242 // Setup globals. 243 _gradient_spread = QGradient::PadSpread; 244 245 switch (style) { 246 case StyleKind::kLinearPad : _gradient_spread = QGradient::PadSpread ; break; 247 case StyleKind::kLinearRepeat : _gradient_spread = QGradient::RepeatSpread ; break; 248 case StyleKind::kLinearReflect : _gradient_spread = QGradient::ReflectSpread; break; 249 case StyleKind::kRadialPad : _gradient_spread = QGradient::PadSpread ; break; 250 case StyleKind::kRadialRepeat : _gradient_spread = QGradient::RepeatSpread ; break; 251 case StyleKind::kRadialReflect : _gradient_spread = QGradient::ReflectSpread; break; 252 253 default: 254 break; 255 } 256 } 257 258 void QtModule::flush() { 259 // Nothing... 260 } 261 262 void QtModule::after_run() { 263 // Free the surface & the context. 264 delete _qt_context; 265 delete _qt_surface; 266 267 _qt_context = nullptr; 268 _qt_surface = nullptr; 269 270 // Free the sprites. 271 for (uint32_t i = 0; i < kBenchNumSprites; i++) { 272 delete _qt_sprites[i]; 273 _qt_sprites[i] = nullptr; 274 } 275 } 276 277 void QtModule::render_rect_a(RenderOp op) { 278 BLSizeI bounds(_params.screen_w, _params.screen_h); 279 StyleKind style = _params.style; 280 int wh = _params.shape_size; 281 282 if (op == RenderOp::kStroke) 283 _qt_context->setBrush(Qt::NoBrush); 284 285 if (style == StyleKind::kSolid) { 286 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++) { 287 BLRectI rect(_rnd_coord.next_rect_i(bounds, wh, wh)); 288 QColor color(to_qt_color(_rnd_color.next_rgba32())); 289 290 if (op == RenderOp::kStroke) { 291 _qt_context->setPen(color); 292 _qt_context->drawRect(QRectF(rect.x, rect.y, rect.w, rect.h)); 293 } 294 else { 295 _qt_context->fillRect(QRect(rect.x, rect.y, rect.w, rect.h), color); 296 } 297 } 298 } 299 else { 300 if ((style == StyleKind::kPatternNN || style == StyleKind::kPatternBI) && op != RenderOp::kStroke) { 301 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++) { 302 BLRectI rect(_rnd_coord.next_rect_i(bounds, wh, wh)); 303 const QImage& sprite = *_qt_sprites[nextSpriteId()]; 304 305 _qt_context->drawImage(QPoint(rect.x, rect.y), sprite); 306 } 307 } 308 else { 309 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++) { 310 BLRectI rect(_rnd_coord.next_rect_i(bounds, wh, wh)); 311 QBrush brush(create_brush<BLRectI>(style, rect)); 312 313 if (op == RenderOp::kStroke) { 314 QPen pen(brush, qreal(_params.stroke_width)); 315 pen.setJoinStyle(Qt::MiterJoin); 316 _qt_context->setPen(pen); 317 _qt_context->drawRect(QRectF(rect.x, rect.y, rect.w, rect.h)); 318 } 319 else { 320 _qt_context->fillRect(QRect(rect.x, rect.y, rect.w, rect.h), brush); 321 } 322 } 323 } 324 } 325 } 326 327 void QtModule::render_rect_f(RenderOp op) { 328 BLSize bounds(_params.screen_w, _params.screen_h); 329 StyleKind style = _params.style; 330 double wh = _params.shape_size; 331 332 if (op == RenderOp::kStroke) 333 _qt_context->setBrush(Qt::NoBrush); 334 335 if (style == StyleKind::kSolid) { 336 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++) { 337 BLRect rect(_rnd_coord.next_rect(bounds, wh, wh)); 338 QColor color(to_qt_color(_rnd_color.next_rgba32())); 339 340 if (op == RenderOp::kStroke) { 341 _qt_context->setPen(color); 342 _qt_context->drawRect(QRectF(rect.x, rect.y, rect.w, rect.h)); 343 } 344 else { 345 _qt_context->fillRect(QRectF(rect.x, rect.y, rect.w, rect.h), color); 346 } 347 } 348 } 349 else { 350 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++) { 351 BLRect rect(_rnd_coord.next_rect(bounds, wh, wh)); 352 QBrush brush(create_brush<BLRect>(style, rect)); 353 354 if (op == RenderOp::kStroke) { 355 QPen pen(brush, qreal(_params.stroke_width)); 356 pen.setJoinStyle(Qt::MiterJoin); 357 358 _qt_context->setPen(pen); 359 _qt_context->drawRect(QRectF(rect.x, rect.y, rect.w, rect.h)); 360 } 361 else { 362 _qt_context->fillRect(QRectF(rect.x, rect.y, rect.w, rect.h), brush); 363 } 364 } 365 } 366 } 367 368 void QtModule::render_rect_rotated(RenderOp op) { 369 BLSize bounds(_params.screen_w, _params.screen_h); 370 StyleKind style = _params.style; 371 372 double cx = double(_params.screen_w) * 0.5; 373 double cy = double(_params.screen_h) * 0.5; 374 double wh = _params.shape_size; 375 double angle = 0.0; 376 377 if (op == RenderOp::kStroke) 378 _qt_context->setBrush(Qt::NoBrush); 379 380 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++, angle += 0.01) { 381 BLRect rect(_rnd_coord.next_rect(bounds, wh, wh)); 382 383 QTransform transform; 384 transform.translate(cx, cy); 385 transform.rotateRadians(angle); 386 transform.translate(-cx, -cy); 387 _qt_context->setTransform(transform, false); 388 389 if (style == StyleKind::kSolid) { 390 QColor color(to_qt_color(_rnd_color.next_rgba32())); 391 392 if (op == RenderOp::kStroke) { 393 QPen pen(color, qreal(_params.stroke_width)); 394 pen.setJoinStyle(Qt::MiterJoin); 395 396 _qt_context->setPen(pen); 397 _qt_context->drawRect(QRectF(rect.x, rect.y, rect.w, rect.h)); 398 } 399 else { 400 _qt_context->fillRect(QRectF(rect.x, rect.y, rect.w, rect.h), color); 401 } 402 } 403 else { 404 QBrush brush(create_brush<BLRect>(style, rect)); 405 406 if (op == RenderOp::kStroke) { 407 QPen pen(brush, qreal(_params.stroke_width)); 408 pen.setJoinStyle(Qt::MiterJoin); 409 410 _qt_context->setPen(pen); 411 _qt_context->drawRect(QRectF(rect.x, rect.y, rect.w, rect.h)); 412 } 413 else { 414 _qt_context->fillRect(QRectF(rect.x, rect.y, rect.w, rect.h), brush); 415 } 416 } 417 418 _qt_context->resetTransform(); 419 } 420 } 421 422 void QtModule::render_round_f(RenderOp op) { 423 BLSize bounds(_params.screen_w, _params.screen_h); 424 StyleKind style = _params.style; 425 double wh = _params.shape_size; 426 427 if (op == RenderOp::kStroke) 428 _qt_context->setBrush(Qt::NoBrush); 429 else 430 _qt_context->setPen(QPen(Qt::NoPen)); 431 432 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++) { 433 BLRect rect(_rnd_coord.next_rect(bounds, wh, wh)); 434 double radius = _rnd_extra.next_double(4.0, 40.0); 435 436 if (style == StyleKind::kSolid) { 437 QColor color(to_qt_color(_rnd_color.next_rgba32())); 438 439 if (op == RenderOp::kStroke) 440 _qt_context->setPen(QPen(color, qreal(_params.stroke_width))); 441 else 442 _qt_context->setBrush(QBrush(color)); 443 } 444 else { 445 QBrush brush(create_brush<BLRect>(style, rect)); 446 447 if (op == RenderOp::kStroke) 448 _qt_context->setPen(QPen(brush, qreal(_params.stroke_width))); 449 else 450 _qt_context->setBrush(brush); 451 } 452 453 _qt_context->drawRoundedRect( 454 QRectF(rect.x, rect.y, rect.w, rect.h), 455 std::min(rect.w * 0.5, radius), 456 std::min(rect.h * 0.5, radius)); 457 } 458 } 459 460 void QtModule::render_round_rotated(RenderOp op) { 461 BLSize bounds(_params.screen_w, _params.screen_h); 462 StyleKind style = _params.style; 463 464 double cx = double(_params.screen_w) * 0.5; 465 double cy = double(_params.screen_h) * 0.5; 466 double wh = _params.shape_size; 467 double angle = 0.0; 468 469 if (op == RenderOp::kStroke) 470 _qt_context->setBrush(Qt::NoBrush); 471 else 472 _qt_context->setPen(QPen(Qt::NoPen)); 473 474 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++, angle += 0.01) { 475 BLRect rect(_rnd_coord.next_rect(bounds, wh, wh)); 476 double radius = _rnd_extra.next_double(4.0, 40.0); 477 478 QTransform transform; 479 transform.translate(cx, cy); 480 transform.rotateRadians(angle); 481 transform.translate(-cx, -cy); 482 _qt_context->setTransform(transform, false); 483 484 if (style == StyleKind::kSolid) { 485 QColor color(to_qt_color(_rnd_color.next_rgba32())); 486 if (op == RenderOp::kStroke) 487 _qt_context->setPen(QPen(color, qreal(_params.stroke_width))); 488 else 489 _qt_context->setBrush(QBrush(color)); 490 } 491 else { 492 QBrush brush(create_brush<BLRect>(style, rect)); 493 if (op == RenderOp::kStroke) 494 _qt_context->setPen(QPen(brush, qreal(_params.stroke_width))); 495 else 496 _qt_context->setBrush(brush); 497 } 498 499 _qt_context->drawRoundedRect( 500 QRectF(rect.x, rect.y, rect.w, rect.h), 501 std::min(rect.w * 0.5, radius), 502 std::min(rect.h * 0.5, radius)); 503 504 _qt_context->resetTransform(); 505 } 506 } 507 508 void QtModule::render_polygon(RenderOp op, uint32_t complexity) { 509 BLSizeI bounds(_params.screen_w - _params.shape_size, 510 _params.screen_h - _params.shape_size); 511 StyleKind style = _params.style; 512 double wh = double(_params.shape_size); 513 514 Qt::FillRule fillRule = op == RenderOp::kFillEvenOdd ? Qt::OddEvenFill : Qt::WindingFill; 515 516 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++) { 517 BLPoint base(_rnd_coord.nextPoint(bounds)); 518 519 double x = _rnd_coord.next_double(base.x, base.x + wh); 520 double y = _rnd_coord.next_double(base.y, base.y + wh); 521 522 QPainterPath path; 523 path.setFillRule(fillRule); 524 path.moveTo(x, y); 525 526 for (uint32_t p = 1; p < complexity; p++) { 527 x = _rnd_coord.next_double(base.x, base.x + wh); 528 y = _rnd_coord.next_double(base.y, base.y + wh); 529 path.lineTo(x, y); 530 } 531 532 if (style == StyleKind::kSolid) { 533 QColor color(to_qt_color(_rnd_color.next_rgba32())); 534 535 if (op == RenderOp::kStroke) { 536 QPen pen(color, qreal(_params.stroke_width)); 537 pen.setJoinStyle(Qt::MiterJoin); 538 _qt_context->strokePath(path, pen); 539 } 540 else { 541 _qt_context->fillPath(path, QBrush(color)); 542 } 543 } 544 else { 545 BLRect rect(base.x, base.y, wh, wh); 546 QBrush brush(create_brush<BLRect>(style, rect)); 547 548 if (op == RenderOp::kStroke) { 549 QPen pen(brush, qreal(_params.stroke_width)); 550 pen.setJoinStyle(Qt::MiterJoin); 551 _qt_context->strokePath(path, pen); 552 } 553 else { 554 _qt_context->fillPath(path, brush); 555 } 556 } 557 } 558 } 559 560 void QtModule::render_shape(RenderOp op, ShapeData shape) { 561 BLSizeI bounds(_params.screen_w - _params.shape_size, 562 _params.screen_h - _params.shape_size); 563 StyleKind style = _params.style; 564 double wh = double(_params.shape_size); 565 566 ShapeIterator it(shape); 567 QPainterPath path; 568 while (it.has_command()) { 569 if (it.is_move_to()) { 570 path.moveTo(it.x(0) * wh, it.y(0) * wh); 571 } 572 else if (it.is_line_to()) { 573 path.lineTo(it.x(0) * wh, it.y(0) * wh); 574 } 575 else if (it.is_quad_to()) { 576 path.quadTo( 577 it.x(0) * wh, it.y(0) * wh, 578 it.x(1) * wh, it.y(1) * wh); 579 } 580 else if (it.is_cubic_to()) { 581 path.cubicTo( 582 it.x(0) * wh, it.y(0) * wh, 583 it.x(1) * wh, it.y(1) * wh, 584 it.x(2) * wh, it.y(2) * wh); 585 } 586 else { 587 path.closeSubpath(); 588 } 589 it.next(); 590 } 591 592 Qt::FillRule fillRule = op == RenderOp::kFillEvenOdd ? Qt::OddEvenFill : Qt::WindingFill; 593 594 for (uint32_t i = 0, quantity = _params.quantity; i < quantity; i++) { 595 BLPoint base(_rnd_coord.nextPoint(bounds)); 596 597 _qt_context->save(); 598 _qt_context->translate(qreal(base.x), qreal(base.y)); 599 600 if (style == StyleKind::kSolid) { 601 QColor color(to_qt_color(_rnd_color.next_rgba32())); 602 603 if (op == RenderOp::kStroke) { 604 QPen pen(color, qreal(_params.stroke_width)); 605 pen.setJoinStyle(Qt::MiterJoin); 606 _qt_context->strokePath(path, pen); 607 } 608 else { 609 _qt_context->fillPath(path, QBrush(color)); 610 } 611 } 612 else { 613 BLRect rect(0, 0, wh, wh); 614 QBrush brush(create_brush<BLRect>(style, rect)); 615 616 if (op == RenderOp::kStroke) { 617 QPen pen(brush, qreal(_params.stroke_width)); 618 pen.setJoinStyle(Qt::MiterJoin); 619 _qt_context->strokePath(path, pen); 620 } 621 else { 622 _qt_context->fillPath(path, brush); 623 } 624 } 625 626 _qt_context->restore(); 627 } 628 } 629 630 Backend* create_qt_backend() { 631 return new QtModule(); 632 } 633 634 } // {blbench} 635 636 #endif // BL_BENCH_ENABLE_QT