From c78c0f03a1466f8428510c0e21170a2c7b972de4 Mon Sep 17 00:00:00 2001 From: Uwe Rathmann Date: Wed, 17 Apr 2024 14:46:29 +0200 Subject: [PATCH] QskGraphic::defaultSize replaced by QskGraphic::viewBox. svg2qvg uses the viewBox of the SVG document to initialize the viewBox of the graphic. Avoids scaling problems with the symbols of the skins, that often rely on having a viewBox. --- designsystems/fluent2/icons/icon2qvg.sh | 15 +++ designsystems/fluent2/icons/qvg/checkmark.qvg | Bin 1255 -> 1431 bytes .../icons/qvg/combo-box-arrow-closed.qvg | Bin 515 -> 691 bytes .../icons/qvg/combo-box-arrow-open.qvg | Bin 659 -> 691 bytes .../icons/qvg/segmented-button-check.qvg | Bin 575 -> 751 bytes .../fluent2/icons/qvg/spin-box-arrow-down.qvg | Bin 1135 -> 1311 bytes .../fluent2/icons/qvg/spin-box-arrow-up.qvg | Bin 1135 -> 1311 bytes designsystems/fusion/QskFusionSkin.cpp | 35 +++--- designsystems/fusion/QskFusionSkin.h | 3 +- designsystems/material3/icons/icon2qvg.sh | 15 +++ designsystems/material3/icons/qvg/add.qvg | Bin 1095 -> 1271 bytes .../material3/icons/qvg/arrow_drop_down.qvg | Bin 695 -> 871 bytes .../material3/icons/qvg/arrow_drop_up.qvg | Bin 755 -> 931 bytes designsystems/material3/icons/qvg/check.qvg | Bin 835 -> 1011 bytes .../material3/icons/qvg/check_small.qvg | Bin 575 -> 751 bytes .../icons/qvg/combo-box-arrow-closed.qvg | Bin 515 -> 691 bytes .../icons/qvg/combo-box-arrow-open.qvg | Bin 659 -> 691 bytes designsystems/material3/icons/qvg/remove.qvg | Bin 735 -> 911 bytes .../icons/qvg/segmented-button-check.qvg | Bin 575 -> 751 bytes examples/gallery/icons/icon2qvg.sh | 15 +++ .../gallery/icons/qvg/airport_shuttle.qvg | Bin 3115 -> 3291 bytes examples/gallery/icons/qvg/flight.qvg | Bin 1015 -> 1191 bytes examples/gallery/icons/qvg/local_pizza.qvg | Bin 2035 -> 2211 bytes examples/gallery/icons/qvg/plus.qvg | Bin 695 -> 727 bytes examples/gallery/icons/qvg/sports_soccer.qvg | Bin 2855 -> 3031 bytes examples/iotdashboard/images/icon2qvg.sh | 15 +++ examples/iotdashboard/images/qvg/ac.qvg | Bin 6031 -> 6207 bytes .../iotdashboard/images/qvg/dashboard.qvg | Bin 4171 -> 4347 bytes examples/iotdashboard/images/qvg/devices.qvg | Bin 3855 -> 4031 bytes examples/iotdashboard/images/qvg/down.qvg | Bin 935 -> 1111 bytes examples/iotdashboard/images/qvg/humidity.qvg | Bin 5235 -> 5411 bytes .../images/qvg/indoor-temperature.qvg | Bin 3591 -> 3767 bytes examples/iotdashboard/images/qvg/lamps.qvg | Bin 3603 -> 3779 bytes examples/iotdashboard/images/qvg/logout.qvg | Bin 4547 -> 4723 bytes .../iotdashboard/images/qvg/main-icon.qvg | Bin 7699 -> 7875 bytes examples/iotdashboard/images/qvg/members.qvg | Bin 3895 -> 4071 bytes .../iotdashboard/images/qvg/music-system.qvg | Bin 9055 -> 9231 bytes examples/iotdashboard/images/qvg/rooms.qvg | Bin 1435 -> 1611 bytes examples/iotdashboard/images/qvg/router.qvg | Bin 6919 -> 6951 bytes .../iotdashboard/images/qvg/statistics.qvg | Bin 1635 -> 1811 bytes examples/iotdashboard/images/qvg/storage.qvg | Bin 2095 -> 2271 bytes examples/iotdashboard/images/qvg/up.qvg | Bin 935 -> 1111 bytes examples/qvgviewer/qvg/Tux.qvg | Bin 23699 -> 671 bytes src/graphic/QskGraphic.cpp | 110 ++++++++++-------- src/graphic/QskGraphic.h | 5 +- src/graphic/QskGraphicIO.cpp | 6 + tools/svg2qvg/main.cpp | 15 +++ 47 files changed, 173 insertions(+), 61 deletions(-) create mode 100755 designsystems/fluent2/icons/icon2qvg.sh create mode 100755 designsystems/material3/icons/icon2qvg.sh create mode 100755 examples/gallery/icons/icon2qvg.sh create mode 100755 examples/iotdashboard/images/icon2qvg.sh diff --git a/designsystems/fluent2/icons/icon2qvg.sh b/designsystems/fluent2/icons/icon2qvg.sh new file mode 100755 index 00000000..c562ca17 --- /dev/null +++ b/designsystems/fluent2/icons/icon2qvg.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +if [ $# -eq 0 ]; then + echo "Usage $0 file ..." + exit 1 +fi + +for file in $* +do + base=`basename -s .svg $file` + echo "${base}.svg -> qvg/${base}.qvg" + svg2qvg ${base}.svg qvg/${base}.qvg +done + +exit $status diff --git a/designsystems/fluent2/icons/qvg/checkmark.qvg b/designsystems/fluent2/icons/qvg/checkmark.qvg index dc894a09312fcde0421cb06c1865651524d89b24..07216854692a52ed23d627c3b613a24b6a41ed0e 100644 GIT binary patch delta 116 zcmaFPIh|WOFxcCj0S!2)K?EEW;1bNtOwJRzizkYPa@c>Iu~W3^*XxNBB_!-WxnH}= q&~q22Zhzv8ZHoJ5zSwv;oSE5~A#fsZArk|`#D?IBN**jgMN9xjVjG(P delta 47 zcmbQv{hX6KFxcCjfq{XUnTdI#b}=L4#Q7nctr^{!nVA^^C+Ze5F)~bC5X=Hp!2|#S CGzs7U diff --git a/designsystems/fluent2/icons/qvg/combo-box-arrow-closed.qvg b/designsystems/fluent2/icons/qvg/combo-box-arrow-closed.qvg index 2585b89267974a0533490f71d3b3fdccdca1ce86..72e1f95f4364cc4a922e4ec032d973411e39f871 100644 GIT binary patch delta 114 zcmZo>+03dP80_uNfCd~CAOa2|a0zB+Cg+LVCphds3WCAJi4qF-UqitFrfB~~h}{0C Z5b=qpvzeV40w?koOL>FxcCjfq{XUnaPfHgpWwAFWo?g!E%n&${w`lTn#*oRM8GQh|XCj&a delta 34 pcmaFQx}SwRFxcCjfq{XUnTdI#_KC^XjPn_pC*Ni~!2%Ry0sxvz2sZ!# diff --git a/designsystems/fluent2/icons/qvg/spin-box-arrow-down.qvg b/designsystems/fluent2/icons/qvg/spin-box-arrow-down.qvg index 2825e1fbbd0b7fd4dd919b2c0f377d7e6811a94d..7536d52cdeef9c1b22d922db3f23e9794f03e154 100644 GIT binary patch delta 120 zcmaFQF`r92FxcCj0S!2)Km;5l;1bNtOwJRzizkYPa@c=7E>n11rfA|s2?hJl8?A*m rT8qHc?SBZ7+yA!n#@x;u^ERHo&cy7@5IB*ykcoj|Vngs`WfmU*l~x|u delta 47 zcmbQw^`3(}FxcCjfq{XUnTdI#b}=L4#Q7nctr^cVF*7p+PSh=AVq}=OAeaTHf(ZZ) CM+$WS diff --git a/designsystems/fluent2/icons/qvg/spin-box-arrow-up.qvg b/designsystems/fluent2/icons/qvg/spin-box-arrow-up.qvg index 3ae75f325009d6b145bd2ea1483a625bd41e0a35..08c62e599aff9e2e51094c0fdb428d7ad12babf4 100644 GIT binary patch delta 120 zcmaFQF`r92FxcCj0S!2)Km;5l;1bNtOwJRzizkYPa@c=7E>n11rfA|s2?hJl8?A*m rT8qHc?SBZ7+kdz7#@x;u^ERHo&cy7@5IB*ykcoj|Vngs`WfmU*la?OH delta 47 zcmbQw^`3(}FxcCjfq{XUnTdI#b}=L4#Q7nctr^cVF*7p+PSh=AVq}=OAeaTHf(ZZ) CM+$WS diff --git a/designsystems/fusion/QskFusionSkin.cpp b/designsystems/fusion/QskFusionSkin.cpp index 73ec47f9..d637fdfd 100644 --- a/designsystems/fusion/QskFusionSkin.cpp +++ b/designsystems/fusion/QskFusionSkin.cpp @@ -145,13 +145,21 @@ namespace if ( strcmp( name, "checkMark" ) == 0 ) { + graphic.setViewBox( QRectF( 0.0, 0.0, 14.0, 14.0 ) ); + QPainterPath path; - path.moveTo( 0.11, 0.47 ); - path.lineTo( 0.5, 1.0); - path.lineTo( 1.0, 0.0 ); + path.moveTo( 3.5, 7.0 ); + path.lineTo( 6.5, 14.0 ); + path.lineTo( 11.0, 1.0 ); + + QPen pen( Qt::black, 2.8 ); + pen.setCapStyle( Qt::FlatCap ); + pen.setJoinStyle( Qt::BevelJoin ); QPainter painter( &graphic ); - painter.setPen( QPen( Qt::black, 0.25 ) ); + painter.setRenderHint( QPainter::Antialiasing ); + + painter.setPen( pen ); painter.drawPath( path ); } @@ -209,19 +217,12 @@ void Editor::setupCheckBox() } } - setGraphicRole( Q::Indicator, QskFusionSkin::GraphicNormal ); + setGraphicRole( Q::Indicator, QskFusionSkin::GraphicIndicator ); setGraphicRole( Q::Indicator | Q::Disabled, QskFusionSkin::GraphicDisabled ); setGraphicRole( Q::Indicator | Q::Error, QskFusionSkin::GraphicError ); -#if 0 - // aligning/scaling of the symbols needs to be fixed in the skinlet TODO .. - - setPadding( Q::Box, 4_dp ); + setPadding( Q::Box, 3_dp ); const auto checkMark = symbol( "checkMark" ); -#else - setPadding( Q::Box, 2_dp ); - const auto checkMark = QskStandardSymbol::graphic( QskStandardSymbol::CheckMark ); -#endif for ( auto state : { QskAspect::NoState, Q::Disabled } ) { @@ -277,6 +278,7 @@ void Editor::setupComboBox() setGraphicRole( Q::Icon | Q::Disabled, QskFusionSkin::GraphicDisabled ); setStrutSize( Q::StatusIndicator, 10_dp, 10_dp ); + setGraphicRole( Q::StatusIndicator, QskFusionSkin::GraphicIndicator ); setGraphicRole( Q::StatusIndicator | Q::Disabled, QskFusionSkin::GraphicDisabled ); setAlignment( Q::StatusIndicator, Qt::AlignRight | Qt::AlignVCenter ); @@ -1339,6 +1341,13 @@ void QskFusionSkin::initHints() setGraphicColor( GraphicError, palette.error ); setGraphicColor( GraphicHighlighted, palette.active( P::HighlightedText ) ); + { + auto rgb = palette.darker( P::Active, P::Text, 120 ); + rgb = QskRgb::toTransparent( rgb, 180 ); + + setGraphicColor( GraphicIndicator, rgb ); + } + Editor editor( palette, &hintTable() ); editor.setup(); } diff --git a/designsystems/fusion/QskFusionSkin.h b/designsystems/fusion/QskFusionSkin.h index c3feb9e7..3ec1f178 100644 --- a/designsystems/fusion/QskFusionSkin.h +++ b/designsystems/fusion/QskFusionSkin.h @@ -24,7 +24,8 @@ class QSK_FUSION_EXPORT QskFusionSkin : public QskSkin GraphicNormal, GraphicDisabled, GraphicHighlighted, - GraphicError + GraphicError, + GraphicIndicator }; protected: diff --git a/designsystems/material3/icons/icon2qvg.sh b/designsystems/material3/icons/icon2qvg.sh new file mode 100755 index 00000000..c562ca17 --- /dev/null +++ b/designsystems/material3/icons/icon2qvg.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +if [ $# -eq 0 ]; then + echo "Usage $0 file ..." + exit 1 +fi + +for file in $* +do + base=`basename -s .svg $file` + echo "${base}.svg -> qvg/${base}.qvg" + svg2qvg ${base}.svg qvg/${base}.qvg +done + +exit $status diff --git a/designsystems/material3/icons/qvg/add.qvg b/designsystems/material3/icons/qvg/add.qvg index f347bbd2bb35290f4f6d3ab19d05326ba2ff3243..fbb711f9f088b0bf3d205d25585ee2fa9e842855 100644 GIT binary patch delta 114 zcmX@k@tspUFxcCj0S!1%XJT}oT+Mu9qLK#-P!$sZWg8r) delta 40 vcmey)d7OhgFxcCjfq{XUnTdI#_KD5bjLVsrnHd5n>K087X9-~eN-+Td&%Ox< diff --git a/designsystems/material3/icons/qvg/arrow_drop_down.qvg b/designsystems/material3/icons/qvg/arrow_drop_down.qvg index e8de8a68babf17129ded0e1ace8e9c95854e314a..9ab42f6d1accd196e21d85a11b7244edfcad2137 100644 GIT binary patch delta 114 zcmdna`kYNWFxcCj0S!1Ju9^cO2$p<{9eA?D9FJ|NEXhvpdhQNuuMU!VUg-l+~Q*s^oy$dr>3hzw#STuV!R+W(b_fTQvDKQ^@4+Og;dm>>!2! delta 41 wcmey&ewd9nFxcCjfq{XUnTeSpVDdwzqKWfEHd`|;W@KcZe4ptA3s8;;0O)rLrvLx| diff --git a/designsystems/material3/icons/qvg/check_small.qvg b/designsystems/material3/icons/qvg/check_small.qvg index ea738b8639303983a6c47ec95103ead792067a09..5f84fa5f368616ebcffc59f491962eca25505b13 100644 GIT binary patch delta 84 zcmdnb@}5;YFxcCj0S!24Km;6A;1bNtOwJRzPfY&IsL1}2wJ3?}$&rZ@B_^I;&g{$( PIFYw#@^i)zprj7~Ow1ES delta 34 pcmaFQx}SwRFxcCjfq{XUnTdI#_KC^XjPn_pC*Ni~!2%Ry0sxvz2sZ!# diff --git a/designsystems/material3/icons/qvg/combo-box-arrow-closed.qvg b/designsystems/material3/icons/qvg/combo-box-arrow-closed.qvg index 2585b89267974a0533490f71d3b3fdccdca1ce86..72e1f95f4364cc4a922e4ec032d973411e39f871 100644 GIT binary patch delta 114 zcmZo>+03dP80_uNfCd~CAOa2|a0zB+Cg+LVCphds3WCAJi4qF-UqitFrfB~~h}{0C Z5b=qpvzeV40w?koOL>FxcCjfq{XUnaPDeCs=@@OaPJC2V4LE diff --git a/designsystems/material3/icons/qvg/segmented-button-check.qvg b/designsystems/material3/icons/qvg/segmented-button-check.qvg index fa0e1ce2b2e02e7cf03098703b1b56b2f3e179c4..c3d2df1a8fe1b7b14dbe0f85c9a2c17d7d0d8da0 100644 GIT binary patch delta 114 zcmdnb@}5;YFxcCj0S!3lKm;7r;1bNtOwJRzPjJ|O__cHQXU5`*6D1VvKh|Fj{b2AG qrfC1VWBCUTuP@$z>fHgpWwAFWo?g!E%n&${w`lTn#*oRM8GQh|XCj&a delta 34 pcmaFQx}SwRFxcCjfq{XUnTdI#_KC^XjPn_pC*Ni~!2%Ry0sxvz2sZ!# diff --git a/examples/gallery/icons/icon2qvg.sh b/examples/gallery/icons/icon2qvg.sh new file mode 100755 index 00000000..c562ca17 --- /dev/null +++ b/examples/gallery/icons/icon2qvg.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +if [ $# -eq 0 ]; then + echo "Usage $0 file ..." + exit 1 +fi + +for file in $* +do + base=`basename -s .svg $file` + echo "${base}.svg -> qvg/${base}.qvg" + svg2qvg ${base}.svg qvg/${base}.qvg +done + +exit $status diff --git a/examples/gallery/icons/qvg/airport_shuttle.qvg b/examples/gallery/icons/qvg/airport_shuttle.qvg index fe2cb6603ab1d0be47cd83a5bf39850aa24945d3..a2df7d1ac13cdbc29c678bff56e201455b5d8072 100644 GIT binary patch delta 121 zcmZ22aa&S1FxcCj0S!2qLj)Z3;1bNtOwJ4elM}g%Cf0{=*nili*S+Y)u89*R6zo5$ lO!5RGn9}_ZAaeU3Lc}+op3KGQJUO2G#N;w=4;G*@CII<@A6@_e delta 40 ucmcaDxmtodFxcCjfq{XUnTdI#_KD5bjNM$!%nX4Ob&Doj^MtSfrI-N8-U!D4 diff --git a/examples/gallery/icons/qvg/flight.qvg b/examples/gallery/icons/qvg/flight.qvg index c4d0cd47441dc239b88f2b42b6d59208a89c381d..d776378b0e73de0e5b26b53279ace82fd767e70e 100644 GIT binary patch delta 114 zcmey)zMNA#FxcCj0S!2qLIhwmkjKo-t<8 diff --git a/examples/gallery/icons/qvg/sports_soccer.qvg b/examples/gallery/icons/qvg/sports_soccer.qvg index cbf98807b8bb1e1a8506d5bf87cd1effa6e898ec..f709436063e980ed09e64d1beb9683e64f72aa6f 100644 GIT binary patch delta 114 zcmZ23c3oUMFxcCj0S!2qLIhwmkjKo-; diff --git a/examples/iotdashboard/images/icon2qvg.sh b/examples/iotdashboard/images/icon2qvg.sh new file mode 100755 index 00000000..c562ca17 --- /dev/null +++ b/examples/iotdashboard/images/icon2qvg.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +if [ $# -eq 0 ]; then + echo "Usage $0 file ..." + exit 1 +fi + +for file in $* +do + base=`basename -s .svg $file` + echo "${base}.svg -> qvg/${base}.qvg" + svg2qvg ${base}.svg qvg/${base}.qvg +done + +exit $status diff --git a/examples/iotdashboard/images/qvg/ac.qvg b/examples/iotdashboard/images/qvg/ac.qvg index 56ba511624be271583d723f79e913a237a787b59..1daace163d44f5bf765eb094b76ab42fe44b681a 100644 GIT binary patch delta 92 zcmeCz-*2ED80_uNfCe0#AOa2+a0z~9Cg+LVCnl$JDzWLN<=pYNpEyxs@;?sljo03Y XGCMN_PUJ0`Y%U%GRG>3CUt9qI&ubI{ delta 41 wcmdmQ(67%G80_uNz`(%I%rse#^UP*D#y6tO%nX5(4LOS@&leA20m?A}0N(2f!~g&Q diff --git a/examples/iotdashboard/images/qvg/dashboard.qvg b/examples/iotdashboard/images/qvg/dashboard.qvg index 85ae5e056d43f06005b613187bb23058681fad6d..c1c4e66c86390ae14f2f47011e3a980272210cb2 100644 GIT binary patch delta 90 zcmX@D@LN$kFxcCj0S!3lKm;5#;1aCNOwN<%Go6^cjY*OHBjW;-r!AcmCrV7VXXf5` TZ3Q2r^W=Jdkfa9-Pzw_P-fR=j delta 40 vcmeyZcv^uwFxcCjfq{XQnTdI#_KD5bjH~&WnHd5n>K09o76@ShN-+Td+13eR diff --git a/examples/iotdashboard/images/qvg/devices.qvg b/examples/iotdashboard/images/qvg/devices.qvg index aefe593523f46b64d7a0083e5b9ceacf95cd66a2..211beb98c17543db127cf5244ece844e58700d16 100644 GIT binary patch delta 92 zcmeB|+b^#j80_uNfCe0tAOa3La0y;!Cg;iPIZklce<)=S0HTQ#B_{iGYHz%j!^`Z< X5IA`wN73Z%d?Aysv*}EJ&!+$Yx>*#C delta 41 wcmdll-!I1%80_uNz`(%E%rto(+nLRFj5)l_%nX5(7qS&imgf&)0m?A}0NVlyY5)KL diff --git a/examples/iotdashboard/images/qvg/down.qvg b/examples/iotdashboard/images/qvg/down.qvg index 71e37f4efd771d90236e5b5b9c77bf87f4875376..7a8552c31d82e2fd0ea96e8e3bf4923cc264a193 100644 GIT binary patch delta 114 zcmZ3^ew{-*FxcCj0S!2)Km;5l;1bNtOwJRzPjJ|OU| oMf(N+pXv;CTD>o*A-~$KZ~4a4{7j6_lW#Mfn5g8z0#wBW0B4pNfdBvi delta 40 vcmcc4v7DVdFxcCjfq{XUnTdI#_KD5bjOE;CsyredszAeP;%n&${w`j7oNXTS$5g!1`QW}x~ delta 35 qcmZ3i^;v@}FxcCjfq{XSnQ8Jo_A{I97%vDhGEe3gIl%%HWdZ=OTnL*0 diff --git a/examples/iotdashboard/images/qvg/indoor-temperature.qvg b/examples/iotdashboard/images/qvg/indoor-temperature.qvg index 34d9e6d5ae1ba20be7d26f709904cb9fa853d5b8..6050e4b8e0a9e6aae06a4b0a00060220b2ed3d74 100644 GIT binary patch delta 122 zcmZpd*)FRc80_uNfCe0#AObKN$YW(@a-J;DdV<6LLqftCd9OJWCrT&)*>Q6Ov{_)< t_urOoTlYpMeE)5!T7wx2e{DRS&%^A@5I9+pwP^Bs-jK;=tR5i6OaQ089QObK delta 40 ucmdlk+b+W$80_uNz`(%D%)~rV`^08z#&jNLW`@9txsJ6VP+FxcCjfq_AonQ3wz%bCq~j0HT5%#+vio?rorG64Xhy$DzU diff --git a/examples/iotdashboard/images/qvg/logout.qvg b/examples/iotdashboard/images/qvg/logout.qvg index 9213e3c33b3a907aaa990e45aed25f1a198e09be..b241e980796743c597cd0daa56fa18b628e6f6d3 100644 GIT binary patch delta 100 zcmX@C{8>diFxcCj0S!24Km=ekkSEB@&)UhlhLu5BUTqPLx1qPkztDz44lY V0JAeg;N(E2qRH8UA(P7meE^o07ZU&g delta 35 pcmeyYa#)!wFxcCjfq_AgnQ5{f@0rbZj0ysb%#-5luzaG1vs X$liE*J};y5K09Q=MP~4N-+Td(9Q`7 diff --git a/examples/iotdashboard/images/qvg/music-system.qvg b/examples/iotdashboard/images/qvg/music-system.qvg index 365c609099cbbbf039916f75f45f7739b9ab8874..f1aed287378ee503c70e6ff5b13afabc1c2ad720 100644 GIT binary patch delta 115 zcmccb*6*Pm80_uNfCe0#AObKN$YW+^a-PV2g2Vp9_X`(4Z{9L-qJ)C|$K^W{rK+dF qbnpMK092%^Jc2lwtw^%i0NF diff --git a/examples/iotdashboard/images/qvg/router.qvg b/examples/iotdashboard/images/qvg/router.qvg index 5d41390450e26a26eb33197c721d3d5c07ec400d..58db77631ed5fddad08275c6e15ea3af2b156f82 100644 GIT binary patch delta 55 lcmZoSTW+Qm80_uNfClz|fC#{7AWxK;X|f;FnT^*Br2qh_3G@H} delta 23 ecmZ2()^5fX80_uNz`!8N%rrTV>CDD&hEf1Zt_HRM diff --git a/examples/iotdashboard/images/qvg/statistics.qvg b/examples/iotdashboard/images/qvg/statistics.qvg index c43fb5480f0775c9c6da3537d14a14a3b1af661f..7f8271769d0107a14fd5c485aa9c597962d0dec7 100644 GIT binary patch delta 88 zcmaFNGnr32FxcCj0S!3lKm;6=;1bNtOwJRzPfQkPQ(~+9{r0cTu89*RCZA*F-gxZ* T3$rsr;6&b{$=qxqKm|Skju;ax delta 41 wcmbQt_n3z_FxcCjfq{XUnTeSpU@{|H(Zu;7o2?lSvoJDG{?B@X1t`Y^0MFnF-T(jq diff --git a/examples/iotdashboard/images/qvg/storage.qvg b/examples/iotdashboard/images/qvg/storage.qvg index 1313ee76d39093637086380ce27a45a8df8f39cd..1a043c9757cc1ab38986d3e10295f1981a0ccaf8 100644 GIT binary patch delta 107 zcmZ24a9>b6FxcCj0S!3lKm;7r;1bNtOwJRzPjJ|OU|_TeR(myZqJ)I~2NA_hX3v9Q iiflL7@k*G==50JYpN-j>A#fsZ(d6swA(J1o`v3s4uNImB delta 35 qcmcaFxL$xeFxcCjfq{XUnTdI#_KD5bjQwnk%#%;EpI`xsG64XfI|w@f diff --git a/examples/iotdashboard/images/qvg/up.qvg b/examples/iotdashboard/images/qvg/up.qvg index 58c142f6a01402658f5f43b01fc73276dbf14102..b28fc66e21b46dac80553086a86131d6b83df0eb 100644 GIT binary patch delta 114 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 diff --git a/src/graphic/QskGraphic.cpp b/src/graphic/QskGraphic.cpp index 791e79ae..29127cf7 100644 --- a/src/graphic/QskGraphic.cpp +++ b/src/graphic/QskGraphic.cpp @@ -339,7 +339,7 @@ class QskGraphic::PrivateData : public QSharedData PrivateData( const PrivateData& other ) : QSharedData( other ) - , defaultSize( other.defaultSize ) + , viewBox( other.viewBox ) , commands( other.commands ) , pathInfos( other.pathInfos ) , boundingRect( other.boundingRect ) @@ -354,7 +354,18 @@ class QskGraphic::PrivateData : public QSharedData { return ( modificationId == other.modificationId ) && ( renderHints == other.renderHints ) && - ( defaultSize == other.defaultSize ); + ( viewBox == other.viewBox ); + } + + void resetCommands() + { + commands.clear(); + pathInfos.clear(); + + commandTypes = 0; + boundingRect = pointRect = { 0.0, 0.0, -1.0, -1.0 }; + + modificationId = 0; } inline void addCommand( const QskPainterCommand& command ) @@ -365,7 +376,7 @@ class QskGraphic::PrivateData : public QSharedData modificationId = nextId.fetchAndAddRelaxed( 1 ); } - QSizeF defaultSize; + QRectF viewBox = { 0.0, 0.0, -1.0, -1.0 }; QVector< QskPainterCommand > commands; QVector< QskGraphicPrivate::PathInfo > pathInfos; @@ -492,16 +503,9 @@ int QskGraphic::metric( PaintDeviceMetric deviceMetric ) const void QskGraphic::reset() { - m_data->commands.clear(); - m_data->pathInfos.clear(); + m_data->resetCommands(); - m_data->commandTypes = 0; - - m_data->boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); - m_data->pointRect = QRectF( 0.0, 0.0, -1.0, -1.0 ); - m_data->defaultSize = QSizeF(); - - m_data->modificationId = 0; + m_data->viewBox = { 0.0, 0.0, -1.0, -1.0 }; delete m_paintEngine; m_paintEngine = nullptr; @@ -580,18 +584,20 @@ QSize QskGraphic::sizeMetrics() const return QSize( qCeil( sz.width() ), qCeil( sz.height() ) ); } -void QskGraphic::setDefaultSize( const QSizeF& size ) +void QskGraphic::setViewBox( const QRectF& rect ) { - const double w = qMax( qreal( 0.0 ), size.width() ); - const double h = qMax( qreal( 0.0 ), size.height() ); + m_data->viewBox = rect; +} - m_data->defaultSize = QSizeF( w, h ); +QRectF QskGraphic::viewBox() const +{ + return m_data->viewBox; } QSizeF QskGraphic::defaultSize() const { - if ( !m_data->defaultSize.isEmpty() ) - return m_data->defaultSize; + if ( !m_data->viewBox.isEmpty() ) + return m_data->viewBox.size(); return boundingRect().size(); } @@ -670,30 +676,42 @@ void QskGraphic::render( QPainter* painter, const QRectF& rect, if ( isEmpty() || rect.isEmpty() ) return; + const bool scalePens = !( m_data->renderHints & RenderPensUnscaled ); + qreal sx = 1.0; qreal sy = 1.0; - if ( m_data->pointRect.width() > 0.0 ) - sx = rect.width() / m_data->pointRect.width(); + QRectF boundingBox = m_data->viewBox; - if ( m_data->pointRect.height() > 0.0 ) - sy = rect.height() / m_data->pointRect.height(); - - const bool scalePens = !( m_data->renderHints & RenderPensUnscaled ); - - for ( const auto& info : std::as_const( m_data->pathInfos ) ) + if ( !boundingBox.isEmpty() ) { - const qreal ssx = info.scaleFactorX( m_data->pointRect, - rect, m_data->boundingRect, scalePens ); + sx = rect.width() / boundingBox.width(); + sy = rect.height() / boundingBox.height(); + } + else + { + boundingBox = m_data->boundingRect; - if ( ssx > 0.0 ) - sx = qMin( sx, ssx ); + if ( m_data->pointRect.width() > 0.0 ) + sx = rect.width() / m_data->pointRect.width(); - const qreal ssy = info.scaleFactorY( m_data->pointRect, - rect, m_data->boundingRect, scalePens ); + if ( m_data->pointRect.height() > 0.0 ) + sy = rect.height() / m_data->pointRect.height(); - if ( ssy > 0.0 ) - sy = qMin( sy, ssy ); + for ( const auto& info : std::as_const( m_data->pathInfos ) ) + { + const qreal ssx = info.scaleFactorX( m_data->pointRect, + rect, m_data->boundingRect, scalePens ); + + if ( ssx > 0.0 ) + sx = qMin( sx, ssx ); + + const qreal ssy = info.scaleFactorY( m_data->pointRect, + rect, m_data->boundingRect, scalePens ); + + if ( ssy > 0.0 ) + sy = qMin( sy, ssy ); + } } if ( aspectRatioMode == Qt::KeepAspectRatio ) @@ -705,15 +723,17 @@ void QskGraphic::render( QPainter* painter, const QRectF& rect, sx = sy = qMax( sx, sy ); } - const auto& br = m_data->boundingRect; - const auto rc = rect.center(); - QTransform tr; - tr.translate( - rc.x() - 0.5 * sx * br.width(), - rc.y() - 0.5 * sy * br.height() ); - tr.scale( sx, sy ); - tr.translate( -br.x(), -br.y() ); + + { + const auto rc = rect.center(); + + tr.translate( + rc.x() - 0.5 * sx * boundingBox.width(), + rc.y() - 0.5 * sy * boundingBox.height() ); + tr.scale( sx, sy ); + tr.translate( -boundingBox.x(), -boundingBox.y() ); + } const auto transform = painter->transform(); @@ -986,7 +1006,7 @@ const QVector< QskPainterCommand >& QskGraphic::commands() const void QskGraphic::setCommands( const QVector< QskPainterCommand >& commands ) { - reset(); + m_data->resetCommands(); const int numCommands = commands.size(); if ( numCommands <= 0 ) @@ -1019,9 +1039,7 @@ quint64 QskGraphic::modificationId() const QskHashValue QskGraphic::hash( QskHashValue seed ) const { auto hash = qHash( m_data->renderHints, seed ); - - hash = qHash( m_data->defaultSize.width(), hash ); - hash = qHash( m_data->defaultSize.height(), hash ); + hash = qHashBits( &m_data->viewBox, sizeof( QRectF ), hash ); return qHash( m_data->modificationId, hash ); } diff --git a/src/graphic/QskGraphic.h b/src/graphic/QskGraphic.h index bd678397..d9e8c5a0 100644 --- a/src/graphic/QskGraphic.h +++ b/src/graphic/QskGraphic.h @@ -29,6 +29,7 @@ class QSK_EXPORT QskGraphic : public QPaintDevice Q_GADGET Q_PROPERTY( qreal aspectRatio READ aspectRatio ) + Q_PROPERTY( QRectF viewBox READ viewBox WRITE setViewBox ) Q_PROPERTY( QRectF boundingRect READ boundingRect ) Q_PROPERTY( QRectF controlPointRect READ controlPointRect ) Q_PROPERTY( QSizeF defaultSize READ defaultSize ) @@ -106,9 +107,11 @@ class QSK_EXPORT QskGraphic : public QPaintDevice const QVector< QskPainterCommand >& commands() const; void setCommands( const QVector< QskPainterCommand >& ); - void setDefaultSize( const QSizeF& ); QSizeF defaultSize() const; + void setViewBox( const QRectF& ); + QRectF viewBox() const; + qreal aspectRatio() const; qreal heightForWidth( qreal width ) const; diff --git a/src/graphic/QskGraphicIO.cpp b/src/graphic/QskGraphicIO.cpp index b7bf699f..b654d6f9 100644 --- a/src/graphic/QskGraphicIO.cpp +++ b/src/graphic/QskGraphicIO.cpp @@ -241,6 +241,9 @@ QskGraphic QskGraphicIO::read( QIODevice* dev ) return QskGraphic(); } + QRectF viewBox; + stream >> viewBox; + quint32 numCommands; stream >> numCommands; @@ -280,6 +283,7 @@ QskGraphic QskGraphicIO::read( QIODevice* dev ) } QskGraphic graphic; + graphic.setViewBox( viewBox ); graphic.setCommands( commands ); return graphic; @@ -315,6 +319,8 @@ bool QskGraphicIO::write( const QskGraphic& graphic, QIODevice* dev ) stream.setByteOrder( QDataStream::BigEndian ); stream.writeRawData( qskMagicNumber, 4 ); + stream << graphic.viewBox(); + const auto numCommands = graphic.commands().size(); const QskPainterCommand* cmds = graphic.commands().constData(); diff --git a/tools/svg2qvg/main.cpp b/tools/svg2qvg/main.cpp index d5ffcf82..e4afa0dc 100644 --- a/tools/svg2qvg/main.cpp +++ b/tools/svg2qvg/main.cpp @@ -57,6 +57,21 @@ int main( int argc, char* argv[] ) QskGraphic graphic; + { + /* + QSvgRenderer::viewBoxF() returns a bounding box when no viewBox + has been defined. So we clear the viewBox and compare the result with + the initial value - assuming, that there was a viewBox when they differ. + + */ + const auto viewBox = renderer.viewBoxF(); + renderer.setViewBox( QRectF() ); + + if ( viewBox != renderer.viewBoxF() ) + graphic.setViewBox( viewBox ); + } + + QPainter painter( &graphic ); renderer.render( &painter ); painter.end();