Merge lp:~loic.molinari/ubuntu-ui-toolkit/ubuntu-ui-toolkit-shape-rewrite into lp:ubuntu-ui-toolkit/staging
- ubuntu-ui-toolkit-shape-rewrite
- Merge into staging
Status: | Merged | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Zsombor Egri | ||||||||||||||||||||||||||||||||||||||||||||
Approved revision: | 1340 | ||||||||||||||||||||||||||||||||||||||||||||
Merged at revision: | 1427 | ||||||||||||||||||||||||||||||||||||||||||||
Proposed branch: | lp:~loic.molinari/ubuntu-ui-toolkit/ubuntu-ui-toolkit-shape-rewrite | ||||||||||||||||||||||||||||||||||||||||||||
Merge into: | lp:ubuntu-ui-toolkit/staging | ||||||||||||||||||||||||||||||||||||||||||||
Diff against target: |
3415 lines (+1965/-1054) 13 files modified
.bzrignore (+1/-0) components.api (+40/-15) examples/ubuntu-ui-toolkit-gallery/UbuntuShape.qml (+26/-23) modules/Ubuntu/Components/Themes/Ambiance/ProgressBarStyle.qml (+1/-1) modules/Ubuntu/Components/plugin/plugin.cpp (+6/-5) modules/Ubuntu/Components/plugin/plugin.pro (+10/-3) modules/Ubuntu/Components/plugin/plugin.qrc (+6/-0) modules/Ubuntu/Components/plugin/shaders/shape.frag (+57/-0) modules/Ubuntu/Components/plugin/shaders/shape.vert (+43/-0) modules/Ubuntu/Components/plugin/ucubuntushape.cpp (+1202/-820) modules/Ubuntu/Components/plugin/ucubuntushape.h (+270/-183) modules/Ubuntu/Components/plugin/ucubuntushapetexture.h (+4/-4) tests/resources/ubuntushape/UbuntuShapeTest.qml (+299/-0) |
||||||||||||||||||||||||||||||||||||||||||||
To merge this branch: | bzr merge lp:~loic.molinari/ubuntu-ui-toolkit/ubuntu-ui-toolkit-shape-rewrite | ||||||||||||||||||||||||||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Zsombor Egri | Approve | ||
Review via email:
|
Commit message
[UbuntuShape] Refactored the base component.
The UbuntuShape needed a rework in order to propose more features while keeping efficiency high and maintenance easy.
Description of the change
[UbuntuShape] Refactored the base component.
The UbuntuShape needed a rework in order to propose more features while keeping efficiency high and maintenance easy.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Zsombor Egri (zsombi) wrote : | # |
I went through your MR, and I'd suggest to turn it on Needs Review unless you have anything to add.
Nice work!!! Will give a shot to see whether I can see any visual glitches. I was thinking whether we could add some unit tests or something to guard the current functionality, it is hard, as it mostly has visual feedback, no API driven ones...
Some of the comments below needs fixing, some not.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Loïc Molinari (loic.molinari) wrote : | # |
Thanks for the review Zsombor. See my replies in the diff.
Marking as NeedReview but I still have to instrument the OpenGL ES path on the device, so please don't approve for now.
Cheers ;)
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1333
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Zsombor Egri (zsombi) wrote : | # |
Problems with the revision. Please check them.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Zsombor Egri (zsombi) wrote : | # |
> Problems with the revision. Please check them.
Ok, seems the revision number doesn't need to be in sync with the minor version, I understood it wrongly. And thinking of it, it shouldn't even be, as if the major changes, the revisions cannot be reset to 0, unless a new library is made resetting all revision API to 0. Which can be insane.
So then the only thing remaining to see why the components.api diff?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Loïc Molinari (loic.molinari) wrote : | # |
> > Problems with the revision. Please check them.
>
> Ok, seems the revision number doesn't need to be in sync with the minor
> version, I understood it wrongly. And thinking of it, it shouldn't even be, as
> if the major changes, the revisions cannot be reset to 0, unless a new library
> is made resetting all revision API to 0. Which can be insane.
>
> So then the only thing remaining to see why the components.api diff?
Because I thought you requested it from a previous comment. removing it anyway.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1335
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1337
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1338
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Loïc Molinari (loic.molinari) wrote : | # |
Tested successfully on Qt 5.4.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1339
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1340
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
Unapproved changes made after approval.
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2015-02-02 14:40:18 +0000 | |||
3 | +++ .bzrignore 2015-03-02 15:41:23 +0000 | |||
4 | @@ -2,6 +2,7 @@ | |||
5 | 2 | modules/Makefile.ubuntu-ui-toolkit | 2 | modules/Makefile.ubuntu-ui-toolkit |
6 | 3 | modules/Ubuntu/Components/Makefile.ubuntu-ui-toolkit | 3 | modules/Ubuntu/Components/Makefile.ubuntu-ui-toolkit |
7 | 4 | modules/Ubuntu/Components/plugin/Makefile.ubuntu-ui-toolkit | 4 | modules/Ubuntu/Components/plugin/Makefile.ubuntu-ui-toolkit |
8 | 5 | modules/Ubuntu/Components/plugin/qrc_plugin.cpp | ||
9 | 5 | documentation/html/* | 6 | documentation/html/* |
10 | 6 | *.moc | 7 | *.moc |
11 | 7 | moc_*.cpp | 8 | moc_*.cpp |
12 | 8 | 9 | ||
13 | === modified file 'components.api' | |||
14 | --- components.api 2015-02-24 14:54:58 +0000 | |||
15 | +++ components.api 2015-03-02 15:41:23 +0000 | |||
16 | @@ -794,21 +794,6 @@ | |||
17 | 794 | name: "get" | 794 | name: "get" |
18 | 795 | Parameter { name: "row"; type: "int" } | 795 | Parameter { name: "row"; type: "int" } |
19 | 796 | Method { name: "count"; type: "int" } | 796 | Method { name: "count"; type: "int" } |
20 | 797 | name: "ShapeItem" | ||
21 | 798 | prototype: "QQuickItem" | ||
22 | 799 | exports: [ | ||
23 | 800 | name: "HAlignment" | ||
24 | 801 | name: "VAlignment" | ||
25 | 802 | Property { name: "color"; type: "QColor" } | ||
26 | 803 | Property { name: "gradientColor"; type: "QColor" } | ||
27 | 804 | Property { name: "radius"; type: "string" } | ||
28 | 805 | Property { name: "image"; type: "QVariant" } | ||
29 | 806 | Property { name: "stretched"; type: "bool" } | ||
30 | 807 | Property { name: "horizontalAlignment"; type: "HAlignment" } | ||
31 | 808 | Property { name: "verticalAlignment"; type: "VAlignment" } | ||
32 | 809 | Property { name: "borderSource"; type: "string" } | ||
33 | 810 | Signal { name: "borderChanged" } | ||
34 | 811 | Method { name: "gridUnitChanged" } | ||
35 | 812 | name: "SortBehavior" | 797 | name: "SortBehavior" |
36 | 813 | prototype: "QObject" | 798 | prototype: "QObject" |
37 | 814 | exports: ["SortBehavior 1.1"] | 799 | exports: ["SortBehavior 1.1"] |
38 | @@ -1073,6 +1058,46 @@ | |||
39 | 1073 | Property { name: "SleepyDuration"; type: "int"; isReadonly: true } | 1058 | Property { name: "SleepyDuration"; type: "int"; isReadonly: true } |
40 | 1074 | Property { name: "StandardEasing"; type: "QEasingCurve"; isReadonly: true } | 1059 | Property { name: "StandardEasing"; type: "QEasingCurve"; isReadonly: true } |
41 | 1075 | Property { name: "StandardEasingReverse"; type: "QEasingCurve"; isReadonly: true } | 1060 | Property { name: "StandardEasingReverse"; type: "QEasingCurve"; isReadonly: true } |
42 | 1061 | name: "UCUbuntuShape" | ||
43 | 1062 | prototype: "QQuickItem" | ||
44 | 1063 | exports: [ | ||
45 | 1064 | name: "BackgroundMode" | ||
46 | 1065 | name: "HAlignment" | ||
47 | 1066 | name: "VAlignment" | ||
48 | 1067 | name: "FillMode" | ||
49 | 1068 | name: "WrapMode" | ||
50 | 1069 | Property { name: "radius"; type: "string" } | ||
51 | 1070 | Property { name: "borderSource"; type: "string" } | ||
52 | 1071 | Property { name: "source"; revision: 1; type: "QVariant" } | ||
53 | 1072 | Property { name: "sourceOpacity"; revision: 1; type: "float" } | ||
54 | 1073 | Property { name: "sourceFillMode"; revision: 1; type: "FillMode" } | ||
55 | 1074 | Property { name: "sourceHorizontalWrapMode"; revision: 1; type: "WrapMode" } | ||
56 | 1075 | Property { name: "sourceVerticalWrapMode"; revision: 1; type: "WrapMode" } | ||
57 | 1076 | Property { name: "sourceHorizontalAlignment"; revision: 1; type: "HAlignment" } | ||
58 | 1077 | Property { name: "sourceVerticalAlignment"; revision: 1; type: "VAlignment" } | ||
59 | 1078 | Property { name: "sourceTranslation"; revision: 1; type: "QVector2D" } | ||
60 | 1079 | Property { name: "sourceScale"; revision: 1; type: "QVector2D" } | ||
61 | 1080 | Property { name: "backgroundColor"; revision: 1; type: "QColor" } | ||
62 | 1081 | Property { name: "secondaryBackgroundColor"; revision: 1; type: "QColor" } | ||
63 | 1082 | Property { name: "backgroundMode"; revision: 1; type: "BackgroundMode" } | ||
64 | 1083 | Property { name: "color"; type: "QColor" } | ||
65 | 1084 | Property { name: "gradientColor"; type: "QColor" } | ||
66 | 1085 | Property { name: "image"; type: "QVariant" } | ||
67 | 1086 | Property { name: "stretched"; type: "bool" } | ||
68 | 1087 | Property { name: "horizontalAlignment"; type: "HAlignment" } | ||
69 | 1088 | Property { name: "verticalAlignment"; type: "VAlignment" } | ||
70 | 1089 | Signal { name: "sourceChanged"; revision: 1 } | ||
71 | 1090 | Signal { name: "sourceOpacityChanged"; revision: 1 } | ||
72 | 1091 | Signal { name: "sourceFillModeChanged"; revision: 1 } | ||
73 | 1092 | Signal { name: "sourceHorizontalWrapModeChanged"; revision: 1 } | ||
74 | 1093 | Signal { name: "sourceVerticalWrapModeChanged"; revision: 1 } | ||
75 | 1094 | Signal { name: "sourceHorizontalAlignmentChanged"; revision: 1 } | ||
76 | 1095 | Signal { name: "sourceVerticalAlignmentChanged"; revision: 1 } | ||
77 | 1096 | Signal { name: "sourceTranslationChanged"; revision: 1 } | ||
78 | 1097 | Signal { name: "sourceScaleChanged"; revision: 1 } | ||
79 | 1098 | Signal { name: "backgroundColorChanged"; revision: 1 } | ||
80 | 1099 | Signal { name: "secondaryBackgroundColorChanged"; revision: 1 } | ||
81 | 1100 | Signal { name: "backgroundModeChanged"; revision: 1 } | ||
82 | 1076 | name: "UCUnits" | 1101 | name: "UCUnits" |
83 | 1077 | prototype: "QObject" | 1102 | prototype: "QObject" |
84 | 1078 | exports: ["UCUnits 0.1", "UCUnits 1.0"] | 1103 | exports: ["UCUnits 0.1", "UCUnits 1.0"] |
85 | 1079 | 1104 | ||
86 | === modified file 'examples/ubuntu-ui-toolkit-gallery/UbuntuShape.qml' | |||
87 | --- examples/ubuntu-ui-toolkit-gallery/UbuntuShape.qml 2014-11-19 11:10:00 +0000 | |||
88 | +++ examples/ubuntu-ui-toolkit-gallery/UbuntuShape.qml 2015-03-02 15:41:23 +0000 | |||
89 | @@ -14,8 +14,8 @@ | |||
90 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
91 | 15 | */ | 15 | */ |
92 | 16 | 16 | ||
95 | 17 | import QtQuick 2.0 | 17 | import QtQuick 2.2 |
96 | 18 | import Ubuntu.Components 0.1 | 18 | import Ubuntu.Components 1.2 |
97 | 19 | 19 | ||
98 | 20 | Template { | 20 | Template { |
99 | 21 | objectName: "ubuntuShapesTemplate" | 21 | objectName: "ubuntuShapesTemplate" |
100 | @@ -30,18 +30,17 @@ | |||
101 | 30 | height: units.gu(8) | 30 | height: units.gu(8) |
102 | 31 | 31 | ||
103 | 32 | UbuntuShape { | 32 | UbuntuShape { |
116 | 33 | objectName: "ubuntushape_color_hex" | 33 | objectName: "ubuntushape_backgroundcolor_orange" |
117 | 34 | color: UbuntuColors.orange | 34 | backgroundColor: UbuntuColors.orange |
118 | 35 | } | 35 | } |
119 | 36 | 36 | ||
120 | 37 | UbuntuShape { | 37 | UbuntuShape { |
121 | 38 | objectName: "ubuntushape_color_lightaubergine" | 38 | objectName: "ubuntushape_verticalgradient" |
122 | 39 | color: UbuntuColors.lightAubergine | 39 | backgroundColor: UbuntuColors.lightAubergine |
123 | 40 | } | 40 | secondaryBackgroundColor: Qt.rgba( |
124 | 41 | 41 | UbuntuColors.lightAubergine.r, UbuntuColors.lightAubergine.g, | |
125 | 42 | UbuntuShape { | 42 | UbuntuColors.lightAubergine.b, 0.25) |
126 | 43 | objectName: "ubuntushape_color_darkgray" | 43 | backgroundMode: UbuntuShape.VerticalGradient |
115 | 44 | color: UbuntuColors.warmGrey | ||
127 | 45 | } | 44 | } |
128 | 46 | } | 45 | } |
129 | 47 | 46 | ||
130 | @@ -51,12 +50,16 @@ | |||
131 | 51 | height: units.gu(8) | 50 | height: units.gu(8) |
132 | 52 | 51 | ||
133 | 53 | UbuntuShape { | 52 | UbuntuShape { |
135 | 54 | objectName: "ubuntushape_image" | 53 | objectName: "ubuntushape_preserveaspectcrop" |
136 | 54 | source: Image { source: "map_icon.png" } | ||
137 | 55 | sourceFillMode: UbuntuShape.PreserveAspectCrop | ||
138 | 56 | } | ||
139 | 55 | 57 | ||
144 | 56 | image: Image { | 58 | UbuntuShape { |
145 | 57 | source: "map_icon.png" | 59 | objectName: "ubuntushape_pad" |
146 | 58 | fillMode: Image.PreserveAspectCrop | 60 | backgroundColor: UbuntuColors.warmGrey |
147 | 59 | } | 61 | source: Image { source: "images.png" } |
148 | 62 | sourceFillMode: UbuntuShape.Pad | ||
149 | 60 | } | 63 | } |
150 | 61 | } | 64 | } |
151 | 62 | 65 | ||
152 | @@ -68,7 +71,7 @@ | |||
153 | 68 | UbuntuShape { | 71 | UbuntuShape { |
154 | 69 | objectName: "ubuntushape_radius_small" | 72 | objectName: "ubuntushape_radius_small" |
155 | 70 | 73 | ||
157 | 71 | color: Theme.palette.normal.foreground | 74 | backgroundColor: Theme.palette.normal.foreground |
158 | 72 | radius: "small" | 75 | radius: "small" |
159 | 73 | 76 | ||
160 | 74 | Label { | 77 | Label { |
161 | @@ -81,7 +84,7 @@ | |||
162 | 81 | 84 | ||
163 | 82 | UbuntuShape { | 85 | UbuntuShape { |
164 | 83 | objectName: "ubuntushape_radius_medium" | 86 | objectName: "ubuntushape_radius_medium" |
166 | 84 | color: Theme.palette.normal.foreground | 87 | backgroundColor: Theme.palette.normal.foreground |
167 | 85 | radius: "medium" | 88 | radius: "medium" |
168 | 86 | 89 | ||
169 | 87 | Label { | 90 | Label { |
170 | @@ -100,7 +103,7 @@ | |||
171 | 100 | 103 | ||
172 | 101 | UbuntuShape { | 104 | UbuntuShape { |
173 | 102 | objectName: "ubuntushape_sizes_15_6" | 105 | objectName: "ubuntushape_sizes_15_6" |
175 | 103 | color: Theme.palette.normal.foreground | 106 | backgroundColor: Theme.palette.normal.foreground |
176 | 104 | width: units.gu(15) | 107 | width: units.gu(15) |
177 | 105 | height: units.gu(6) | 108 | height: units.gu(6) |
178 | 106 | anchors.verticalCenter: parent.verticalCenter | 109 | anchors.verticalCenter: parent.verticalCenter |
179 | @@ -108,7 +111,7 @@ | |||
180 | 108 | 111 | ||
181 | 109 | UbuntuShape { | 112 | UbuntuShape { |
182 | 110 | objectName: "ubuntushape_sizes_10_14" | 113 | objectName: "ubuntushape_sizes_10_14" |
184 | 111 | color: Theme.palette.normal.foreground | 114 | backgroundColor: Theme.palette.normal.foreground |
185 | 112 | width: units.gu(10) | 115 | width: units.gu(10) |
186 | 113 | height: units.gu(14) | 116 | height: units.gu(14) |
187 | 114 | } | 117 | } |
188 | 115 | 118 | ||
189 | === modified file 'modules/Ubuntu/Components/Themes/Ambiance/ProgressBarStyle.qml' | |||
190 | --- modules/Ubuntu/Components/Themes/Ambiance/ProgressBarStyle.qml 2015-02-10 16:47:59 +0000 | |||
191 | +++ modules/Ubuntu/Components/Themes/Ambiance/ProgressBarStyle.qml 2015-03-02 15:41:23 +0000 | |||
192 | @@ -36,7 +36,7 @@ | |||
193 | 36 | /* The color must be white for PartialColorizeUbuntuShape to accurately | 36 | /* The color must be white for PartialColorizeUbuntuShape to accurately |
194 | 37 | replace the white with leftColor and rightColor | 37 | replace the white with leftColor and rightColor |
195 | 38 | */ | 38 | */ |
197 | 39 | color: progressBar.indeterminate ? backgroundColor : "#FFFFFF" | 39 | color: progressBar.indeterminate ? progressBarStyle.backgroundColor : "#FFFFFF" |
198 | 40 | } | 40 | } |
199 | 41 | 41 | ||
200 | 42 | property real progress: progressBar.indeterminate ? 0.0 | 42 | property real progress: progressBar.indeterminate ? 0.0 |
201 | 43 | 43 | ||
202 | === modified file 'modules/Ubuntu/Components/plugin/plugin.cpp' | |||
203 | --- modules/Ubuntu/Components/plugin/plugin.cpp 2015-02-13 13:27:51 +0000 | |||
204 | +++ modules/Ubuntu/Components/plugin/plugin.cpp 2015-03-02 15:41:23 +0000 | |||
205 | @@ -31,7 +31,7 @@ | |||
206 | 31 | #include "ucscalingimageprovider.h" | 31 | #include "ucscalingimageprovider.h" |
207 | 32 | #include "ucqquickimageextension.h" | 32 | #include "ucqquickimageextension.h" |
208 | 33 | #include "quickutils.h" | 33 | #include "quickutils.h" |
210 | 34 | #include "shapeitem.h" | 34 | #include "ucubuntushape.h" |
211 | 35 | #include "inversemouseareatype.h" | 35 | #include "inversemouseareatype.h" |
212 | 36 | #include "qquickclipboard.h" | 36 | #include "qquickclipboard.h" |
213 | 37 | #include "qquickmimedata.h" | 37 | #include "qquickmimedata.h" |
214 | @@ -129,9 +129,9 @@ | |||
215 | 129 | qmlRegisterUncreatableType<UbuntuI18n>(uri, major, minor, "i18n", "Singleton object"); | 129 | qmlRegisterUncreatableType<UbuntuI18n>(uri, major, minor, "i18n", "Singleton object"); |
216 | 130 | qmlRegisterExtendedType<QQuickImageBase, UCQQuickImageExtension>(uri, major, minor, "QQuickImageBase"); | 130 | qmlRegisterExtendedType<QQuickImageBase, UCQQuickImageExtension>(uri, major, minor, "QQuickImageBase"); |
217 | 131 | qmlRegisterUncreatableType<UCUnits>(uri, major, minor, "UCUnits", "Not instantiable"); | 131 | qmlRegisterUncreatableType<UCUnits>(uri, major, minor, "UCUnits", "Not instantiable"); |
221 | 132 | qmlRegisterType<ShapeItem>(uri, major, minor, "UbuntuShape"); | 132 | qmlRegisterType<UCUbuntuShape>(uri, major, minor, "UbuntuShape"); |
222 | 133 | // FIXME/DEPRECATED: Shape is exported for backwards compatibity only | 133 | // FIXME/DEPRECATED: Shape is exported for backwards compatibility only |
223 | 134 | qmlRegisterType<ShapeItem>(uri, major, minor, "Shape"); | 134 | qmlRegisterType<UCUbuntuShape>(uri, major, minor, "Shape"); |
224 | 135 | qmlRegisterType<InverseMouseAreaType>(uri, major, minor, "InverseMouseArea"); | 135 | qmlRegisterType<InverseMouseAreaType>(uri, major, minor, "InverseMouseArea"); |
225 | 136 | qmlRegisterType<QQuickMimeData>(uri, major, minor, "MimeData"); | 136 | qmlRegisterType<QQuickMimeData>(uri, major, minor, "MimeData"); |
226 | 137 | qmlRegisterSingletonType<QQuickClipboard>(uri, major, minor, "Clipboard", registerClipboard); | 137 | qmlRegisterSingletonType<QQuickClipboard>(uri, major, minor, "Clipboard", registerClipboard); |
227 | @@ -169,13 +169,14 @@ | |||
228 | 169 | qmlRegisterUncreatableType<SortBehavior>(uri, 1, 1, "SortBehavior", "Not instantiable"); | 169 | qmlRegisterUncreatableType<SortBehavior>(uri, 1, 1, "SortBehavior", "Not instantiable"); |
229 | 170 | qmlRegisterType<UCServiceProperties, 1>(uri, 1, 1, "ServiceProperties"); | 170 | qmlRegisterType<UCServiceProperties, 1>(uri, 1, 1, "ServiceProperties"); |
230 | 171 | 171 | ||
232 | 172 | // ListItem and related types, released to 1.2 | 172 | // register 1.2 only API |
233 | 173 | qmlRegisterType<UCListItem>(uri, 1, 2, "ListItem"); | 173 | qmlRegisterType<UCListItem>(uri, 1, 2, "ListItem"); |
234 | 174 | qmlRegisterType<UCListItemDivider>(); | 174 | qmlRegisterType<UCListItemDivider>(); |
235 | 175 | qmlRegisterUncreatableType<UCSwipeEvent>(uri, 1, 2, "SwipeEvent", "This is an event object."); | 175 | qmlRegisterUncreatableType<UCSwipeEvent>(uri, 1, 2, "SwipeEvent", "This is an event object."); |
236 | 176 | qmlRegisterUncreatableType<UCDragEvent>(uri, 1, 2, "ListItemDrag", "This is an event object"); | 176 | qmlRegisterUncreatableType<UCDragEvent>(uri, 1, 2, "ListItemDrag", "This is an event object"); |
237 | 177 | qmlRegisterType<UCListItemActions>(uri, 1, 2, "ListItemActions"); | 177 | qmlRegisterType<UCListItemActions>(uri, 1, 2, "ListItemActions"); |
238 | 178 | qmlRegisterUncreatableType<UCViewItemsAttached>(uri, 1, 2, "ViewItems", "Not instantiable"); | 178 | qmlRegisterUncreatableType<UCViewItemsAttached>(uri, 1, 2, "ViewItems", "Not instantiable"); |
239 | 179 | qmlRegisterType<UCUbuntuShape, 1>(uri, 1, 2, "UbuntuShape"); | ||
240 | 179 | } | 180 | } |
241 | 180 | 181 | ||
242 | 181 | void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri) | 182 | void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
243 | 182 | 183 | ||
244 | === modified file 'modules/Ubuntu/Components/plugin/plugin.pro' | |||
245 | --- modules/Ubuntu/Components/plugin/plugin.pro 2015-02-17 12:21:52 +0000 | |||
246 | +++ modules/Ubuntu/Components/plugin/plugin.pro 2015-03-02 15:41:23 +0000 | |||
247 | @@ -33,8 +33,8 @@ | |||
248 | 33 | ucunits.h \ | 33 | ucunits.h \ |
249 | 34 | ucqquickimageextension.h \ | 34 | ucqquickimageextension.h \ |
250 | 35 | quickutils.h \ | 35 | quickutils.h \ |
253 | 36 | shapeitemtexture.h \ | 36 | ucubuntushapetexture.h \ |
254 | 37 | shapeitem.h \ | 37 | ucubuntushape.h \ |
255 | 38 | inversemouseareatype.h \ | 38 | inversemouseareatype.h \ |
256 | 39 | qquickclipboard.h \ | 39 | qquickclipboard.h \ |
257 | 40 | qquickmimedata.h \ | 40 | qquickmimedata.h \ |
258 | @@ -88,7 +88,7 @@ | |||
259 | 88 | ucunits.cpp \ | 88 | ucunits.cpp \ |
260 | 89 | ucqquickimageextension.cpp \ | 89 | ucqquickimageextension.cpp \ |
261 | 90 | quickutils.cpp \ | 90 | quickutils.cpp \ |
263 | 91 | shapeitem.cpp \ | 91 | ucubuntushape.cpp \ |
264 | 92 | inversemouseareatype.cpp \ | 92 | inversemouseareatype.cpp \ |
265 | 93 | qquickclipboard.cpp \ | 93 | qquickclipboard.cpp \ |
266 | 94 | qquickmimedata.cpp \ | 94 | qquickmimedata.cpp \ |
267 | @@ -127,6 +127,13 @@ | |||
268 | 127 | # adapters | 127 | # adapters |
269 | 128 | SOURCES += adapters/alarmsadapter_organizer.cpp | 128 | SOURCES += adapters/alarmsadapter_organizer.cpp |
270 | 129 | 129 | ||
271 | 130 | RESOURCES += \ | ||
272 | 131 | plugin.qrc | ||
273 | 132 | |||
274 | 133 | OTHER_FILES += \ | ||
275 | 134 | shaders/shape.vert \ | ||
276 | 135 | shaders/shape.frag | ||
277 | 136 | |||
278 | 130 | # deployment rules for the plugin | 137 | # deployment rules for the plugin |
279 | 131 | installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /) | 138 | installPath = $$[QT_INSTALL_QML]/$$replace(uri, \\., /) |
280 | 132 | target.path = $$installPath | 139 | target.path = $$installPath |
281 | 133 | 140 | ||
282 | === added file 'modules/Ubuntu/Components/plugin/plugin.qrc' | |||
283 | --- modules/Ubuntu/Components/plugin/plugin.qrc 1970-01-01 00:00:00 +0000 | |||
284 | +++ modules/Ubuntu/Components/plugin/plugin.qrc 2015-03-02 15:41:23 +0000 | |||
285 | @@ -0,0 +1,6 @@ | |||
286 | 1 | <RCC> | ||
287 | 2 | <qresource prefix="/uc"> | ||
288 | 3 | <file>shaders/shape.frag</file> | ||
289 | 4 | <file>shaders/shape.vert</file> | ||
290 | 5 | </qresource> | ||
291 | 6 | </RCC> | ||
292 | 0 | 7 | ||
293 | === added directory 'modules/Ubuntu/Components/plugin/shaders' | |||
294 | === added file 'modules/Ubuntu/Components/plugin/shaders/shape.frag' | |||
295 | --- modules/Ubuntu/Components/plugin/shaders/shape.frag 1970-01-01 00:00:00 +0000 | |||
296 | +++ modules/Ubuntu/Components/plugin/shaders/shape.frag 2015-03-02 15:41:23 +0000 | |||
297 | @@ -0,0 +1,57 @@ | |||
298 | 1 | // Copyright © 2015 Canonical Ltd. | ||
299 | 2 | // | ||
300 | 3 | // This program is free software; you can redistribute it and/or modify | ||
301 | 4 | // it under the terms of the GNU Lesser General Public License as published by | ||
302 | 5 | // the Free Software Foundation; version 3. | ||
303 | 6 | // | ||
304 | 7 | // This program is distributed in the hope that it will be useful, | ||
305 | 8 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
306 | 9 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
307 | 10 | // GNU Lesser General Public License for more details. | ||
308 | 11 | // | ||
309 | 12 | // You should have received a copy of the GNU Lesser General Public License | ||
310 | 13 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
311 | 14 | // | ||
312 | 15 | // Author: Loïc Molinari <loic.molinari@canonical.com> | ||
313 | 16 | |||
314 | 17 | // Static flow control (branching on a uniform value) is fast on most GPUs (including ultra-low | ||
315 | 18 | // power ones) because it allows to use the same shader execution path for an entire draw call. We | ||
316 | 19 | // rely on that technique here (also known as "uber-shader" solution) to avoid the complexity of | ||
317 | 20 | // dealing with a multiple shaders solution. | ||
318 | 21 | // FIXME(loicm) Validate GPU behavior with regards to static flow control. | ||
319 | 22 | |||
320 | 23 | uniform sampler2D shapeTexture; | ||
321 | 24 | uniform sampler2D sourceTexture; | ||
322 | 25 | uniform lowp float sourceOpacity; | ||
323 | 26 | uniform lowp float opacity; | ||
324 | 27 | uniform bool textured; | ||
325 | 28 | |||
326 | 29 | varying mediump vec2 shapeCoord; | ||
327 | 30 | varying mediump vec4 sourceCoord; | ||
328 | 31 | varying lowp vec4 backgroundColor; | ||
329 | 32 | |||
330 | 33 | void main(void) | ||
331 | 34 | { | ||
332 | 35 | // Early texture fetch to cover latency as best as possible. | ||
333 | 36 | lowp vec4 shapeData = texture2D(shapeTexture, shapeCoord); | ||
334 | 37 | |||
335 | 38 | lowp vec4 color = backgroundColor; | ||
336 | 39 | |||
337 | 40 | // FIXME(loicm) Would be better to use a bitfield but bitwise ops have only been integrated in | ||
338 | 41 | // GLSL 1.3 (OpenGL 3) and GLSL ES 3 (OpenGL ES 3). | ||
339 | 42 | if (textured) { | ||
340 | 43 | // Blend the source over the current color (static flow control prevents the texture fetch). | ||
341 | 44 | lowp vec2 axisMask = -sign((sourceCoord.zw * sourceCoord.zw) - vec2(1.0)); | ||
342 | 45 | lowp float mask = clamp(axisMask.x + axisMask.y, 0.0, 1.0); | ||
343 | 46 | lowp vec4 source = texture2D(sourceTexture, sourceCoord.st) * vec4(sourceOpacity * mask); | ||
344 | 47 | color = vec4(1.0 - source.a) * color + source; | ||
345 | 48 | } | ||
346 | 49 | |||
347 | 50 | // Shape the current color with the mask. | ||
348 | 51 | color *= vec4(shapeData.b); | ||
349 | 52 | |||
350 | 53 | // Blend the border over the current color. | ||
351 | 54 | color = vec4(1.0 - shapeData.r) * color + shapeData.gggr; | ||
352 | 55 | |||
353 | 56 | gl_FragColor = color * vec4(opacity); | ||
354 | 57 | } | ||
355 | 0 | 58 | ||
356 | === added file 'modules/Ubuntu/Components/plugin/shaders/shape.vert' | |||
357 | --- modules/Ubuntu/Components/plugin/shaders/shape.vert 1970-01-01 00:00:00 +0000 | |||
358 | +++ modules/Ubuntu/Components/plugin/shaders/shape.vert 2015-03-02 15:41:23 +0000 | |||
359 | @@ -0,0 +1,43 @@ | |||
360 | 1 | // Copyright © 2015 Canonical Ltd. | ||
361 | 2 | // | ||
362 | 3 | // This program is free software; you can redistribute it and/or modify | ||
363 | 4 | // it under the terms of the GNU Lesser General Public License as published by | ||
364 | 5 | // the Free Software Foundation; version 3. | ||
365 | 6 | // | ||
366 | 7 | // This program is distributed in the hope that it will be useful, | ||
367 | 8 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
368 | 9 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
369 | 10 | // GNU Lesser General Public License for more details. | ||
370 | 11 | // | ||
371 | 12 | // You should have received a copy of the GNU Lesser General Public License | ||
372 | 13 | // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
373 | 14 | // | ||
374 | 15 | // Author: Loïc Molinari <loic.molinari@canonical.com> | ||
375 | 16 | |||
376 | 17 | uniform mediump mat4 matrix; | ||
377 | 18 | uniform bool textured; | ||
378 | 19 | |||
379 | 20 | attribute mediump vec4 positionAttrib; | ||
380 | 21 | attribute mediump vec2 shapeCoordAttrib; | ||
381 | 22 | attribute mediump vec4 sourceCoordAttrib; | ||
382 | 23 | attribute lowp vec4 backgroundColorAttrib; | ||
383 | 24 | |||
384 | 25 | // FIXME(loicm) Optimize by reducing/packing varyings. | ||
385 | 26 | varying mediump vec2 shapeCoord; | ||
386 | 27 | varying mediump vec4 sourceCoord; | ||
387 | 28 | varying lowp vec4 backgroundColor; | ||
388 | 29 | |||
389 | 30 | void main() | ||
390 | 31 | { | ||
391 | 32 | shapeCoord = shapeCoordAttrib; | ||
392 | 33 | |||
393 | 34 | // FIXME(loicm) Would be better to use a bitfield but bitwise ops have only been integrated in | ||
394 | 35 | // GLSL 1.3 (OpenGL 3) and GLSL ES 3 (OpenGL ES 3). | ||
395 | 36 | if (textured) { | ||
396 | 37 | sourceCoord = sourceCoordAttrib; | ||
397 | 38 | } | ||
398 | 39 | |||
399 | 40 | backgroundColor = backgroundColorAttrib; | ||
400 | 41 | |||
401 | 42 | gl_Position = matrix * positionAttrib; | ||
402 | 43 | } | ||
403 | 0 | 44 | ||
404 | === renamed file 'modules/Ubuntu/Components/plugin/shapeitem.cpp' => 'modules/Ubuntu/Components/plugin/ucubuntushape.cpp' | |||
405 | --- modules/Ubuntu/Components/plugin/shapeitem.cpp 2014-11-19 12:23:05 +0000 | |||
406 | +++ modules/Ubuntu/Components/plugin/ucubuntushape.cpp 2015-03-02 15:41:23 +0000 | |||
407 | @@ -1,5 +1,5 @@ | |||
408 | 1 | /* | 1 | /* |
410 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright 2013-2015 Canonical Ltd. |
411 | 3 | * | 3 | * |
412 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
413 | 5 | * it under the terms of the GNU Lesser General Public License as published by | 5 | * it under the terms of the GNU Lesser General Public License as published by |
414 | @@ -16,297 +16,803 @@ | |||
415 | 16 | * Author: Loïc Molinari <loic.molinari@canonical.com> | 16 | * Author: Loïc Molinari <loic.molinari@canonical.com> |
416 | 17 | */ | 17 | */ |
417 | 18 | 18 | ||
420 | 19 | #include "shapeitem.h" | 19 | // FIXME(loicm) Storing lower precision data types in the vertex buffer could be more efficent. On |
421 | 20 | #include "shapeitemtexture.h" | 20 | // PowerVR, for instance, that requires a conversion so the trade-off between shader cycles and |
422 | 21 | // bandwidth requirements must be benchmarked. | ||
423 | 22 | |||
424 | 23 | #include "ucubuntushape.h" | ||
425 | 24 | #include "ucubuntushapetexture.h" | ||
426 | 21 | #include "ucunits.h" | 25 | #include "ucunits.h" |
427 | 22 | #include <QtCore/QPointer> | 26 | #include <QtCore/QPointer> |
428 | 23 | #include <QtQuick/QQuickWindow> | 27 | #include <QtQuick/QQuickWindow> |
429 | 24 | #include <QtQuick/QSGTextureProvider> | 28 | #include <QtQuick/QSGTextureProvider> |
430 | 25 | #include <QtQuick/private/qquickimage_p.h> | 29 | #include <QtQuick/private/qquickimage_p.h> |
436 | 26 | 30 | #include <math.h> | |
437 | 27 | /*! | 31 | |
438 | 28 | \qmltype UbuntuShape | 32 | // --- Scene graph shader --- |
439 | 29 | \instantiates ShapeItem | 33 | |
440 | 30 | \inqmlmodule Ubuntu.Components 1.1 | 34 | ShapeShader::ShapeShader() |
441 | 35 | { | ||
442 | 36 | setShaderSourceFile(QOpenGLShader::Vertex, QStringLiteral(":/uc/shaders/shape.vert")); | ||
443 | 37 | setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/uc/shaders/shape.frag")); | ||
444 | 38 | } | ||
445 | 39 | |||
446 | 40 | char const* const* ShapeShader::attributeNames() const | ||
447 | 41 | { | ||
448 | 42 | static char const* const attributes[] = { | ||
449 | 43 | "positionAttrib", "shapeCoordAttrib", "sourceCoordAttrib", "backgroundColorAttrib", 0 | ||
450 | 44 | }; | ||
451 | 45 | return attributes; | ||
452 | 46 | } | ||
453 | 47 | |||
454 | 48 | void ShapeShader::initialize() | ||
455 | 49 | { | ||
456 | 50 | QSGMaterialShader::initialize(); | ||
457 | 51 | |||
458 | 52 | program()->bind(); | ||
459 | 53 | program()->setUniformValue("shapeTexture", 0); | ||
460 | 54 | program()->setUniformValue("sourceTexture", 1); | ||
461 | 55 | |||
462 | 56 | m_functions = QOpenGLContext::currentContext()->functions(); | ||
463 | 57 | m_matrixId = program()->uniformLocation("matrix"); | ||
464 | 58 | m_opacityId = program()->uniformLocation("opacity"); | ||
465 | 59 | m_sourceOpacityId = program()->uniformLocation("sourceOpacity"); | ||
466 | 60 | m_texturedId = program()->uniformLocation("textured"); | ||
467 | 61 | } | ||
468 | 62 | |||
469 | 63 | void ShapeShader::updateState( | ||
470 | 64 | const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) | ||
471 | 65 | { | ||
472 | 66 | Q_UNUSED(oldEffect); | ||
473 | 67 | |||
474 | 68 | const ShapeMaterial::Data* data = static_cast<ShapeMaterial*>(newEffect)->constData(); | ||
475 | 69 | |||
476 | 70 | // Bind shape texture. | ||
477 | 71 | QSGTexture* shapeTexture = data->shapeTexture; | ||
478 | 72 | if (shapeTexture) { | ||
479 | 73 | shapeTexture->setFiltering(static_cast<QSGTexture::Filtering>(data->shapeTextureFiltering)); | ||
480 | 74 | shapeTexture->setHorizontalWrapMode(QSGTexture::ClampToEdge); | ||
481 | 75 | shapeTexture->setVerticalWrapMode(QSGTexture::ClampToEdge); | ||
482 | 76 | shapeTexture->bind(); | ||
483 | 77 | } else { | ||
484 | 78 | glBindTexture(GL_TEXTURE_2D, 0); | ||
485 | 79 | } | ||
486 | 80 | |||
487 | 81 | if (data->flags & ShapeMaterial::Data::Textured) { | ||
488 | 82 | // Bind image texture. | ||
489 | 83 | m_functions->glActiveTexture(GL_TEXTURE1); | ||
490 | 84 | QSGTextureProvider* provider = data->sourceTextureProvider; | ||
491 | 85 | QSGTexture* texture = provider ? provider->texture() : NULL; | ||
492 | 86 | if (texture) { | ||
493 | 87 | if (data->flags & ShapeMaterial::Data::Repeated) { | ||
494 | 88 | if (texture->isAtlasTexture()) { | ||
495 | 89 | // A texture in an atlas can't be repeated with builtin GPU facility (exposed by | ||
496 | 90 | // GL_REPEAT with OpenGL), so we extract it and create a new dedicated one. | ||
497 | 91 | texture = texture->removedFromAtlas(); | ||
498 | 92 | } | ||
499 | 93 | texture->setHorizontalWrapMode( | ||
500 | 94 | data->flags & ShapeMaterial::Data::HorizontallyRepeated ? | ||
501 | 95 | QSGTexture::Repeat : QSGTexture::ClampToEdge); | ||
502 | 96 | texture->setVerticalWrapMode( | ||
503 | 97 | data->flags & ShapeMaterial::Data::VerticallyRepeated ? | ||
504 | 98 | QSGTexture::Repeat : QSGTexture::ClampToEdge); | ||
505 | 99 | } | ||
506 | 100 | texture->bind(); | ||
507 | 101 | } else { | ||
508 | 102 | glBindTexture(GL_TEXTURE_2D, 0); | ||
509 | 103 | } | ||
510 | 104 | m_functions->glActiveTexture(GL_TEXTURE0); | ||
511 | 105 | // Update image uniform. | ||
512 | 106 | const float u8toF32 = 1.0f / 255.0f; | ||
513 | 107 | program()->setUniformValue(m_sourceOpacityId, data->sourceOpacity * u8toF32); | ||
514 | 108 | } | ||
515 | 109 | |||
516 | 110 | program()->setUniformValue(m_texturedId, !!(data->flags & ShapeMaterial::Data::Textured)); | ||
517 | 111 | |||
518 | 112 | // Update QtQuick engine uniforms. | ||
519 | 113 | if (state.isMatrixDirty()) { | ||
520 | 114 | program()->setUniformValue(m_matrixId, state.combinedMatrix()); | ||
521 | 115 | } | ||
522 | 116 | if (state.isOpacityDirty()) { | ||
523 | 117 | program()->setUniformValue(m_opacityId, state.opacity()); | ||
524 | 118 | } | ||
525 | 119 | } | ||
526 | 120 | |||
527 | 121 | // --- Scene graph material --- | ||
528 | 122 | |||
529 | 123 | ShapeMaterial::ShapeMaterial() | ||
530 | 124 | { | ||
531 | 125 | // The whole struct (with the padding bytes) must be initialized for memcmp() to work as | ||
532 | 126 | // expected in ShapeMaterial::compare(). | ||
533 | 127 | memset(&m_data, 0x00, sizeof(Data)); | ||
534 | 128 | setFlag(Blending); | ||
535 | 129 | } | ||
536 | 130 | |||
537 | 131 | QSGMaterialType* ShapeMaterial::type() const | ||
538 | 132 | { | ||
539 | 133 | static QSGMaterialType type; | ||
540 | 134 | return &type; | ||
541 | 135 | } | ||
542 | 136 | |||
543 | 137 | QSGMaterialShader* ShapeMaterial::createShader() const | ||
544 | 138 | { | ||
545 | 139 | return new ShapeShader; | ||
546 | 140 | } | ||
547 | 141 | |||
548 | 142 | int ShapeMaterial::compare(const QSGMaterial* other) const | ||
549 | 143 | { | ||
550 | 144 | // Repeat wrap modes require textures to be extracted from their atlases. Since we just store | ||
551 | 145 | // the texture provider in the material data (not the texture as we want to do the extraction at | ||
552 | 146 | // QSGShader::updateState() time), we make the comparison fail when repeat wrapping is set. | ||
553 | 147 | const ShapeMaterial::Data* otherData = static_cast<const ShapeMaterial*>(other)->constData(); | ||
554 | 148 | return memcmp(&m_data, otherData, sizeof(m_data)) | ||
555 | 149 | | (m_data.flags & ShapeMaterial::Data::Repeated); | ||
556 | 150 | } | ||
557 | 151 | |||
558 | 152 | // --- Scene graph node --- | ||
559 | 153 | |||
560 | 154 | ShapeNode::ShapeNode() | ||
561 | 155 | : QSGGeometryNode() | ||
562 | 156 | , m_material() | ||
563 | 157 | , m_geometry(attributeSet(), vertexCount, indexCount, indexType) | ||
564 | 158 | { | ||
565 | 159 | memcpy(m_geometry.indexData(), indices(), indexCount * indexTypeSize); | ||
566 | 160 | m_geometry.setDrawingMode(drawingMode); | ||
567 | 161 | m_geometry.setIndexDataPattern(indexDataPattern); | ||
568 | 162 | m_geometry.setVertexDataPattern(vertexDataPattern); | ||
569 | 163 | setMaterial(&m_material); | ||
570 | 164 | setGeometry(&m_geometry); | ||
571 | 165 | } | ||
572 | 166 | |||
573 | 167 | // static | ||
574 | 168 | const unsigned short* ShapeNode::indices() | ||
575 | 169 | { | ||
576 | 170 | // Don't forget to update indexCount if changed. | ||
577 | 171 | static const unsigned short indices[] = { | ||
578 | 172 | 0, 4, 1, 5, 2, 6, 3, 7, // Triangles 1 to 6. | ||
579 | 173 | 7, 4, // Degenerate triangles. | ||
580 | 174 | 4, 8, 5, 9, 6, 10, 7, 11, // Triangles 7 to 12. | ||
581 | 175 | 11, 8, // Degenerate triangles. | ||
582 | 176 | 8, 12, 9, 13, 10, 14, 11, 15 // Triangles 13 to 18. | ||
583 | 177 | }; | ||
584 | 178 | return indices; | ||
585 | 179 | } | ||
586 | 180 | |||
587 | 181 | // static | ||
588 | 182 | const QSGGeometry::AttributeSet& ShapeNode::attributeSet() | ||
589 | 183 | { | ||
590 | 184 | static const QSGGeometry::Attribute attributes[] = { | ||
591 | 185 | QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), | ||
592 | 186 | QSGGeometry::Attribute::create(1, 2, GL_FLOAT), | ||
593 | 187 | QSGGeometry::Attribute::create(2, 4, GL_FLOAT), | ||
594 | 188 | QSGGeometry::Attribute::create(3, 4, GL_UNSIGNED_BYTE) | ||
595 | 189 | }; | ||
596 | 190 | static const QSGGeometry::AttributeSet attributeSet = { | ||
597 | 191 | 4, sizeof(Vertex), attributes | ||
598 | 192 | }; | ||
599 | 193 | return attributeSet; | ||
600 | 194 | } | ||
601 | 195 | |||
602 | 196 | // --- QtQuick item --- | ||
603 | 197 | |||
604 | 198 | struct ShapeTextures | ||
605 | 199 | { | ||
606 | 200 | ShapeTextures() : high(0), low(0) {} | ||
607 | 201 | QSGTexture* high; | ||
608 | 202 | QSGTexture* low; | ||
609 | 203 | }; | ||
610 | 204 | |||
611 | 205 | static QHash<QOpenGLContext*, ShapeTextures> shapeTexturesHash; | ||
612 | 206 | |||
613 | 207 | const float implicitGridUnitWidth = 8.0f; | ||
614 | 208 | const float implicitGridUnitHeight = 8.0f; | ||
615 | 209 | |||
616 | 210 | // Threshold in grid unit defining the texture quality to be used. | ||
617 | 211 | const float lowHighTextureThreshold = 11.0f; | ||
618 | 212 | |||
619 | 213 | /*! \qmltype UbuntuShape | ||
620 | 214 | \instantiates UCUbuntuShape | ||
621 | 215 | \inqmlmodule Ubuntu.Components 1.2 | ||
622 | 31 | \ingroup ubuntu | 216 | \ingroup ubuntu |
634 | 32 | \brief The UbuntuShape item provides a standard Ubuntu shaped rounded rectangle. | 217 | \brief Rounded rectangle containing a source image blended over a background color. |
635 | 33 | 218 | ||
636 | 34 | The UbuntuShape is used where a rounded rectangle is needed either filled | 219 | The UbuntuShape is a rounded rectangle (based on a \l |
637 | 35 | with a color or an image that it crops. | 220 | {https://en.wikipedia.org/wiki/Squircle}{squircle}) containing an optional source image blended |
638 | 36 | 221 | over a background color (solid or linear gradient). Different properties allow to change the | |
639 | 37 | When given with a \l color it is applied with an overlay blending as a | 222 | look of the shape. |
629 | 38 | vertical gradient going from \l color to \l gradientColor. | ||
630 | 39 | Two corner \l radius are available, "small" (default) and "medium", that | ||
631 | 40 | determine the size of the corners. | ||
632 | 41 | Optionally, an Image can be passed that will be displayed inside the | ||
633 | 42 | UbuntuShape and cropped to fit it. | ||
640 | 43 | 223 | ||
641 | 44 | Examples: | 224 | Examples: |
807 | 45 | \qml | 225 | |
808 | 46 | import Ubuntu.Components 1.1 | 226 | \qml |
809 | 47 | 227 | import Ubuntu.Components 1.2 | |
810 | 48 | UbuntuShape { | 228 | |
811 | 49 | color: "lightblue" | 229 | UbuntuShape { |
812 | 50 | radius: "medium" | 230 | backgroundColor: "green" |
813 | 51 | } | 231 | } |
814 | 52 | \endqml | 232 | \endqml |
815 | 53 | 233 | ||
816 | 54 | \qml | 234 | \qml |
817 | 55 | import Ubuntu.Components 1.1 | 235 | import Ubuntu.Components 1.2 |
818 | 56 | 236 | ||
819 | 57 | UbuntuShape { | 237 | UbuntuShape { |
820 | 58 | image: Image { | 238 | source: Image { |
821 | 59 | source: "icon.png" | 239 | source: "ubuntu.png" |
822 | 60 | } | 240 | } |
823 | 61 | } | 241 | } |
824 | 62 | \endqml | 242 | \endqml |
825 | 63 | */ | 243 | */ |
826 | 64 | 244 | UCUbuntuShape::UCUbuntuShape(QQuickItem* parent) | |
662 | 65 | /*! | ||
663 | 66 | \qmlproperty string UbuntuShape::radius | ||
664 | 67 | |||
665 | 68 | The size of the corners among: "small" (default) and "medium". | ||
666 | 69 | */ | ||
667 | 70 | |||
668 | 71 | /*! | ||
669 | 72 | \qmlproperty color UbuntuShape::color | ||
670 | 73 | |||
671 | 74 | The top color of the gradient used to fill the shape. Setting only this | ||
672 | 75 | one is enough to set the overall color the shape. | ||
673 | 76 | */ | ||
674 | 77 | |||
675 | 78 | /*! | ||
676 | 79 | \qmlproperty color UbuntuShape::gradientColor | ||
677 | 80 | |||
678 | 81 | The bottom color of the gradient used for the overlay blending of the | ||
679 | 82 | color that fills the shape. It is optional to set this one as setting | ||
680 | 83 | \l color is enough to set the overall color of the shape. | ||
681 | 84 | */ | ||
682 | 85 | |||
683 | 86 | /*! | ||
684 | 87 | \qmlproperty string UbuntuShape::borderSource | ||
685 | 88 | |||
686 | 89 | This property defines the look of the shape borders. The supported strings | ||
687 | 90 | are \c "radius_idle.sci" providing an idle button style and | ||
688 | 91 | "radius_pressed.sci" providing a pressed button style. Any other strings | ||
689 | 92 | (like the empty one "") disables styling. Default value is \c | ||
690 | 93 | "radius_idle.sci". | ||
691 | 94 | |||
692 | 95 | \note We plan to expose that feature through styling properties. | ||
693 | 96 | */ | ||
694 | 97 | |||
695 | 98 | /*! | ||
696 | 99 | \qmlproperty Image UbuntuShape::image | ||
697 | 100 | |||
698 | 101 | The image used to fill the shape. | ||
699 | 102 | */ | ||
700 | 103 | |||
701 | 104 | // Retrieves the size of an array at compile time. | ||
702 | 105 | #define ARRAY_SIZE(a) \ | ||
703 | 106 | ((sizeof(a) / sizeof(*(a))) / static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) | ||
704 | 107 | |||
705 | 108 | // Threshold in grid unit defining the texture quality to be used. | ||
706 | 109 | const float lowHighTextureThreshold = 11.0f; | ||
707 | 110 | |||
708 | 111 | // Map of windows and associated textures. | ||
709 | 112 | QHash<QOpenGLContext*, ShapeItem::TextureHandles> ShapeItem::textures_; | ||
710 | 113 | |||
711 | 114 | static const char* const shapeVertexShader = | ||
712 | 115 | "uniform lowp mat4 matrix; \n" | ||
713 | 116 | "attribute lowp vec4 positionAttrib; \n" | ||
714 | 117 | "attribute lowp vec2 shapeCoordAttrib; \n" | ||
715 | 118 | "attribute lowp vec2 imageCoordAttrib; \n" | ||
716 | 119 | "varying lowp vec2 shapeCoord; \n" | ||
717 | 120 | "varying lowp vec2 imageCoord; \n" | ||
718 | 121 | "void main() \n" | ||
719 | 122 | "{ \n" | ||
720 | 123 | " shapeCoord = shapeCoordAttrib; \n" | ||
721 | 124 | " imageCoord = imageCoordAttrib; \n" | ||
722 | 125 | " gl_Position = matrix * positionAttrib; \n" | ||
723 | 126 | "}"; | ||
724 | 127 | |||
725 | 128 | static const char* const shapeTexturedFragmentShader = | ||
726 | 129 | "uniform lowp float opacity; \n" | ||
727 | 130 | "uniform sampler2D shapeTexture; \n" | ||
728 | 131 | "uniform sampler2D imageTexture; \n" | ||
729 | 132 | "varying lowp vec2 shapeCoord; \n" | ||
730 | 133 | "varying lowp vec2 imageCoord; \n" | ||
731 | 134 | "void main() \n" | ||
732 | 135 | "{ \n" | ||
733 | 136 | " lowp vec4 shapeData = texture2D(shapeTexture, shapeCoord); \n" | ||
734 | 137 | " lowp vec4 color = texture2D(imageTexture, imageCoord) * vec4(shapeData.b); \n" | ||
735 | 138 | " lowp vec4 blend = shapeData.gggr + vec4(1.0 - shapeData.r) * color; \n" | ||
736 | 139 | " gl_FragColor = blend * vec4(opacity); \n" | ||
737 | 140 | "}"; | ||
738 | 141 | |||
739 | 142 | static const char* const shapeColoredFragmentShader = | ||
740 | 143 | "uniform lowp float opacity; \n" | ||
741 | 144 | "uniform sampler2D shapeTexture; \n" | ||
742 | 145 | "uniform lowp vec4 color; \n" | ||
743 | 146 | "uniform lowp vec4 gradientColor; \n" | ||
744 | 147 | "varying lowp vec2 shapeCoord; \n" | ||
745 | 148 | "varying lowp vec2 imageCoord; \n" | ||
746 | 149 | "void main(void) \n" | ||
747 | 150 | "{ \n" | ||
748 | 151 | " lowp vec4 shapeData = texture2D(shapeTexture, shapeCoord); \n" | ||
749 | 152 | " lowp vec4 result = mix(color, gradientColor, imageCoord.t) * vec4(shapeData.b); \n" | ||
750 | 153 | " lowp vec4 blend = shapeData.gggr + vec4(1.0 - shapeData.r) * result; \n" | ||
751 | 154 | " gl_FragColor = blend * vec4(opacity); \n" | ||
752 | 155 | "}"; | ||
753 | 156 | |||
754 | 157 | static const unsigned short shapeMeshIndices[] __attribute__((aligned(16))) = { | ||
755 | 158 | 0, 4, 1, 5, 2, 6, 3, 7, // Triangles 1 to 6. | ||
756 | 159 | 7, 4, // Degenerate triangles. | ||
757 | 160 | 4, 8, 5, 9, 6, 10, 7, 11, // Triangles 7 to 12. | ||
758 | 161 | 11, 8, // Degenerate triangles. | ||
759 | 162 | 8, 12, 9, 13, 10, 14, 11, 15 // Triangles 13 to 18 | ||
760 | 163 | }; | ||
761 | 164 | |||
762 | 165 | static const struct { | ||
763 | 166 | const unsigned short* const indices; | ||
764 | 167 | int indexCount; // Number of indices. | ||
765 | 168 | int vertexCount; // Number of vertices. | ||
766 | 169 | int attributeCount; // Number of attributes. | ||
767 | 170 | int stride; // Offset in bytes from one vertex to the other. | ||
768 | 171 | int positionCount; // Number of components per position. | ||
769 | 172 | int positionType; // OpenGL type of the position components. | ||
770 | 173 | int shapeCoordCount; // Number of components per shape texture coordinate. | ||
771 | 174 | int shapeCoordType; // OpenGL type of the shape texture coordinate components. | ||
772 | 175 | int imageCoordCount; // Number of components per image texture coordinate. | ||
773 | 176 | int imageCoordType; // OpenGL type of the image texture coordinate components. | ||
774 | 177 | int indexType; // OpenGL type of the indices. | ||
775 | 178 | } shapeMesh = { | ||
776 | 179 | shapeMeshIndices, ARRAY_SIZE(shapeMeshIndices), | ||
777 | 180 | 16, 3, sizeof(ShapeNode::Vertex), 2, GL_FLOAT, 2, GL_FLOAT, 2, GL_FLOAT, GL_UNSIGNED_SHORT | ||
778 | 181 | }; | ||
779 | 182 | |||
780 | 183 | static const QSGGeometry::AttributeSet& getAttributes() | ||
781 | 184 | { | ||
782 | 185 | static QSGGeometry::Attribute data[] = { | ||
783 | 186 | QSGGeometry::Attribute::create(0, shapeMesh.positionCount, shapeMesh.positionType, true), | ||
784 | 187 | QSGGeometry::Attribute::create(1, shapeMesh.shapeCoordCount, shapeMesh.shapeCoordType), | ||
785 | 188 | QSGGeometry::Attribute::create(2, shapeMesh.imageCoordCount, shapeMesh.imageCoordType) | ||
786 | 189 | }; | ||
787 | 190 | static QSGGeometry::AttributeSet attributes = { | ||
788 | 191 | shapeMesh.attributeCount, shapeMesh.stride, data | ||
789 | 192 | }; | ||
790 | 193 | return attributes; | ||
791 | 194 | } | ||
792 | 195 | |||
793 | 196 | // Gets the size in bytes of an OpenGL type in the range [GL_BYTE, GL_DOUBLE]. | ||
794 | 197 | static int sizeOfType(GLenum type) | ||
795 | 198 | { | ||
796 | 199 | static int sizes[] = { | ||
797 | 200 | sizeof(char), sizeof(unsigned char), sizeof(short), sizeof(unsigned short), sizeof(int), | ||
798 | 201 | sizeof(unsigned int), sizeof(float), 2, 3, 4, sizeof(double) | ||
799 | 202 | }; | ||
800 | 203 | Q_ASSERT(type >= 0x1400 && type <= 0x140a); | ||
801 | 204 | return sizes[type - 0x1400]; | ||
802 | 205 | } | ||
803 | 206 | |||
804 | 207 | // --- QtQuick item --- | ||
805 | 208 | |||
806 | 209 | ShapeItem::ShapeItem(QQuickItem* parent) | ||
827 | 210 | : QQuickItem(parent) | 245 | : QQuickItem(parent) |
841 | 211 | , provider_(NULL) | 246 | , m_source(NULL) |
842 | 212 | , color_(0.0, 0.0, 0.0, 0.0) | 247 | , m_sourceTextureProvider(NULL) |
843 | 213 | , gradientColor_(0.0, 0.0, 0.0, 0.0) | 248 | , m_backgroundColor(qRgba(0, 0, 0, 0)) |
844 | 214 | , gradientColorSet_(false) | 249 | , m_secondaryBackgroundColor(qRgba(0, 0, 0, 0)) |
845 | 215 | , radiusString_("small") | 250 | , m_sourceScale(1.0f, 1.0f) |
846 | 216 | , radius_(ShapeItem::SmallRadius) | 251 | , m_sourceTranslation(0.0f, 0.0f) |
847 | 217 | , border_(ShapeItem::IdleBorder) | 252 | , m_sourceTransform(1.0f, 1.0f, 0.0f, 0.0f) |
848 | 218 | , image_(NULL) | 253 | , m_radius(SmallRadius) |
849 | 219 | , stretched_(true) | 254 | , m_border(IdleBorder) |
850 | 220 | , hAlignment_(ShapeItem::AlignHCenter) | 255 | , m_imageHorizontalAlignment(AlignHCenter) |
851 | 221 | , vAlignment_(ShapeItem::AlignVCenter) | 256 | , m_imageVerticalAlignment(AlignVCenter) |
852 | 222 | , gridUnit_(UCUnits::instance().gridUnit()) | 257 | , m_backgroundMode(SolidColor) |
853 | 223 | , geometry_() | 258 | , m_sourceHorizontalAlignment(AlignHCenter) |
854 | 259 | , m_sourceVerticalAlignment(AlignVCenter) | ||
855 | 260 | , m_sourceFillMode(Stretch) | ||
856 | 261 | , m_sourceHorizontalWrapMode(Transparent) | ||
857 | 262 | , m_sourceVerticalWrapMode(Transparent) | ||
858 | 263 | , m_sourceOpacity(255) | ||
859 | 264 | , m_flags(Stretched) | ||
860 | 224 | { | 265 | { |
861 | 225 | setFlag(ItemHasContents); | 266 | setFlag(ItemHasContents); |
862 | 226 | QObject::connect(&UCUnits::instance(), SIGNAL(gridUnitChanged()), this, | 267 | QObject::connect(&UCUnits::instance(), SIGNAL(gridUnitChanged()), this, |
866 | 227 | SLOT(gridUnitChanged())); | 268 | SLOT(_q_gridUnitChanged())); |
867 | 228 | setImplicitWidth(8 * gridUnit_); | 269 | const float gridUnit = UCUnits::instance().gridUnit(); |
868 | 229 | setImplicitHeight(8 * gridUnit_); | 270 | setImplicitWidth(implicitGridUnitWidth * gridUnit); |
869 | 271 | setImplicitHeight(implicitGridUnitHeight * gridUnit); | ||
870 | 230 | update(); | 272 | update(); |
871 | 231 | } | 273 | } |
872 | 232 | 274 | ||
902 | 233 | void ShapeItem::setColor(const QColor& color) | 275 | /*! \qmlproperty string UbuntuShape::radius |
903 | 234 | { | 276 | |
904 | 235 | if (color_ != color) { | 277 | This property defines the corner radius. Two fixed values are supported: \c "small" and \c |
905 | 236 | color_ = color; | 278 | "medium". The default value is \c "small". |
906 | 237 | // gradientColor has the same value as color unless it was manually set | 279 | */ |
907 | 238 | if (!gradientColorSet_) { | 280 | void UCUbuntuShape::setRadius(const QString& radius) |
908 | 239 | gradientColor_ = color; | 281 | { |
909 | 240 | Q_EMIT gradientColorChanged(); | 282 | const Radius newRadius = (radius == "medium") ? MediumRadius : SmallRadius; |
910 | 241 | } | 283 | if (m_radius != newRadius) { |
911 | 242 | update(); | 284 | m_radius = newRadius; |
883 | 243 | Q_EMIT colorChanged(); | ||
884 | 244 | } | ||
885 | 245 | } | ||
886 | 246 | |||
887 | 247 | void ShapeItem::setGradientColor(const QColor& gradientColor) | ||
888 | 248 | { | ||
889 | 249 | gradientColorSet_ = true; | ||
890 | 250 | if (gradientColor_ != gradientColor) { | ||
891 | 251 | gradientColor_ = gradientColor; | ||
892 | 252 | update(); | ||
893 | 253 | Q_EMIT gradientColorChanged(); | ||
894 | 254 | } | ||
895 | 255 | } | ||
896 | 256 | |||
897 | 257 | void ShapeItem::setRadius(const QString& radius) | ||
898 | 258 | { | ||
899 | 259 | if (radiusString_ != radius) { | ||
900 | 260 | radiusString_ = radius; | ||
901 | 261 | radius_ = (radius == "medium") ? ShapeItem::MediumRadius : ShapeItem::SmallRadius; | ||
912 | 262 | update(); | 285 | update(); |
913 | 263 | Q_EMIT radiusChanged(); | 286 | Q_EMIT radiusChanged(); |
914 | 264 | } | 287 | } |
915 | 265 | } | 288 | } |
916 | 266 | 289 | ||
918 | 267 | void ShapeItem::setBorderSource(const QString& borderSource) | 290 | /*! \qmlproperty string UbuntuShape::borderSource |
919 | 291 | |||
920 | 292 | This property defines the look of the shape borders. The supported strings are \c | ||
921 | 293 | "radius_idle.sci" providing an idle button style and \c "radius_pressed.sci" providing a pressed | ||
922 | 294 | button style. Any other strings (like the empty one \c "") disables styling. The default value | ||
923 | 295 | is \c "radius_idle.sci". | ||
924 | 296 | */ | ||
925 | 297 | void UCUbuntuShape::setBorderSource(const QString& borderSource) | ||
926 | 268 | { | 298 | { |
935 | 269 | if (borderSource_ != borderSource) { | 299 | Border border; |
936 | 270 | if (borderSource.endsWith(QString("radius_idle.sci"))) | 300 | if (borderSource.endsWith(QString("radius_idle.sci"))) { |
937 | 271 | border_ = ShapeItem::IdleBorder; | 301 | border = IdleBorder; |
938 | 272 | else if (borderSource.endsWith(QString("radius_pressed.sci"))) | 302 | } else if (borderSource.endsWith(QString("radius_pressed.sci"))) { |
939 | 273 | border_ = ShapeItem::PressedBorder; | 303 | border = PressedBorder; |
940 | 274 | else | 304 | } else { |
941 | 275 | border_ = ShapeItem::RawBorder; | 305 | border = RawBorder; |
942 | 276 | borderSource_ = borderSource; | 306 | } |
943 | 307 | if (m_border != border) { | ||
944 | 308 | m_border = border; | ||
945 | 277 | update(); | 309 | update(); |
946 | 278 | Q_EMIT borderSourceChanged(); | 310 | Q_EMIT borderSourceChanged(); |
947 | 279 | } | 311 | } |
948 | 280 | } | 312 | } |
949 | 281 | 313 | ||
974 | 282 | void ShapeItem::setImage(const QVariant& image) | 314 | // Deprecation layer. |
975 | 283 | { | 315 | void UCUbuntuShape::dropImageSupport() |
976 | 284 | QQuickItem* newImage = qobject_cast<QQuickItem*>(qvariant_cast<QObject*>(image)); | 316 | { |
977 | 285 | if (image_ != newImage) { | 317 | if (!(m_flags & SourceApiSet)) { |
978 | 286 | image_ = newImage; | 318 | m_flags |= SourceApiSet; |
979 | 287 | 319 | if (m_source) { | |
980 | 288 | // update values of properties that depend on properties of the image | 320 | QObject::disconnect(m_source); |
981 | 289 | QObject::disconnect(image_); | 321 | m_source = NULL; |
982 | 290 | if (newImage != NULL) { | 322 | update(); |
983 | 291 | updateFromImageProperties(newImage); | 323 | Q_EMIT imageChanged(); |
984 | 292 | connectToImageProperties(newImage); | 324 | } |
985 | 293 | } | 325 | } |
986 | 294 | 326 | } | |
987 | 295 | if (image_ && !image_->parentItem()) { | 327 | |
988 | 296 | // Inlined images need a parent and must not be visible. | 328 | /*! \qmlproperty variant UbuntuShape::source |
989 | 297 | image_->setParentItem(this); | 329 | \since Ubuntu.Components 1.2 |
990 | 298 | image_->setVisible(false); | 330 | |
991 | 299 | } | 331 | This property sets the source provider of a texture rendered in the UbuntuShape. Supported types |
992 | 300 | update(); | 332 | are \c Image, \c AnimatedImage (to render a GIF image for instance) and \c ShaderEffectSource |
993 | 301 | Q_EMIT imageChanged(); | 333 | (to embed a UI previously rendered with QML). It is blended over the background color. The |
994 | 302 | } | 334 | default value is \c null. |
995 | 303 | } | 335 | |
996 | 304 | 336 | It can be set either with an inlined \c Image: | |
997 | 305 | void ShapeItem::updateFromImageProperties(QQuickItem* image) | 337 | |
998 | 338 | \qml | ||
999 | 339 | Item { | ||
1000 | 340 | UbuntuShape { | ||
1001 | 341 | source: Image { source: "ubuntu.png" } | ||
1002 | 342 | } | ||
1003 | 343 | } | ||
1004 | 344 | \endqml | ||
1005 | 345 | |||
1006 | 346 | or with an \c Image \c id: | ||
1007 | 347 | |||
1008 | 348 | \qml | ||
1009 | 349 | Item { | ||
1010 | 350 | Image { | ||
1011 | 351 | id: img | ||
1012 | 352 | visible: false | ||
1013 | 353 | source: "ubuntu.png" | ||
1014 | 354 | } | ||
1015 | 355 | UbuntuShape { | ||
1016 | 356 | source: img | ||
1017 | 357 | } | ||
1018 | 358 | } | ||
1019 | 359 | \endqml | ||
1020 | 360 | |||
1021 | 361 | Note that in this case, the \c Image is stored in the scene tree as any other items. So setting | ||
1022 | 362 | it as not visible might be needed. | ||
1023 | 363 | |||
1024 | 364 | The \l{https://en.wikipedia.org/wiki/Texture_filtering}{sampling filter} is set through the | ||
1025 | 365 | given Item's \c smooth property. Set it to \c false for nearest-neighbor filtering or to \c true | ||
1026 | 366 | for bilinear filtering. | ||
1027 | 367 | |||
1028 | 368 | The fill modes and alignments set on the \c Image and \c AnimatedImage are not monitored, use | ||
1029 | 369 | the appropriate UbuntuShape properties instead (\l sourceFillMode, \l sourceHorizontalAlignment | ||
1030 | 370 | and \l sourceVerticalAlignment). | ||
1031 | 371 | |||
1032 | 372 | \note Setting this disables support for the deprecated \l image property. | ||
1033 | 373 | */ | ||
1034 | 374 | void UCUbuntuShape::setSource(const QVariant& source) | ||
1035 | 375 | { | ||
1036 | 376 | dropImageSupport(); | ||
1037 | 377 | |||
1038 | 378 | QQuickItem* newSource = qobject_cast<QQuickItem*>(qvariant_cast<QObject*>(source)); | ||
1039 | 379 | if (m_source != newSource) { | ||
1040 | 380 | if (newSource) { | ||
1041 | 381 | if (!newSource->parentItem()) { | ||
1042 | 382 | // Inlined images need a parent and must not be visible. | ||
1043 | 383 | newSource->setParentItem(this); | ||
1044 | 384 | newSource->setVisible(false); | ||
1045 | 385 | } | ||
1046 | 386 | m_flags |= DirtySourceTransform; | ||
1047 | 387 | } | ||
1048 | 388 | m_source = newSource; | ||
1049 | 389 | update(); | ||
1050 | 390 | Q_EMIT sourceChanged(); | ||
1051 | 391 | } | ||
1052 | 392 | } | ||
1053 | 393 | |||
1054 | 394 | /*! \qmlproperty real UbuntuShape::sourceOpacity | ||
1055 | 395 | \since Ubuntu.Components 1.2 | ||
1056 | 396 | |||
1057 | 397 | This property holds the opacity of the \l source texture. Opacity is specified as a number | ||
1058 | 398 | between 0.0 (fully transparent) and 1.0 (fully opaque). The default value is 1.0. | ||
1059 | 399 | |||
1060 | 400 | \note Setting this disables support for the deprecated \l image property. | ||
1061 | 401 | */ | ||
1062 | 402 | void UCUbuntuShape::setSourceOpacity(float sourceOpacity) | ||
1063 | 403 | { | ||
1064 | 404 | dropImageSupport(); | ||
1065 | 405 | |||
1066 | 406 | const quint8 sourceOpacityPacked = | ||
1067 | 407 | qMax(0.0f, qMin(1.0f, sourceOpacity)) * static_cast<float>(0xff); | ||
1068 | 408 | if (m_sourceOpacity != sourceOpacityPacked) { | ||
1069 | 409 | m_sourceOpacity = sourceOpacityPacked; | ||
1070 | 410 | update(); | ||
1071 | 411 | Q_EMIT sourceOpacityChanged(); | ||
1072 | 412 | } | ||
1073 | 413 | } | ||
1074 | 414 | |||
1075 | 415 | /*! \qmlproperty enumeration UbuntuShape::sourceFillMode | ||
1076 | 416 | \since Ubuntu.Components 1.2 | ||
1077 | 417 | |||
1078 | 418 | This properties defines how the \l source texture fills the UbuntuShape. The modes are the same | ||
1079 | 419 | as the ones used by \c Image, minus the tiling which is exposed through wrapping properties (\l | ||
1080 | 420 | sourceHorizontalWrapMode and \l sourceVerticalWrapMode). The default value is \c | ||
1081 | 421 | UbuntuShape.Stretch. | ||
1082 | 422 | |||
1083 | 423 | \note Setting this disables support for the deprecated \l image property. | ||
1084 | 424 | |||
1085 | 425 | \list | ||
1086 | 426 | \li \b UbuntuShape.Stretch - the source is scaled non-uniformly to fit | ||
1087 | 427 | \li \b UbuntuShape.PreserveAspectFit - the source is scaled uniformly to fit without cropping | ||
1088 | 428 | \li \b UbuntuShape.PreserveAspectCrop - the source is scaled uniformly to fit with cropping | ||
1089 | 429 | \li \b UbuntuShape.Pad - the source is not scaled | ||
1090 | 430 | \endlist | ||
1091 | 431 | */ | ||
1092 | 432 | void UCUbuntuShape::setSourceFillMode(UCUbuntuShape::FillMode sourceFillMode) | ||
1093 | 433 | { | ||
1094 | 434 | dropImageSupport(); | ||
1095 | 435 | |||
1096 | 436 | if (m_sourceFillMode != sourceFillMode) { | ||
1097 | 437 | m_sourceFillMode = sourceFillMode; | ||
1098 | 438 | m_flags |= DirtySourceTransform; | ||
1099 | 439 | update(); | ||
1100 | 440 | Q_EMIT sourceFillModeChanged(); | ||
1101 | 441 | } | ||
1102 | 442 | } | ||
1103 | 443 | |||
1104 | 444 | /*! \qmlproperty enumeration UbuntuShape::sourceHorizontalWrapMode | ||
1105 | 445 | \qmlproperty enumeration UbuntuShape::sourceVerticalWrapMode | ||
1106 | 446 | \since Ubuntu.Components 1.2 | ||
1107 | 447 | |||
1108 | 448 | When the \l sourceFillMode is set to \c UbuntuShape.Pad or \c UbuntuShape.PreserveAspectFit or | ||
1109 | 449 | when the \l sourceScale and/or \l sourceTranslation properties are changed, the \l source | ||
1110 | 450 | texture might not cover the entire UbuntuShape area. This property defines how the source | ||
1111 | 451 | texture wraps outside of its content area. The default value is \c UbuntuShape.Transparent. | ||
1112 | 452 | |||
1113 | 453 | Ensure \c UbuntuShape.Repeat is used only when necessary (in case of an \c Image or \c | ||
1114 | 454 | AnimatedImage source) as it requires the underlying texture to be extracted from its atlas. That | ||
1115 | 455 | slows down the rendering speed since it prevents the QtQuick renderer to batch the UbuntuShape | ||
1116 | 456 | with others. | ||
1117 | 457 | |||
1118 | 458 | \note Some OpenGL ES 2 implementations do not support \c UbuntuShape.Repeat with | ||
1119 | 459 | non-power-of-two sized source textures. | ||
1120 | 460 | \note Setting this disables support for the deprecated \l image property. | ||
1121 | 461 | |||
1122 | 462 | \list | ||
1123 | 463 | \li \b UbuntuShape.Transparent - the source is clamped to transparent | ||
1124 | 464 | \li \b UbuntuShape.Repeat - the source is repeated indefinitely (not supported yet) | ||
1125 | 465 | \endlist | ||
1126 | 466 | */ | ||
1127 | 467 | void UCUbuntuShape::setSourceHorizontalWrapMode(UCUbuntuShape::WrapMode sourceHorizontalWrapMode) | ||
1128 | 468 | { | ||
1129 | 469 | dropImageSupport(); | ||
1130 | 470 | |||
1131 | 471 | if (m_sourceHorizontalWrapMode != sourceHorizontalWrapMode) { | ||
1132 | 472 | m_sourceHorizontalWrapMode = sourceHorizontalWrapMode; | ||
1133 | 473 | update(); | ||
1134 | 474 | Q_EMIT sourceHorizontalWrapModeChanged(); | ||
1135 | 475 | } | ||
1136 | 476 | } | ||
1137 | 477 | |||
1138 | 478 | void UCUbuntuShape::setSourceVerticalWrapMode(UCUbuntuShape::WrapMode sourceVerticalWrapMode) | ||
1139 | 479 | { | ||
1140 | 480 | dropImageSupport(); | ||
1141 | 481 | |||
1142 | 482 | if (m_sourceVerticalWrapMode != sourceVerticalWrapMode) { | ||
1143 | 483 | m_sourceVerticalWrapMode = sourceVerticalWrapMode; | ||
1144 | 484 | update(); | ||
1145 | 485 | Q_EMIT sourceVerticalWrapModeChanged(); | ||
1146 | 486 | } | ||
1147 | 487 | } | ||
1148 | 488 | |||
1149 | 489 | /*! \qmlproperty enumeration UbuntuShape::sourceHorizontalAlignment | ||
1150 | 490 | \since Ubuntu.Components 1.2 | ||
1151 | 491 | |||
1152 | 492 | This property defines how the \l source texture is horizontally aligned inside the UbuntuShape | ||
1153 | 493 | area. The default value is \c UbuntuShape.AlignLeft. | ||
1154 | 494 | |||
1155 | 495 | \note Setting this disables support for the deprecated \l image property. | ||
1156 | 496 | |||
1157 | 497 | \list | ||
1158 | 498 | \li \b UbuntuShape.AlignLeft - the source is aligned to the left | ||
1159 | 499 | \li \b UbuntuShape.AlignHCenter - the source is aligned to the horizontal center | ||
1160 | 500 | \li \b UbuntuShape.AlignRight - the source is aligned to the right | ||
1161 | 501 | \endlist | ||
1162 | 502 | */ | ||
1163 | 503 | void UCUbuntuShape::setSourceHorizontalAlignment( | ||
1164 | 504 | UCUbuntuShape::HAlignment sourceHorizontalAlignment) | ||
1165 | 505 | { | ||
1166 | 506 | dropImageSupport(); | ||
1167 | 507 | |||
1168 | 508 | if (m_sourceHorizontalAlignment != sourceHorizontalAlignment) { | ||
1169 | 509 | m_sourceHorizontalAlignment = sourceHorizontalAlignment; | ||
1170 | 510 | m_flags |= DirtySourceTransform; | ||
1171 | 511 | update(); | ||
1172 | 512 | Q_EMIT sourceHorizontalAlignmentChanged(); | ||
1173 | 513 | } | ||
1174 | 514 | } | ||
1175 | 515 | |||
1176 | 516 | /*! \qmlproperty enumeration UbuntuShape::sourceVerticalAlignment | ||
1177 | 517 | \since Ubuntu.Components 1.2 | ||
1178 | 518 | |||
1179 | 519 | This property defines how the \l source texture is vertically aligned inside the UbuntuShape | ||
1180 | 520 | area. The default value is \c UbuntuShape.AlignTop. | ||
1181 | 521 | |||
1182 | 522 | \note Setting this disables support for the deprecated \l image property. | ||
1183 | 523 | |||
1184 | 524 | \list | ||
1185 | 525 | \li \b UbuntuShape.AlignTop - the source is aligned to the top | ||
1186 | 526 | \li \b UbuntuShape.AlignVCenter - the source is aligned to the vertical center | ||
1187 | 527 | \li \b UbuntuShape.AlignBottom - the source is aligned to the bottom | ||
1188 | 528 | \endlist | ||
1189 | 529 | */ | ||
1190 | 530 | void UCUbuntuShape::setSourceVerticalAlignment(UCUbuntuShape::VAlignment sourceVerticalAlignment) | ||
1191 | 531 | { | ||
1192 | 532 | dropImageSupport(); | ||
1193 | 533 | |||
1194 | 534 | if (m_sourceVerticalAlignment != sourceVerticalAlignment) { | ||
1195 | 535 | m_sourceVerticalAlignment = sourceVerticalAlignment; | ||
1196 | 536 | m_flags |= DirtySourceTransform; | ||
1197 | 537 | update(); | ||
1198 | 538 | Q_EMIT sourceVerticalAlignmentChanged(); | ||
1199 | 539 | } | ||
1200 | 540 | } | ||
1201 | 541 | |||
1202 | 542 | /*! \qmlproperty vector2d UbuntuShape::sourceTranslation | ||
1203 | 543 | \since Ubuntu.Components 1.2 | ||
1204 | 544 | |||
1205 | 545 | This property defines the two-component vector in normalized item coordinates used to translate | ||
1206 | 546 | the \l source texture. The default value is \c {Qt.vector2d(0.0,0.0)}. | ||
1207 | 547 | |||
1208 | 548 | That can be used to put the \l source texture at a precise position, to create infinite | ||
1209 | 549 | scrolling animations (using the \c UbuntuShape.Repeat wrap mode), etc. | ||
1210 | 550 | |||
1211 | 551 | \note Setting this disables support for the deprecated \l image property. | ||
1212 | 552 | */ | ||
1213 | 553 | void UCUbuntuShape::setSourceTranslation(const QVector2D& sourceTranslation) | ||
1214 | 554 | { | ||
1215 | 555 | dropImageSupport(); | ||
1216 | 556 | |||
1217 | 557 | if (m_sourceTranslation != sourceTranslation) { | ||
1218 | 558 | m_sourceTranslation = sourceTranslation; | ||
1219 | 559 | m_flags |= DirtySourceTransform; | ||
1220 | 560 | update(); | ||
1221 | 561 | Q_EMIT sourceTranslationChanged(); | ||
1222 | 562 | } | ||
1223 | 563 | } | ||
1224 | 564 | |||
1225 | 565 | /*! \qmlproperty vector2d UbuntuShape::sourceScale | ||
1226 | 566 | \since Ubuntu.Components 1.2 | ||
1227 | 567 | |||
1228 | 568 | This property defines the two-component vector used to scale the \l source texture. The texture | ||
1229 | 569 | is scaled at the alignment point defined by \l sourceHorizontalAlignment and \l | ||
1230 | 570 | sourceVerticalAlignment. The default value is \c {Qt.vector2d(1.0,1.0)}. | ||
1231 | 571 | |||
1232 | 572 | That can be used to change the size of the \l source texture, to flip it horizontally and/or | ||
1233 | 573 | vertically, to achieve pulsing animations, etc. | ||
1234 | 574 | |||
1235 | 575 | Here is a code sample showing how to apply an horizontal flip: | ||
1236 | 576 | |||
1237 | 577 | \qml | ||
1238 | 578 | UbuntuShape { | ||
1239 | 579 | source: Image { source: "ubuntu.png" } | ||
1240 | 580 | sourceScale: Qt.vector2d(-1.0, 1.0) | ||
1241 | 581 | } | ||
1242 | 582 | \endqml | ||
1243 | 583 | |||
1244 | 584 | \note Setting this disables support for the deprecated \l image property. | ||
1245 | 585 | */ | ||
1246 | 586 | void UCUbuntuShape::setSourceScale(const QVector2D& sourceScale) | ||
1247 | 587 | { | ||
1248 | 588 | dropImageSupport(); | ||
1249 | 589 | |||
1250 | 590 | if (m_sourceScale != sourceScale) { | ||
1251 | 591 | m_sourceScale = sourceScale; | ||
1252 | 592 | m_flags |= DirtySourceTransform; | ||
1253 | 593 | update(); | ||
1254 | 594 | Q_EMIT sourceScaleChanged(); | ||
1255 | 595 | } | ||
1256 | 596 | } | ||
1257 | 597 | |||
1258 | 598 | // Deprecation layer. | ||
1259 | 599 | void UCUbuntuShape::dropColorSupport() | ||
1260 | 600 | { | ||
1261 | 601 | if (!(m_flags & BackgroundApiSet)) { | ||
1262 | 602 | m_flags |= BackgroundApiSet; | ||
1263 | 603 | if (m_backgroundColor) { | ||
1264 | 604 | m_backgroundColor = qRgba(0, 0, 0, 0); | ||
1265 | 605 | Q_EMIT colorChanged(); | ||
1266 | 606 | } | ||
1267 | 607 | if (m_secondaryBackgroundColor) { | ||
1268 | 608 | m_secondaryBackgroundColor = qRgba(0, 0, 0, 0); | ||
1269 | 609 | Q_EMIT gradientColorChanged(); | ||
1270 | 610 | } | ||
1271 | 611 | } | ||
1272 | 612 | } | ||
1273 | 613 | |||
1274 | 614 | /*! \qmlproperty color UbuntuShape::backgroundColor | ||
1275 | 615 | \since Ubuntu.Components 1.2 | ||
1276 | 616 | |||
1277 | 617 | This property defines the background color. The default value is transparent black. | ||
1278 | 618 | |||
1279 | 619 | \note Setting this disables support for the deprecated \l color and \l gradientColor properties. | ||
1280 | 620 | */ | ||
1281 | 621 | void UCUbuntuShape::setBackgroundColor(const QColor& backgroundColor) | ||
1282 | 622 | { | ||
1283 | 623 | dropColorSupport(); | ||
1284 | 624 | |||
1285 | 625 | const QRgb backgroundColorRgb = qRgba( | ||
1286 | 626 | backgroundColor.red(), backgroundColor.green(), backgroundColor.blue(), | ||
1287 | 627 | backgroundColor.alpha()); | ||
1288 | 628 | if (m_backgroundColor != backgroundColorRgb) { | ||
1289 | 629 | m_backgroundColor = backgroundColorRgb; | ||
1290 | 630 | update(); | ||
1291 | 631 | Q_EMIT backgroundColorChanged(); | ||
1292 | 632 | } | ||
1293 | 633 | } | ||
1294 | 634 | |||
1295 | 635 | /*! \qmlproperty color UbuntuShape::secondaryBackgroundColor | ||
1296 | 636 | \since Ubuntu.Components 1.2 | ||
1297 | 637 | |||
1298 | 638 | This property defines the secondary background color. It is used when \l backgroundMode is set | ||
1299 | 639 | to \c UbuntuShape.VerticalGradient. The default value is transparent black. | ||
1300 | 640 | |||
1301 | 641 | \note Setting this disables support for the deprecated \l color and \l gradientColor properties. | ||
1302 | 642 | */ | ||
1303 | 643 | void UCUbuntuShape::setSecondaryBackgroundColor(const QColor& secondaryBackgroundColor) | ||
1304 | 644 | { | ||
1305 | 645 | dropColorSupport(); | ||
1306 | 646 | |||
1307 | 647 | const QRgb secondaryBackgroundColorRgb = qRgba( | ||
1308 | 648 | secondaryBackgroundColor.red(), secondaryBackgroundColor.green(), | ||
1309 | 649 | secondaryBackgroundColor.blue(), secondaryBackgroundColor.alpha()); | ||
1310 | 650 | if (m_secondaryBackgroundColor != secondaryBackgroundColorRgb) { | ||
1311 | 651 | m_secondaryBackgroundColor = secondaryBackgroundColorRgb; | ||
1312 | 652 | update(); | ||
1313 | 653 | Q_EMIT secondaryBackgroundColorChanged(); | ||
1314 | 654 | } | ||
1315 | 655 | } | ||
1316 | 656 | |||
1317 | 657 | /*! \qmlproperty enumeration UbuntuShape::backgroundMode | ||
1318 | 658 | \since Ubuntu.Components 1.2 | ||
1319 | 659 | |||
1320 | 660 | This property defines the background rendering mode. The default value is \c | ||
1321 | 661 | UbuntuShape.SolidColor. | ||
1322 | 662 | |||
1323 | 663 | \note Setting this disables support for the deprecated \l color and \l gradientColor properties. | ||
1324 | 664 | |||
1325 | 665 | \list | ||
1326 | 666 | \li \b UbuntuShape.SolidColor - the color is \l backgroundColor | ||
1327 | 667 | \li \b UbuntuShape.VerticalGradient - the color is a vertical gradient from \l backgroundColor | ||
1328 | 668 | to \l secondaryBackgroundColor. | ||
1329 | 669 | \endlist | ||
1330 | 670 | */ | ||
1331 | 671 | void UCUbuntuShape::setBackgroundMode(BackgroundMode backgroundMode) | ||
1332 | 672 | { | ||
1333 | 673 | dropColorSupport(); | ||
1334 | 674 | |||
1335 | 675 | if (m_backgroundMode != backgroundMode) { | ||
1336 | 676 | m_backgroundMode = backgroundMode; | ||
1337 | 677 | update(); | ||
1338 | 678 | Q_EMIT backgroundModeChanged(); | ||
1339 | 679 | } | ||
1340 | 680 | } | ||
1341 | 681 | |||
1342 | 682 | /*! \qmlproperty color UbuntuShape::color | ||
1343 | 683 | \deprecated | ||
1344 | 684 | |||
1345 | 685 | This property defines the color used to fill the UbuntuShape when there is no \l image set. If | ||
1346 | 686 | \l gradientColor is set, this property defines the top color of the gradient. The default value | ||
1347 | 687 | is transparent black. | ||
1348 | 688 | |||
1349 | 689 | \note Use \l backgroundColor, \l secondaryBackgroundColor and \l backgroundMode instead. | ||
1350 | 690 | */ | ||
1351 | 691 | void UCUbuntuShape::setColor(const QColor& color) | ||
1352 | 692 | { | ||
1353 | 693 | if (!(m_flags & BackgroundApiSet)) { | ||
1354 | 694 | const QRgb colorRgb = qRgba(color.red(), color.green(), color.blue(), color.alpha()); | ||
1355 | 695 | if (m_backgroundColor != colorRgb) { | ||
1356 | 696 | m_backgroundColor = colorRgb; | ||
1357 | 697 | // gradientColor has the same value as color unless it was explicitly set. | ||
1358 | 698 | if (!(m_flags & GradientColorSet)) { | ||
1359 | 699 | m_secondaryBackgroundColor = colorRgb; | ||
1360 | 700 | Q_EMIT gradientColorChanged(); | ||
1361 | 701 | } | ||
1362 | 702 | update(); | ||
1363 | 703 | Q_EMIT colorChanged(); | ||
1364 | 704 | } | ||
1365 | 705 | } | ||
1366 | 706 | } | ||
1367 | 707 | |||
1368 | 708 | /*! \qmlproperty color UbuntuShape::gradientColor | ||
1369 | 709 | \deprecated | ||
1370 | 710 | |||
1371 | 711 | This property defines the bottom color used for the vertical gradient filling the UbuntuShape | ||
1372 | 712 | when there is no \l image set. As long as this property is not set, a single color (defined | ||
1373 | 713 | by \l color) is used to fill the UbuntuShape. | ||
1374 | 714 | |||
1375 | 715 | \note Use \l backgroundColor, \l secondaryBackgroundColor and \l backgroundMode instead. | ||
1376 | 716 | */ | ||
1377 | 717 | void UCUbuntuShape::setGradientColor(const QColor& gradientColor) | ||
1378 | 718 | { | ||
1379 | 719 | if (!(m_flags & BackgroundApiSet)) { | ||
1380 | 720 | m_flags |= GradientColorSet; | ||
1381 | 721 | const QRgb gradientColorRgb = qRgba( | ||
1382 | 722 | gradientColor.red(), gradientColor.green(), gradientColor.blue(), | ||
1383 | 723 | gradientColor.alpha()); | ||
1384 | 724 | if (m_secondaryBackgroundColor != gradientColorRgb) { | ||
1385 | 725 | m_secondaryBackgroundColor = gradientColorRgb; | ||
1386 | 726 | update(); | ||
1387 | 727 | Q_EMIT gradientColorChanged(); | ||
1388 | 728 | } | ||
1389 | 729 | } | ||
1390 | 730 | } | ||
1391 | 731 | |||
1392 | 732 | /*! \qmlproperty Image UbuntuShape::image | ||
1393 | 733 | \deprecated | ||
1394 | 734 | |||
1395 | 735 | This property holds the \c Image or \c ShaderEffectSource rendered in the UbuntuShape. In case | ||
1396 | 736 | of an \c Image, it watches for fillMode (\c Image.Stretch and\c Image.PreserveAspectCrop), \c | ||
1397 | 737 | horizontalAlignment and \c verticalAlignment property changes. The default value is \c null. | ||
1398 | 738 | |||
1399 | 739 | \note Use \l source instead. | ||
1400 | 740 | */ | ||
1401 | 741 | void UCUbuntuShape::setImage(const QVariant& image) | ||
1402 | 742 | { | ||
1403 | 743 | if (!(m_flags & SourceApiSet)) { | ||
1404 | 744 | QQuickItem* newImage = qobject_cast<QQuickItem*>(qvariant_cast<QObject*>(image)); | ||
1405 | 745 | if (m_source != newImage) { | ||
1406 | 746 | if (newImage) { | ||
1407 | 747 | // Watch for property changes. | ||
1408 | 748 | updateFromImageProperties(newImage); | ||
1409 | 749 | connectToImageProperties(newImage); | ||
1410 | 750 | if (!newImage->parentItem()) { | ||
1411 | 751 | // Inlined images need a parent and must not be visible. | ||
1412 | 752 | newImage->setParentItem(this); | ||
1413 | 753 | newImage->setVisible(false); | ||
1414 | 754 | } | ||
1415 | 755 | m_flags |= DirtySourceTransform; | ||
1416 | 756 | } | ||
1417 | 757 | QObject::disconnect(m_source); | ||
1418 | 758 | update(); | ||
1419 | 759 | m_source = newImage; | ||
1420 | 760 | Q_EMIT imageChanged(); | ||
1421 | 761 | } | ||
1422 | 762 | } | ||
1423 | 763 | } | ||
1424 | 764 | |||
1425 | 765 | // Deprecation layer. Even though "stretched" is exposed as a QML property, it's only been used when | ||
1426 | 766 | // there was a QML UbuntuShape proxy. This is why we don't provide doc for it. We'll still have to | ||
1427 | 767 | // maintain it for a while for compatibility reasons. | ||
1428 | 768 | void UCUbuntuShape::setStretched(bool stretched) | ||
1429 | 769 | { | ||
1430 | 770 | if (!(m_flags & SourceApiSet)) { | ||
1431 | 771 | if (!!(m_flags & Stretched) != stretched) { | ||
1432 | 772 | if (stretched) { | ||
1433 | 773 | m_flags |= Stretched; | ||
1434 | 774 | } else { | ||
1435 | 775 | m_flags &= ~Stretched; | ||
1436 | 776 | } | ||
1437 | 777 | m_flags |= DirtySourceTransform; | ||
1438 | 778 | update(); | ||
1439 | 779 | Q_EMIT stretchedChanged(); | ||
1440 | 780 | } | ||
1441 | 781 | } | ||
1442 | 782 | } | ||
1443 | 783 | |||
1444 | 784 | // Deprecation layer. Same comment as setStretched(). | ||
1445 | 785 | void UCUbuntuShape::setHorizontalAlignment(HAlignment horizontalAlignment) | ||
1446 | 786 | { | ||
1447 | 787 | if (!(m_flags & SourceApiSet)) { | ||
1448 | 788 | if (m_imageHorizontalAlignment != horizontalAlignment) { | ||
1449 | 789 | m_imageHorizontalAlignment = horizontalAlignment; | ||
1450 | 790 | m_flags |= DirtySourceTransform; | ||
1451 | 791 | update(); | ||
1452 | 792 | Q_EMIT horizontalAlignmentChanged(); | ||
1453 | 793 | } | ||
1454 | 794 | } | ||
1455 | 795 | } | ||
1456 | 796 | |||
1457 | 797 | // Deprecation layer. Same comment as setStretched(). | ||
1458 | 798 | void UCUbuntuShape::setVerticalAlignment(VAlignment verticalAlignment) | ||
1459 | 799 | { | ||
1460 | 800 | if (!(m_flags & SourceApiSet)) { | ||
1461 | 801 | if (m_imageVerticalAlignment != verticalAlignment) { | ||
1462 | 802 | m_imageVerticalAlignment = verticalAlignment; | ||
1463 | 803 | m_flags |= DirtySourceTransform; | ||
1464 | 804 | update(); | ||
1465 | 805 | Q_EMIT verticalAlignmentChanged(); | ||
1466 | 806 | } | ||
1467 | 807 | } | ||
1468 | 808 | } | ||
1469 | 809 | |||
1470 | 810 | // Deprecation layer. | ||
1471 | 811 | void UCUbuntuShape::updateFromImageProperties(QQuickItem* image) | ||
1472 | 306 | { | 812 | { |
1473 | 307 | int alignment; | 813 | int alignment; |
1474 | 308 | 814 | ||
1476 | 309 | // ShapeItem::stretched depends on image::fillMode | 815 | // UbuntuShape::stretched depends on Image::fillMode. |
1477 | 310 | QQuickImage::FillMode fillMode = (QQuickImage::FillMode)image->property("fillMode").toInt(); | 816 | QQuickImage::FillMode fillMode = (QQuickImage::FillMode)image->property("fillMode").toInt(); |
1478 | 311 | if (fillMode == QQuickImage::PreserveAspectCrop) { | 817 | if (fillMode == QQuickImage::PreserveAspectCrop) { |
1479 | 312 | setStretched(false); | 818 | setStretched(false); |
1480 | @@ -314,640 +820,516 @@ | |||
1481 | 314 | setStretched(true); | 820 | setStretched(true); |
1482 | 315 | } | 821 | } |
1483 | 316 | 822 | ||
1485 | 317 | // ShapeItem::horizontalAlignment depends on image::horizontalAlignment | 823 | // UbuntuShape::horizontalAlignment depends on Image::horizontalAlignment. |
1486 | 318 | int imageHorizontalAlignment = image->property("horizontalAlignment").toInt(); | 824 | int imageHorizontalAlignment = image->property("horizontalAlignment").toInt(); |
1487 | 319 | if (imageHorizontalAlignment == Qt::AlignLeft) { | 825 | if (imageHorizontalAlignment == Qt::AlignLeft) { |
1489 | 320 | alignment = ShapeItem::AlignLeft; | 826 | alignment = AlignLeft; |
1490 | 321 | } else if (imageHorizontalAlignment == Qt::AlignRight) { | 827 | } else if (imageHorizontalAlignment == Qt::AlignRight) { |
1492 | 322 | alignment = ShapeItem::AlignRight; | 828 | alignment = AlignRight; |
1493 | 323 | } else { | 829 | } else { |
1495 | 324 | alignment = ShapeItem::AlignHCenter; | 830 | alignment = AlignHCenter; |
1496 | 325 | } | 831 | } |
1498 | 326 | setHorizontalAlignment(static_cast<ShapeItem::HAlignment>(alignment)); | 832 | setHorizontalAlignment(static_cast<HAlignment>(alignment)); |
1499 | 327 | 833 | ||
1501 | 328 | // ShapeItem::verticalAlignment depends on image::verticalAlignment | 834 | // UbuntuShape::verticalAlignment depends on Image::verticalAlignment. |
1502 | 329 | int imageVerticalAlignment = image->property("verticalAlignment").toInt(); | 835 | int imageVerticalAlignment = image->property("verticalAlignment").toInt(); |
1503 | 330 | if (imageVerticalAlignment == Qt::AlignTop) { | 836 | if (imageVerticalAlignment == Qt::AlignTop) { |
1505 | 331 | alignment = ShapeItem::AlignTop; | 837 | alignment = AlignTop; |
1506 | 332 | } else if (imageVerticalAlignment == Qt::AlignBottom) { | 838 | } else if (imageVerticalAlignment == Qt::AlignBottom) { |
1508 | 333 | alignment = ShapeItem::AlignBottom; | 839 | alignment = AlignBottom; |
1509 | 334 | } else { | 840 | } else { |
1511 | 335 | alignment = ShapeItem::AlignVCenter; | 841 | alignment = AlignVCenter; |
1512 | 336 | } | 842 | } |
1514 | 337 | setVerticalAlignment(static_cast<ShapeItem::VAlignment>(alignment)); | 843 | setVerticalAlignment(static_cast<UCUbuntuShape::VAlignment>(alignment)); |
1515 | 338 | } | 844 | } |
1516 | 339 | 845 | ||
1519 | 340 | void ShapeItem::connectToPropertyChange(QObject* sender, const char* property, | 846 | // Deprecation layer. |
1520 | 341 | QObject* receiver, const char* slot) | 847 | void UCUbuntuShape::connectToPropertyChange( |
1521 | 848 | QObject* sender, const char* property, QObject* receiver, const char* slot) | ||
1522 | 342 | { | 849 | { |
1523 | 343 | int propertyIndex = sender->metaObject()->indexOfProperty(property); | 850 | int propertyIndex = sender->metaObject()->indexOfProperty(property); |
1524 | 344 | if (propertyIndex != -1) { | 851 | if (propertyIndex != -1) { |
1525 | 345 | QMetaMethod changeSignal = sender->metaObject()->property(propertyIndex).notifySignal(); | 852 | QMetaMethod changeSignal = sender->metaObject()->property(propertyIndex).notifySignal(); |
1526 | 346 | |||
1527 | 347 | int slotIndex = receiver->metaObject()->indexOfSlot(slot); | 853 | int slotIndex = receiver->metaObject()->indexOfSlot(slot); |
1528 | 348 | QMetaMethod updateSlot = receiver->metaObject()->method(slotIndex); | 854 | QMetaMethod updateSlot = receiver->metaObject()->method(slotIndex); |
1529 | 349 | |||
1530 | 350 | QObject::connect(sender, changeSignal, receiver, updateSlot); | 855 | QObject::connect(sender, changeSignal, receiver, updateSlot); |
1531 | 351 | } | 856 | } |
1532 | 352 | } | 857 | } |
1533 | 353 | 858 | ||
1535 | 354 | void ShapeItem::connectToImageProperties(QQuickItem* image) | 859 | // Deprecation layer. |
1536 | 860 | void UCUbuntuShape::connectToImageProperties(QQuickItem* image) | ||
1537 | 355 | { | 861 | { |
1541 | 356 | connectToPropertyChange(image, "fillMode", this, "onImagePropertiesChanged()"); | 862 | connectToPropertyChange(image, "fillMode", this, "_q_imagePropertiesChanged()"); |
1542 | 357 | connectToPropertyChange(image, "horizontalAlignment", this, "onImagePropertiesChanged()"); | 863 | connectToPropertyChange(image, "horizontalAlignment", this, "_q_imagePropertiesChanged()"); |
1543 | 358 | connectToPropertyChange(image, "verticalAlignment", this, "onImagePropertiesChanged()"); | 864 | connectToPropertyChange(image, "verticalAlignment", this, "_q_imagePropertiesChanged()"); |
1544 | 359 | } | 865 | } |
1545 | 360 | 866 | ||
1547 | 361 | void ShapeItem::onImagePropertiesChanged() | 867 | // Deprecation layer. |
1548 | 868 | void UCUbuntuShape::_q_imagePropertiesChanged() | ||
1549 | 362 | { | 869 | { |
1550 | 363 | QQuickItem* image = qobject_cast<QQuickItem*>(sender()); | 870 | QQuickItem* image = qobject_cast<QQuickItem*>(sender()); |
1551 | 364 | updateFromImageProperties(image); | 871 | updateFromImageProperties(image); |
1552 | 365 | } | 872 | } |
1553 | 366 | 873 | ||
1597 | 367 | void ShapeItem::setStretched(bool stretched) | 874 | void UCUbuntuShape::_q_openglContextDestroyed() |
1555 | 368 | { | ||
1556 | 369 | if (stretched_ != stretched) { | ||
1557 | 370 | stretched_ = stretched; | ||
1558 | 371 | update(); | ||
1559 | 372 | Q_EMIT stretchedChanged(); | ||
1560 | 373 | } | ||
1561 | 374 | } | ||
1562 | 375 | |||
1563 | 376 | void ShapeItem::setHorizontalAlignment(HAlignment hAlignment) | ||
1564 | 377 | { | ||
1565 | 378 | if (hAlignment_ != hAlignment) { | ||
1566 | 379 | hAlignment_ = hAlignment; | ||
1567 | 380 | update(); | ||
1568 | 381 | Q_EMIT horizontalAlignmentChanged(); | ||
1569 | 382 | } | ||
1570 | 383 | } | ||
1571 | 384 | |||
1572 | 385 | void ShapeItem::setVerticalAlignment(VAlignment vAlignment) | ||
1573 | 386 | { | ||
1574 | 387 | if (vAlignment_ != vAlignment) { | ||
1575 | 388 | vAlignment_ = vAlignment; | ||
1576 | 389 | update(); | ||
1577 | 390 | Q_EMIT verticalAlignmentChanged(); | ||
1578 | 391 | } | ||
1579 | 392 | } | ||
1580 | 393 | |||
1581 | 394 | void ShapeItem::gridUnitChanged() | ||
1582 | 395 | { | ||
1583 | 396 | gridUnit_ = UCUnits::instance().gridUnit(); | ||
1584 | 397 | setImplicitWidth(8 * gridUnit_); | ||
1585 | 398 | setImplicitHeight(8 * gridUnit_); | ||
1586 | 399 | update(); | ||
1587 | 400 | } | ||
1588 | 401 | |||
1589 | 402 | void ShapeItem::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) | ||
1590 | 403 | { | ||
1591 | 404 | geometry_ = newGeometry; | ||
1592 | 405 | QQuickItem::geometryChanged(newGeometry, oldGeometry); | ||
1593 | 406 | update(); | ||
1594 | 407 | } | ||
1595 | 408 | |||
1596 | 409 | void ShapeItem::onOpenglContextDestroyed() | ||
1598 | 410 | { | 875 | { |
1599 | 411 | QOpenGLContext* context = qobject_cast<QOpenGLContext*>(sender()); | 876 | QOpenGLContext* context = qobject_cast<QOpenGLContext*>(sender()); |
1609 | 412 | if (Q_UNLIKELY(!context)) return; | 877 | if (context) { |
1610 | 413 | 878 | QHash<QOpenGLContext*, ShapeTextures>::iterator it = shapeTexturesHash.find(context); | |
1611 | 414 | QHash<QOpenGLContext*, TextureHandles>::iterator it = | 879 | if (it != shapeTexturesHash.end()) { |
1612 | 415 | textures_.find(context); | 880 | ShapeTextures &shapeTextures = it.value(); |
1613 | 416 | if (it != textures_.end()) { | 881 | delete shapeTextures.high; |
1614 | 417 | TextureHandles &textureHandles = it.value(); | 882 | delete shapeTextures.low; |
1615 | 418 | delete textureHandles.high; | 883 | shapeTexturesHash.erase(it); |
1616 | 419 | delete textureHandles.low; | 884 | } |
1608 | 420 | textures_.erase(it); | ||
1617 | 421 | } | 885 | } |
1618 | 422 | } | 886 | } |
1619 | 423 | 887 | ||
1621 | 424 | void ShapeItem::providerDestroyed(QObject* object) | 888 | void UCUbuntuShape::_q_gridUnitChanged() |
1622 | 889 | { | ||
1623 | 890 | const float gridUnit = UCUnits::instance().gridUnit(); | ||
1624 | 891 | setImplicitWidth(implicitGridUnitWidth * gridUnit); | ||
1625 | 892 | setImplicitHeight(implicitGridUnitHeight * gridUnit); | ||
1626 | 893 | update(); | ||
1627 | 894 | } | ||
1628 | 895 | |||
1629 | 896 | void UCUbuntuShape::_q_providerDestroyed(QObject* object) | ||
1630 | 425 | { | 897 | { |
1631 | 426 | Q_UNUSED(object); | 898 | Q_UNUSED(object); |
1636 | 427 | provider_ = NULL; | 899 | m_sourceTextureProvider = NULL; |
1637 | 428 | } | 900 | } |
1638 | 429 | 901 | ||
1639 | 430 | QSGNode* ShapeItem::updatePaintNode(QSGNode* old_node, UpdatePaintNodeData* data) | 902 | void UCUbuntuShape::_q_textureChanged() |
1640 | 903 | { | ||
1641 | 904 | m_flags |= DirtySourceTransform; | ||
1642 | 905 | update(); | ||
1643 | 906 | } | ||
1644 | 907 | |||
1645 | 908 | void UCUbuntuShape::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) | ||
1646 | 909 | { | ||
1647 | 910 | QQuickItem::geometryChanged(newGeometry, oldGeometry); | ||
1648 | 911 | m_flags |= DirtySourceTransform; | ||
1649 | 912 | } | ||
1650 | 913 | |||
1651 | 914 | // Gets the nearest boundary to coord in the texel grid of the given size. | ||
1652 | 915 | static Q_DECL_CONSTEXPR float roundTextureCoord(float coord, float size) | ||
1653 | 916 | { | ||
1654 | 917 | return roundf(coord * size) / size; | ||
1655 | 918 | } | ||
1656 | 919 | |||
1657 | 920 | void UCUbuntuShape::updateSourceTransform( | ||
1658 | 921 | float itemWidth, float itemHeight, FillMode fillMode, HAlignment horizontalAlignment, | ||
1659 | 922 | VAlignment verticalAlignment, const QSize& textureSize) | ||
1660 | 923 | { | ||
1661 | 924 | float fillSx, fillSy; | ||
1662 | 925 | if (fillMode == PreserveAspectFit) { | ||
1663 | 926 | const float textureRatio = static_cast<float>(textureSize.width()) / textureSize.height(); | ||
1664 | 927 | const float itemRatio = itemWidth / itemHeight; | ||
1665 | 928 | fillSx = (textureRatio < itemRatio) ? (itemRatio / textureRatio) : 1.0f; | ||
1666 | 929 | fillSy = (textureRatio < itemRatio) ? 1.0f : (textureRatio / itemRatio); | ||
1667 | 930 | } else if (fillMode == PreserveAspectCrop) { | ||
1668 | 931 | const float textureRatio = static_cast<float>(textureSize.width()) / textureSize.height(); | ||
1669 | 932 | const float itemRatio = itemWidth / itemHeight; | ||
1670 | 933 | fillSx = (textureRatio < itemRatio) ? 1.0f : (itemRatio / textureRatio); | ||
1671 | 934 | fillSy = (textureRatio < itemRatio) ? (textureRatio / itemRatio) : 1.0f; | ||
1672 | 935 | } else if (fillMode == Pad) { | ||
1673 | 936 | fillSx = itemWidth / textureSize.width(); | ||
1674 | 937 | fillSy = itemHeight / textureSize.height(); | ||
1675 | 938 | } else { | ||
1676 | 939 | fillSx = 1.0f; | ||
1677 | 940 | fillSy = 1.0f; | ||
1678 | 941 | } | ||
1679 | 942 | |||
1680 | 943 | const float sourceSxInv = 1.0f / m_sourceScale.x(); | ||
1681 | 944 | const float sourceSyInv = 1.0f / m_sourceScale.y(); | ||
1682 | 945 | // Multiplied by fillS* so that the translation unit is in normalized item coordinates. | ||
1683 | 946 | const float sourceTx = (m_sourceTranslation.x() * sourceSxInv) * fillSx; | ||
1684 | 947 | const float sourceTy = (m_sourceTranslation.y() * sourceSyInv) * fillSy; | ||
1685 | 948 | const float sx = fillSx * sourceSxInv; | ||
1686 | 949 | const float sy = fillSy * sourceSyInv; | ||
1687 | 950 | const float factorTable[3] = { 0.0f, 0.5f, 1.0f }; | ||
1688 | 951 | const float hFactor = factorTable[static_cast<int>(horizontalAlignment)]; | ||
1689 | 952 | const float vFactor = factorTable[static_cast<int>(verticalAlignment)]; | ||
1690 | 953 | const float tx = hFactor * (1.0f - sx) - sourceTx; | ||
1691 | 954 | const float ty = vFactor * (1.0f - sy) - sourceTy; | ||
1692 | 955 | |||
1693 | 956 | // Rounding is important to get padded texture perfectly mapped to the pixel grid. It shouldn't | ||
1694 | 957 | // be necessary when there's a scaling but we make it consistent by applying the scale factors | ||
1695 | 958 | // to the texture size, so that there's no ugly position jumps with big scaling values. | ||
1696 | 959 | m_sourceTransform = QVector4D( | ||
1697 | 960 | sx, sy, roundTextureCoord(tx, textureSize.width() * m_sourceScale.x()), | ||
1698 | 961 | roundTextureCoord(ty, textureSize.height() * m_sourceScale.y())); | ||
1699 | 962 | } | ||
1700 | 963 | |||
1701 | 964 | // Pack a premultiplied 32-bit ABGR integer. | ||
1702 | 965 | static quint32 packColor(quint32 a, quint32 b, quint32 g, quint32 r) | ||
1703 | 966 | { | ||
1704 | 967 | const quint32 pb = ((b * a) + 0xff) >> 8; | ||
1705 | 968 | const quint32 pg = ((g * a) + 0xff) >> 8; | ||
1706 | 969 | const quint32 pr = ((r * a) + 0xff) >> 8; | ||
1707 | 970 | return (a << 24) | ((pb & 0xff) << 16) | ((pg & 0xff) << 8) | (pr & 0xff); | ||
1708 | 971 | } | ||
1709 | 972 | |||
1710 | 973 | // Lerp c1 and c2 with t in the range [0, 255]. Return value is a premultiplied 32-bit ABGR integer. | ||
1711 | 974 | static quint32 lerpColor(quint32 t, QRgb c1, QRgb c2) | ||
1712 | 975 | { | ||
1713 | 976 | const quint32 a = qAlpha(c1) + ((t * (qAlpha(c2) - qAlpha(c1)) + 0xff) >> 8); | ||
1714 | 977 | const quint32 b = qBlue(c1) + ((t * (qBlue(c2) - qBlue(c1)) + 0xff) >> 8); | ||
1715 | 978 | const quint32 g = qGreen(c1) + ((t * (qGreen(c2) - qGreen(c1)) + 0xff) >> 8); | ||
1716 | 979 | const quint32 r = qRed(c1) + ((t * (qRed(c2) - qRed(c1)) + 0xff) >> 8); | ||
1717 | 980 | return packColor(a, b, g, r); | ||
1718 | 981 | } | ||
1719 | 982 | |||
1720 | 983 | QSGNode* UCUbuntuShape::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data) | ||
1721 | 431 | { | 984 | { |
1722 | 432 | Q_UNUSED(data); | 985 | Q_UNUSED(data); |
1723 | 433 | 986 | ||
1729 | 434 | // FIXME(loicm) Shape textures are stored in the read-only data section of the plugin as it | 987 | const QSizeF itemSize(width(), height()); |
1730 | 435 | // avoids having to deal with paths for now. It should preferably be loaded from a file. | 988 | if (itemSize.isEmpty()) { |
1731 | 436 | 989 | delete oldNode; | |
1732 | 437 | // OpenGL allocates textures per context, so we store textures reused by | 990 | return NULL; |
1733 | 438 | // all shape instances per context as well | 991 | } |
1734 | 992 | |||
1735 | 993 | QSGNode* node = oldNode ? oldNode : createSceneGraphNode(); | ||
1736 | 994 | Q_ASSERT(node); | ||
1737 | 995 | |||
1738 | 996 | // OpenGL allocates textures per context, so we store textures reused by all shape instances | ||
1739 | 997 | // per context as well. | ||
1740 | 439 | QOpenGLContext* openglContext = window() ? window()->openglContext() : NULL; | 998 | QOpenGLContext* openglContext = window() ? window()->openglContext() : NULL; |
1752 | 440 | if (Q_UNLIKELY(!openglContext)) { | 999 | Q_ASSERT(openglContext); |
1753 | 441 | qCritical() << "Window has no GL context!"; | 1000 | ShapeTextures &shapeTextures = shapeTexturesHash[openglContext]; |
1754 | 442 | delete old_node; | 1001 | if (!shapeTextures.high) { |
1755 | 443 | return NULL; | 1002 | shapeTextures.high = window()->createTextureFromImage( |
1745 | 444 | } | ||
1746 | 445 | |||
1747 | 446 | TextureHandles &textureHandles = textures_[openglContext]; | ||
1748 | 447 | // If the hash table didn't contain an entry for the current context, the | ||
1749 | 448 | // line above has just caused the creation of a default-constructed value. | ||
1750 | 449 | if (!textureHandles.high) { | ||
1751 | 450 | textureHandles.high = window()->createTextureFromImage( | ||
1756 | 451 | QImage(shapeTextureHigh.data, shapeTextureHigh.width, shapeTextureHigh.height, | 1003 | QImage(shapeTextureHigh.data, shapeTextureHigh.width, shapeTextureHigh.height, |
1757 | 452 | QImage::Format_ARGB32_Premultiplied)); | 1004 | QImage::Format_ARGB32_Premultiplied)); |
1759 | 453 | textureHandles.low = window()->createTextureFromImage( | 1005 | shapeTextures.low = window()->createTextureFromImage( |
1760 | 454 | QImage(shapeTextureLow.data, shapeTextureLow.width, shapeTextureLow.height, | 1006 | QImage(shapeTextureLow.data, shapeTextureLow.width, shapeTextureLow.height, |
1761 | 455 | QImage::Format_ARGB32_Premultiplied)); | 1007 | QImage::Format_ARGB32_Premultiplied)); |
1762 | 456 | QObject::connect(openglContext, SIGNAL(aboutToBeDestroyed()), | 1008 | QObject::connect(openglContext, SIGNAL(aboutToBeDestroyed()), |
1773 | 457 | this, SLOT(onOpenglContextDestroyed()), | 1009 | this, SLOT(_q_openglContextDestroyed()), Qt::DirectConnection); |
1774 | 458 | Qt::DirectConnection); | 1010 | } |
1775 | 459 | } | 1011 | |
1776 | 460 | 1012 | // Get the texture info and update the source transform if needed. | |
1777 | 461 | // Update the node whenever the source item's texture changes. | 1013 | QSGTextureProvider* provider = m_source ? m_source->textureProvider() : NULL; |
1778 | 462 | QSGTextureProvider* provider = image_ ? image_->textureProvider() : NULL; | 1014 | QSGTexture* sourceTexture = provider ? provider->texture() : NULL; |
1779 | 463 | if (provider != provider_) { | 1015 | QRectF sourceTextureRect(0.0f, 0.0f, 1.0f, 1.0f); |
1780 | 464 | if (provider_) { | 1016 | if (sourceTexture) { |
1781 | 465 | QObject::disconnect(provider_, SIGNAL(textureChanged()), this, SLOT(update())); | 1017 | if (m_sourceHorizontalWrapMode == Transparent && m_sourceVerticalWrapMode == Transparent) { |
1782 | 466 | QObject::disconnect(provider_, SIGNAL(destroyed()), this, SLOT(providerDestroyed())); | 1018 | sourceTextureRect = sourceTexture->normalizedTextureSubRect(); |
1783 | 1019 | } | ||
1784 | 1020 | if (m_flags & DirtySourceTransform) { | ||
1785 | 1021 | if (m_flags & SourceApiSet) { | ||
1786 | 1022 | updateSourceTransform(itemSize.width(), itemSize.height(), m_sourceFillMode, | ||
1787 | 1023 | m_sourceHorizontalAlignment, m_sourceVerticalAlignment, | ||
1788 | 1024 | sourceTexture->textureSize()); | ||
1789 | 1025 | } else { | ||
1790 | 1026 | FillMode imageFillMode = (m_flags & Stretched) ? Stretch : PreserveAspectCrop; | ||
1791 | 1027 | updateSourceTransform(itemSize.width(), itemSize.height(), imageFillMode, | ||
1792 | 1028 | m_imageHorizontalAlignment, m_imageVerticalAlignment, | ||
1793 | 1029 | sourceTexture->textureSize()); | ||
1794 | 1030 | } | ||
1795 | 1031 | m_flags &= ~DirtySourceTransform; | ||
1796 | 1032 | } | ||
1797 | 1033 | } | ||
1798 | 1034 | |||
1799 | 1035 | // Update the shape item whenever the source item's texture changes. | ||
1800 | 1036 | if (provider != m_sourceTextureProvider) { | ||
1801 | 1037 | if (m_sourceTextureProvider) { | ||
1802 | 1038 | QObject::disconnect(m_sourceTextureProvider, SIGNAL(textureChanged()), | ||
1803 | 1039 | this, SLOT(_q_textureChanged())); | ||
1804 | 1040 | QObject::disconnect(m_sourceTextureProvider, SIGNAL(destroyed()), | ||
1805 | 1041 | this, SLOT(_q_providerDestroyed())); | ||
1806 | 467 | } | 1042 | } |
1807 | 468 | if (provider) { | 1043 | if (provider) { |
1810 | 469 | QObject::connect(provider, SIGNAL(textureChanged()), this, SLOT(update())); | 1044 | QObject::connect(provider, SIGNAL(textureChanged()), this, SLOT(_q_textureChanged())); |
1811 | 470 | QObject::connect(provider, SIGNAL(destroyed()), this, SLOT(providerDestroyed())); | 1045 | QObject::connect(provider, SIGNAL(destroyed()), this, SLOT(_q_providerDestroyed())); |
1812 | 471 | } | 1046 | } |
1828 | 472 | provider_ = provider; | 1047 | m_sourceTextureProvider = provider; |
1829 | 473 | } | 1048 | } |
1830 | 474 | 1049 | ||
1831 | 475 | ShapeNode* node = static_cast<ShapeNode*>(old_node); | 1050 | const float gridUnit = UCUnits::instance().gridUnit(); |
1832 | 476 | if (!node) { | 1051 | ShapeTextureData* shapeTextureData; |
1833 | 477 | node = new ShapeNode(this); | 1052 | QSGTexture* shapeTexture; |
1834 | 478 | } | 1053 | if (gridUnit > lowHighTextureThreshold) { |
1835 | 479 | 1054 | shapeTextureData = &shapeTextureHigh; | |
1836 | 480 | ShapeTexturedMaterial* texturedMaterial = node->texturedMaterial(); | 1055 | shapeTexture = shapeTextures.high; |
1822 | 481 | ShapeColoredMaterial* coloredMaterial = node->coloredMaterial(); | ||
1823 | 482 | TextureData* textureData; | ||
1824 | 483 | QSGTexture* textureHandle; | ||
1825 | 484 | if (gridUnit_ > lowHighTextureThreshold) { | ||
1826 | 485 | textureData = &shapeTextureHigh; | ||
1827 | 486 | textureHandle = textureHandles.high; | ||
1837 | 487 | } else { | 1056 | } else { |
1840 | 488 | textureData = &shapeTextureLow; | 1057 | shapeTextureData = &shapeTextureLow; |
1841 | 489 | textureHandle = textureHandles.low; | 1058 | shapeTexture = shapeTextures.low; |
1842 | 490 | } | 1059 | } |
1843 | 491 | 1060 | ||
1844 | 492 | // Set the shape texture to be used by the materials depending on current grid unit. The radius | 1061 | // Set the shape texture to be used by the materials depending on current grid unit. The radius |
1845 | 493 | // is set considering the current grid unit and the texture raster grid unit. When the item size | 1062 | // is set considering the current grid unit and the texture raster grid unit. When the item size |
1852 | 494 | // is less than 2 radii, the radius is scaled down anyhow. | 1063 | // is less than 2 radii, the radius is scaled down. |
1853 | 495 | float radius = (radius_ == ShapeItem::SmallRadius) ? | 1064 | QSGTexture::Filtering shapeTextureFiltering; |
1854 | 496 | textureData->smallRadius : textureData->mediumRadius; | 1065 | float radius = (m_radius == SmallRadius) ? |
1855 | 497 | const float scaleFactor = gridUnit_ / textureData->gridUnit; | 1066 | shapeTextureData->smallRadius : shapeTextureData->mediumRadius; |
1856 | 498 | radius *= scaleFactor; | 1067 | const float scaleFactor = gridUnit / shapeTextureData->gridUnit; |
1857 | 499 | int scaledDown = 0; | 1068 | shapeTextureFiltering = QSGTexture::Nearest; |
1858 | 500 | if (scaleFactor != 1.0f) { | 1069 | if (scaleFactor != 1.0f) { |
1860 | 501 | scaledDown |= 1; | 1070 | radius *= scaleFactor; |
1861 | 1071 | shapeTextureFiltering = QSGTexture::Linear; | ||
1862 | 502 | } | 1072 | } |
1864 | 503 | const float halfMinWidthHeight = qMin(geometry_.width(), geometry_.height()) * 0.5f; | 1073 | const float halfMinWidthHeight = qMin(itemSize.width(), itemSize.height()) * 0.5f; |
1865 | 504 | if (radius > halfMinWidthHeight) { | 1074 | if (radius > halfMinWidthHeight) { |
1866 | 505 | radius = halfMinWidthHeight; | 1075 | radius = halfMinWidthHeight; |
1868 | 506 | scaledDown |= 1; | 1076 | shapeTextureFiltering = QSGTexture::Linear; |
1869 | 507 | } | 1077 | } |
1882 | 508 | coloredMaterial->setShapeTexture(textureHandle, !!scaledDown); | 1078 | |
1883 | 509 | texturedMaterial->setShapeTexture(textureHandle, !!scaledDown); | 1079 | updateMaterial(node, shapeTexture, shapeTextureFiltering, sourceTexture); |
1884 | 510 | 1080 | ||
1885 | 511 | // Update the other material properties. | 1081 | // Select the right shape texture coordinates. |
1886 | 512 | coloredMaterial->setColor(color_); | 1082 | int index = (m_border == RawBorder) ? 0 : (m_border == IdleBorder) ? 1 : 2; |
1887 | 513 | coloredMaterial->setGradientColor(gradientColor_); | 1083 | if (m_radius == SmallRadius) { |
1876 | 514 | texturedMaterial->setImage(image_); | ||
1877 | 515 | |||
1878 | 516 | // Update node vertices and type. | ||
1879 | 517 | int index = (border_ == ShapeItem::RawBorder) ? | ||
1880 | 518 | 0 : (border_ == ShapeItem::IdleBorder) ? 1 : 2; | ||
1881 | 519 | if (radius_ == ShapeItem::SmallRadius) | ||
1888 | 520 | index += 3; | 1084 | index += 3; |
1893 | 521 | node->setVertices(geometry_, radius, image_, stretched_, hAlignment_, vAlignment_, | 1085 | } |
1894 | 522 | textureData->coordinate[index]); | 1086 | |
1895 | 523 | const QSGTexture* texture = provider ? provider->texture() : NULL; | 1087 | // Get the affine transformation for the source texture coordinates. |
1896 | 524 | node->setMaterialType(texture ? ShapeNode::TexturedMaterial : ShapeNode::ColoredMaterial); | 1088 | const QVector4D sourceCoordTransform( |
1897 | 1089 | m_sourceTransform.x() * sourceTextureRect.width(), | ||
1898 | 1090 | m_sourceTransform.y() * sourceTextureRect.height(), | ||
1899 | 1091 | m_sourceTransform.z() * sourceTextureRect.width() + sourceTextureRect.x(), | ||
1900 | 1092 | m_sourceTransform.w() * sourceTextureRect.height() + sourceTextureRect.y()); | ||
1901 | 1093 | |||
1902 | 1094 | // Get the affine transformation for the source mask coordinates, pixels lying inside the mask | ||
1903 | 1095 | // (values in the range [-1, 1]) will be textured in the fragment shader. In case of a repeat | ||
1904 | 1096 | // wrap mode, the transformation is made so that the mask takes the whole area. | ||
1905 | 1097 | const QVector4D sourceMaskTransform( | ||
1906 | 1098 | m_sourceHorizontalWrapMode == Transparent ? m_sourceTransform.x() * 2.0f : 2.0f, | ||
1907 | 1099 | m_sourceVerticalWrapMode == Transparent ? m_sourceTransform.y() * 2.0f : 2.0f, | ||
1908 | 1100 | m_sourceHorizontalWrapMode == Transparent ? m_sourceTransform.z() * 2.0f - 1.0f : -1.0f, | ||
1909 | 1101 | m_sourceVerticalWrapMode == Transparent ? m_sourceTransform.w() * 2.0f - 1.0f : -1.0f); | ||
1910 | 1102 | |||
1911 | 1103 | // Select and pack the lerp'd and premultiplied background colors. | ||
1912 | 1104 | QRgb color[2]; | ||
1913 | 1105 | if (m_flags & BackgroundApiSet) { | ||
1914 | 1106 | color[0] = m_backgroundColor; | ||
1915 | 1107 | color[1] = (m_backgroundMode == SolidColor) ? | ||
1916 | 1108 | m_backgroundColor : m_secondaryBackgroundColor; | ||
1917 | 1109 | } else { | ||
1918 | 1110 | if (!sourceTexture) { | ||
1919 | 1111 | color[0] = m_backgroundColor; | ||
1920 | 1112 | // For API compatibility reasons, m_secondaryBackgroundColor is set to m_backgroundColor | ||
1921 | 1113 | // as long as setGradientColor() isn't called, so we can safely use it here. | ||
1922 | 1114 | color[1] = m_secondaryBackgroundColor; | ||
1923 | 1115 | } else { | ||
1924 | 1116 | // The deprecated image API was created such that whenever an image is set, the | ||
1925 | 1117 | // background color is transparent. | ||
1926 | 1118 | color[0] = qRgba(0, 0, 0, 0); | ||
1927 | 1119 | color[1] = qRgba(0, 0, 0, 0); | ||
1928 | 1120 | } | ||
1929 | 1121 | } | ||
1930 | 1122 | const quint32 radiusHeight = static_cast<quint32>((radius / itemSize.height()) * 255.0f); | ||
1931 | 1123 | const quint32 backgroundColor[4] = { | ||
1932 | 1124 | packColor(qAlpha(color[0]), qBlue(color[0]), qGreen(color[0]), qRed(color[0])), | ||
1933 | 1125 | lerpColor(radiusHeight, color[0], color[1]), | ||
1934 | 1126 | lerpColor(255 - radiusHeight, color[0], color[1]), | ||
1935 | 1127 | packColor(qAlpha(color[1]), qBlue(color[1]), qGreen(color[1]), qRed(color[1])) | ||
1936 | 1128 | }; | ||
1937 | 1129 | |||
1938 | 1130 | updateGeometry( | ||
1939 | 1131 | node, itemSize.width(), itemSize.height(), radius, shapeTextureData->coordinate[index], | ||
1940 | 1132 | sourceCoordTransform, sourceMaskTransform, backgroundColor); | ||
1941 | 525 | 1133 | ||
1942 | 526 | return node; | 1134 | return node; |
1943 | 527 | } | 1135 | } |
1944 | 528 | 1136 | ||
1954 | 529 | // --- Scene graph geometry node --- | 1137 | QSGNode* UCUbuntuShape::createSceneGraphNode() const |
1946 | 530 | |||
1947 | 531 | ShapeNode::ShapeNode(ShapeItem* item) | ||
1948 | 532 | : QSGGeometryNode() | ||
1949 | 533 | , item_(item) | ||
1950 | 534 | , geometry_(getAttributes(), shapeMesh.vertexCount, shapeMesh.indexCount, shapeMesh.indexType) | ||
1951 | 535 | , texturedMaterial_() | ||
1952 | 536 | , coloredMaterial_() | ||
1953 | 537 | , currentMaterial_(ShapeNode::ColoredMaterial) | ||
1955 | 538 | { | 1138 | { |
1964 | 539 | memcpy(geometry_.indexData(), shapeMesh.indices, | 1139 | return new ShapeNode; |
1957 | 540 | shapeMesh.indexCount * sizeOfType(shapeMesh.indexType)); | ||
1958 | 541 | geometry_.setDrawingMode(GL_TRIANGLE_STRIP); | ||
1959 | 542 | geometry_.setIndexDataPattern(QSGGeometry::StaticPattern); | ||
1960 | 543 | geometry_.setVertexDataPattern(QSGGeometry::AlwaysUploadPattern); | ||
1961 | 544 | setGeometry(&geometry_); | ||
1962 | 545 | setMaterial(&coloredMaterial_); | ||
1963 | 546 | setFlag(UsePreprocess, false); | ||
1965 | 547 | } | 1140 | } |
1966 | 548 | 1141 | ||
1970 | 549 | void ShapeNode::setVertices(const QRectF& geometry, float radius, QQuickItem* image, bool stretched, | 1142 | void UCUbuntuShape::updateMaterial( |
1971 | 550 | ShapeItem::HAlignment hAlignment, ShapeItem::VAlignment vAlignment, | 1143 | QSGNode* node, QSGTexture* shapeTexture, QSGTexture::Filtering shapeTextureFiltering, |
1972 | 551 | float shapeCoordinate[][2]) | 1144 | QSGTexture* sourceTexture) |
1973 | 552 | { | 1145 | { |
1985 | 553 | ShapeNode::Vertex* vertices = reinterpret_cast<ShapeNode::Vertex*>(geometry_.vertexData()); | 1146 | ShapeNode* shapeNode = static_cast<ShapeNode*>(node); |
1986 | 554 | const QSGTextureProvider* provider = image ? image->textureProvider() : NULL; | 1147 | ShapeMaterial::Data* materialData = shapeNode->material()->data(); |
1987 | 555 | const QSGTexture* texture = provider ? provider->texture() : NULL; | 1148 | quint8 flags = 0; |
1977 | 556 | const float width = geometry.width(); | ||
1978 | 557 | const float height = geometry.height(); | ||
1979 | 558 | float topCoordinate; | ||
1980 | 559 | float bottomCoordinate; | ||
1981 | 560 | float leftCoordinate; | ||
1982 | 561 | float rightCoordinate; | ||
1983 | 562 | float radiusCoordinateWidth; | ||
1984 | 563 | float radiusCoordinateHeight; | ||
1988 | 564 | 1149 | ||
2017 | 565 | // FIXME(loicm) With a NxM image, a preserve aspect crop fill mode and a width | 1150 | materialData->shapeTexture = shapeTexture; |
2018 | 566 | // component size of N (or a height component size of M), changing the the | 1151 | if (sourceTexture && m_sourceOpacity) { |
2019 | 567 | // height (or width) breaks the 1:1 texel/pixel mapping for odd values. | 1152 | materialData->sourceTextureProvider = m_sourceTextureProvider; |
2020 | 568 | if (!stretched && texture) { | 1153 | materialData->sourceOpacity = m_sourceOpacity; |
2021 | 569 | // Preserve source image aspect ratio cropping areas exceeding destination rectangle. | 1154 | if (m_sourceHorizontalWrapMode == Repeat) { |
2022 | 570 | const float factors[3] = { 0.0f, 0.5f, 1.0f }; | 1155 | flags |= ShapeMaterial::Data::HorizontallyRepeated; |
2023 | 571 | const QSize srcSize = texture->textureSize(); | 1156 | } |
2024 | 572 | const float srcRatio = static_cast<float>(srcSize.width()) / srcSize.height(); | 1157 | if (m_sourceVerticalWrapMode == Repeat) { |
2025 | 573 | const float dstRatio = static_cast<float>(width) / height; | 1158 | flags |= ShapeMaterial::Data::VerticallyRepeated; |
2026 | 574 | if (dstRatio <= srcRatio) { | 1159 | } |
2027 | 575 | const float inCoordinateSize = dstRatio / srcRatio; | 1160 | flags |= ShapeMaterial::Data::Textured; |
2000 | 576 | const float outCoordinateSize = 1.0f - inCoordinateSize; | ||
2001 | 577 | topCoordinate = 0.0f; | ||
2002 | 578 | bottomCoordinate = 1.0f; | ||
2003 | 579 | leftCoordinate = outCoordinateSize * factors[hAlignment]; | ||
2004 | 580 | rightCoordinate = 1.0f - (outCoordinateSize * (1.0f - factors[hAlignment])); | ||
2005 | 581 | radiusCoordinateHeight = radius / height; | ||
2006 | 582 | radiusCoordinateWidth = (radius / width) * inCoordinateSize; | ||
2007 | 583 | } else { | ||
2008 | 584 | const float inCoordinateSize = srcRatio / dstRatio; | ||
2009 | 585 | const float outCoordinateSize = 1.0f - inCoordinateSize; | ||
2010 | 586 | topCoordinate = outCoordinateSize * factors[vAlignment]; | ||
2011 | 587 | bottomCoordinate = 1.0f - (outCoordinateSize * (1.0f - factors[vAlignment])); | ||
2012 | 588 | leftCoordinate = 0.0f; | ||
2013 | 589 | rightCoordinate = 1.0f; | ||
2014 | 590 | radiusCoordinateHeight = (radius / height) * inCoordinateSize; | ||
2015 | 591 | radiusCoordinateWidth = radius / width; | ||
2016 | 592 | } | ||
2028 | 593 | } else { | 1161 | } else { |
2048 | 594 | // Don't preserve source image aspect ratio stretching it in destination rectangle. | 1162 | materialData->sourceTextureProvider = NULL; |
2049 | 595 | topCoordinate = 0.0f; | 1163 | materialData->sourceOpacity = 0; |
2050 | 596 | bottomCoordinate = 1.0f; | 1164 | } |
2051 | 597 | leftCoordinate = 0.0f; | 1165 | materialData->shapeTextureFiltering = shapeTextureFiltering; |
2052 | 598 | rightCoordinate = 1.0f; | 1166 | materialData->flags = flags; |
2053 | 599 | radiusCoordinateHeight = radius / height; | 1167 | } |
2054 | 600 | radiusCoordinateWidth = radius / width; | 1168 | |
2055 | 601 | } | 1169 | void UCUbuntuShape::updateGeometry( |
2056 | 602 | 1170 | QSGNode* node, float width, float height, float radius, const float shapeCoordinate[][2], | |
2057 | 603 | // Scale and translate coordinates of textures packed in an atlas. | 1171 | const QVector4D& sourceCoordTransform, const QVector4D& sourceMaskTransform, |
2058 | 604 | if (texture && texture->isAtlasTexture()) { | 1172 | const quint32 backgroundColor[4]) |
2059 | 605 | const QRectF srcSubRect = texture->normalizedTextureSubRect(); | 1173 | { |
2060 | 606 | topCoordinate = topCoordinate * srcSubRect.height() + srcSubRect.y(); | 1174 | ShapeNode* shapeNode = static_cast<ShapeNode*>(node); |
2061 | 607 | bottomCoordinate = bottomCoordinate * srcSubRect.height() + srcSubRect.y(); | 1175 | ShapeNode::Vertex* v = reinterpret_cast<ShapeNode::Vertex*>( |
2062 | 608 | leftCoordinate = leftCoordinate * srcSubRect.width() + srcSubRect.x(); | 1176 | shapeNode->geometry()->vertexData()); |
2063 | 609 | rightCoordinate = rightCoordinate * srcSubRect.width() + srcSubRect.x(); | 1177 | |
2064 | 610 | radiusCoordinateHeight = radiusCoordinateHeight * srcSubRect.height(); | 1178 | // Convert radius to normalized coordinates. |
2065 | 611 | radiusCoordinateWidth = radiusCoordinateWidth * srcSubRect.width(); | 1179 | const float rw = radius / width; |
2066 | 612 | } | 1180 | const float rh = radius / height; |
2067 | 613 | 1181 | ||
2068 | 614 | // Set top row of 4 vertices. | 1182 | // Set top row of 4 vertices. |
2093 | 615 | vertices[0].position[0] = 0.0f; | 1183 | v[0].position[0] = 0.0f; |
2094 | 616 | vertices[0].position[1] = 0.0f; | 1184 | v[0].position[1] = 0.0f; |
2095 | 617 | vertices[0].shapeCoordinate[0] = shapeCoordinate[0][0]; | 1185 | v[0].shapeCoordinate[0] = shapeCoordinate[0][0]; |
2096 | 618 | vertices[0].shapeCoordinate[1] = shapeCoordinate[0][1]; | 1186 | v[0].shapeCoordinate[1] = shapeCoordinate[0][1]; |
2097 | 619 | vertices[0].imageCoordinate[0] = leftCoordinate; | 1187 | v[0].sourceCoordinate[0] = sourceCoordTransform.z(); |
2098 | 620 | vertices[0].imageCoordinate[1] = topCoordinate; | 1188 | v[0].sourceCoordinate[1] = sourceCoordTransform.w(); |
2099 | 621 | vertices[1].position[0] = radius; | 1189 | v[0].sourceCoordinate[2] = sourceMaskTransform.z(); |
2100 | 622 | vertices[1].position[1] = 0.0f; | 1190 | v[0].sourceCoordinate[3] = sourceMaskTransform.w(); |
2101 | 623 | vertices[1].shapeCoordinate[0] = shapeCoordinate[1][0]; | 1191 | v[0].backgroundColor = backgroundColor[0]; |
2102 | 624 | vertices[1].shapeCoordinate[1] = shapeCoordinate[1][1]; | 1192 | v[1].position[0] = radius; |
2103 | 625 | vertices[1].imageCoordinate[0] = leftCoordinate + radiusCoordinateWidth; | 1193 | v[1].position[1] = 0.0f; |
2104 | 626 | vertices[1].imageCoordinate[1] = topCoordinate; | 1194 | v[1].shapeCoordinate[0] = shapeCoordinate[1][0]; |
2105 | 627 | vertices[2].position[0] = width - radius; | 1195 | v[1].shapeCoordinate[1] = shapeCoordinate[1][1]; |
2106 | 628 | vertices[2].position[1] = 0.0f; | 1196 | v[1].sourceCoordinate[0] = rw * sourceCoordTransform.x() + sourceCoordTransform.z(); |
2107 | 629 | vertices[2].shapeCoordinate[0] = shapeCoordinate[2][0]; | 1197 | v[1].sourceCoordinate[1] = sourceCoordTransform.w(); |
2108 | 630 | vertices[2].shapeCoordinate[1] = shapeCoordinate[2][1]; | 1198 | v[1].sourceCoordinate[2] = rw * sourceMaskTransform.x() + sourceMaskTransform.z(); |
2109 | 631 | vertices[2].imageCoordinate[0] = rightCoordinate - radiusCoordinateWidth; | 1199 | v[1].sourceCoordinate[3] = sourceMaskTransform.w(); |
2110 | 632 | vertices[2].imageCoordinate[1] = topCoordinate; | 1200 | v[1].backgroundColor = backgroundColor[0]; |
2111 | 633 | vertices[3].position[0] = width; | 1201 | v[2].position[0] = width - radius; |
2112 | 634 | vertices[3].position[1] = 0.0f; | 1202 | v[2].position[1] = 0.0f; |
2113 | 635 | vertices[3].shapeCoordinate[0] = shapeCoordinate[3][0]; | 1203 | v[2].shapeCoordinate[0] = shapeCoordinate[2][0]; |
2114 | 636 | vertices[3].shapeCoordinate[1] = shapeCoordinate[3][1]; | 1204 | v[2].shapeCoordinate[1] = shapeCoordinate[2][1]; |
2115 | 637 | vertices[3].imageCoordinate[0] = rightCoordinate; | 1205 | v[2].sourceCoordinate[0] = (1.0f - rw) * sourceCoordTransform.x() + sourceCoordTransform.z(); |
2116 | 638 | vertices[3].imageCoordinate[1] = topCoordinate; | 1206 | v[2].sourceCoordinate[1] = sourceCoordTransform.w(); |
2117 | 1207 | v[2].sourceCoordinate[2] = (1.0f - rw) * sourceMaskTransform.x() + sourceMaskTransform.z(); | ||
2118 | 1208 | v[2].sourceCoordinate[3] = sourceMaskTransform.w(); | ||
2119 | 1209 | v[2].backgroundColor = backgroundColor[0]; | ||
2120 | 1210 | v[3].position[0] = width; | ||
2121 | 1211 | v[3].position[1] = 0.0f; | ||
2122 | 1212 | v[3].shapeCoordinate[0] = shapeCoordinate[3][0]; | ||
2123 | 1213 | v[3].shapeCoordinate[1] = shapeCoordinate[3][1]; | ||
2124 | 1214 | v[3].sourceCoordinate[0] = sourceCoordTransform.x() + sourceCoordTransform.z(); | ||
2125 | 1215 | v[3].sourceCoordinate[1] = sourceCoordTransform.w(); | ||
2126 | 1216 | v[3].sourceCoordinate[2] = sourceMaskTransform.x() + sourceMaskTransform.z(); | ||
2127 | 1217 | v[3].sourceCoordinate[3] = sourceMaskTransform.w(); | ||
2128 | 1218 | v[3].backgroundColor = backgroundColor[0]; | ||
2129 | 639 | 1219 | ||
2130 | 640 | // Set middle-top row of 4 vertices. | 1220 | // Set middle-top row of 4 vertices. |
2155 | 641 | vertices[4].position[0] = 0.0f; | 1221 | v[4].position[0] = 0.0f; |
2156 | 642 | vertices[4].position[1] = radius; | 1222 | v[4].position[1] = radius; |
2157 | 643 | vertices[4].shapeCoordinate[0] = shapeCoordinate[4][0]; | 1223 | v[4].shapeCoordinate[0] = shapeCoordinate[4][0]; |
2158 | 644 | vertices[4].shapeCoordinate[1] = shapeCoordinate[4][1]; | 1224 | v[4].shapeCoordinate[1] = shapeCoordinate[4][1]; |
2159 | 645 | vertices[4].imageCoordinate[0] = leftCoordinate; | 1225 | v[4].sourceCoordinate[0] = sourceCoordTransform.z(); |
2160 | 646 | vertices[4].imageCoordinate[1] = topCoordinate + radiusCoordinateHeight; | 1226 | v[4].sourceCoordinate[1] = rh * sourceCoordTransform.y() + sourceCoordTransform.w(); |
2161 | 647 | vertices[5].position[0] = radius; | 1227 | v[4].sourceCoordinate[2] = sourceMaskTransform.z(); |
2162 | 648 | vertices[5].position[1] = radius; | 1228 | v[4].sourceCoordinate[3] = rh * sourceMaskTransform.y() + sourceMaskTransform.w(); |
2163 | 649 | vertices[5].shapeCoordinate[0] = shapeCoordinate[5][0]; | 1229 | v[4].backgroundColor = backgroundColor[1]; |
2164 | 650 | vertices[5].shapeCoordinate[1] = shapeCoordinate[5][1]; | 1230 | v[5].position[0] = radius; |
2165 | 651 | vertices[5].imageCoordinate[0] = leftCoordinate + radiusCoordinateWidth; | 1231 | v[5].position[1] = radius; |
2166 | 652 | vertices[5].imageCoordinate[1] = topCoordinate + radiusCoordinateHeight; | 1232 | v[5].shapeCoordinate[0] = shapeCoordinate[5][0]; |
2167 | 653 | vertices[6].position[0] = width - radius; | 1233 | v[5].shapeCoordinate[1] = shapeCoordinate[5][1]; |
2168 | 654 | vertices[6].position[1] = radius; | 1234 | v[5].sourceCoordinate[0] = rw * sourceCoordTransform.x() + sourceCoordTransform.z(); |
2169 | 655 | vertices[6].shapeCoordinate[0] = shapeCoordinate[6][0]; | 1235 | v[5].sourceCoordinate[1] = rh * sourceCoordTransform.y() + sourceCoordTransform.w(); |
2170 | 656 | vertices[6].shapeCoordinate[1] = shapeCoordinate[6][1]; | 1236 | v[5].sourceCoordinate[2] = rw * sourceMaskTransform.x() + sourceMaskTransform.z(); |
2171 | 657 | vertices[6].imageCoordinate[0] = rightCoordinate - radiusCoordinateWidth; | 1237 | v[5].sourceCoordinate[3] = rh * sourceMaskTransform.y() + sourceMaskTransform.w(); |
2172 | 658 | vertices[6].imageCoordinate[1] = topCoordinate + radiusCoordinateHeight; | 1238 | v[5].backgroundColor = backgroundColor[1]; |
2173 | 659 | vertices[7].position[0] = width; | 1239 | v[6].position[0] = width - radius; |
2174 | 660 | vertices[7].position[1] = radius; | 1240 | v[6].position[1] = radius; |
2175 | 661 | vertices[7].shapeCoordinate[0] = shapeCoordinate[7][0]; | 1241 | v[6].shapeCoordinate[0] = shapeCoordinate[6][0]; |
2176 | 662 | vertices[7].shapeCoordinate[1] = shapeCoordinate[7][1]; | 1242 | v[6].shapeCoordinate[1] = shapeCoordinate[6][1]; |
2177 | 663 | vertices[7].imageCoordinate[0] = rightCoordinate; | 1243 | v[6].sourceCoordinate[0] = (1.0f - rw) * sourceCoordTransform.x() + sourceCoordTransform.z(); |
2178 | 664 | vertices[7].imageCoordinate[1] = topCoordinate + radiusCoordinateHeight; | 1244 | v[6].sourceCoordinate[1] = rh * sourceCoordTransform.y() + sourceCoordTransform.w(); |
2179 | 1245 | v[6].sourceCoordinate[2] = (1.0f - rw) * sourceMaskTransform.x() + sourceMaskTransform.z(); | ||
2180 | 1246 | v[6].sourceCoordinate[3] = rh * sourceMaskTransform.y() + sourceMaskTransform.w(); | ||
2181 | 1247 | v[6].backgroundColor = backgroundColor[1]; | ||
2182 | 1248 | v[7].position[0] = width; | ||
2183 | 1249 | v[7].position[1] = radius; | ||
2184 | 1250 | v[7].shapeCoordinate[0] = shapeCoordinate[7][0]; | ||
2185 | 1251 | v[7].shapeCoordinate[1] = shapeCoordinate[7][1]; | ||
2186 | 1252 | v[7].sourceCoordinate[0] = sourceCoordTransform.x() + sourceCoordTransform.z(); | ||
2187 | 1253 | v[7].sourceCoordinate[1] = rh * sourceCoordTransform.y() + sourceCoordTransform.w(); | ||
2188 | 1254 | v[7].sourceCoordinate[2] = sourceMaskTransform.x() + sourceMaskTransform.z(); | ||
2189 | 1255 | v[7].sourceCoordinate[3] = rh * sourceMaskTransform.y() + sourceMaskTransform.w(); | ||
2190 | 1256 | v[7].backgroundColor = backgroundColor[1]; | ||
2191 | 665 | 1257 | ||
2192 | 666 | // Set middle-bottom row of 4 vertices. | 1258 | // Set middle-bottom row of 4 vertices. |
2217 | 667 | vertices[8].position[0] = 0.0f; | 1259 | v[8].position[0] = 0.0f; |
2218 | 668 | vertices[8].position[1] = height - radius; | 1260 | v[8].position[1] = height - radius; |
2219 | 669 | vertices[8].shapeCoordinate[0] = shapeCoordinate[8][0]; | 1261 | v[8].shapeCoordinate[0] = shapeCoordinate[8][0]; |
2220 | 670 | vertices[8].shapeCoordinate[1] = shapeCoordinate[8][1]; | 1262 | v[8].shapeCoordinate[1] = shapeCoordinate[8][1]; |
2221 | 671 | vertices[8].imageCoordinate[0] = leftCoordinate; | 1263 | v[8].sourceCoordinate[0] = sourceCoordTransform.z(); |
2222 | 672 | vertices[8].imageCoordinate[1] = bottomCoordinate - radiusCoordinateHeight; | 1264 | v[8].sourceCoordinate[1] = (1.0f - rh) * sourceCoordTransform.y() + sourceCoordTransform.w(); |
2223 | 673 | vertices[9].position[0] = radius; | 1265 | v[8].sourceCoordinate[2] = sourceMaskTransform.z(); |
2224 | 674 | vertices[9].position[1] = height - radius; | 1266 | v[8].sourceCoordinate[3] = (1.0f - rh) * sourceMaskTransform.y() + sourceMaskTransform.w(); |
2225 | 675 | vertices[9].shapeCoordinate[0] = shapeCoordinate[9][0]; | 1267 | v[8].backgroundColor = backgroundColor[2]; |
2226 | 676 | vertices[9].shapeCoordinate[1] = shapeCoordinate[9][1]; | 1268 | v[9].position[0] = radius; |
2227 | 677 | vertices[9].imageCoordinate[0] = leftCoordinate + radiusCoordinateWidth; | 1269 | v[9].position[1] = height - radius; |
2228 | 678 | vertices[9].imageCoordinate[1] = bottomCoordinate - radiusCoordinateHeight; | 1270 | v[9].shapeCoordinate[0] = shapeCoordinate[9][0]; |
2229 | 679 | vertices[10].position[0] = width - radius; | 1271 | v[9].shapeCoordinate[1] = shapeCoordinate[9][1]; |
2230 | 680 | vertices[10].position[1] = height - radius; | 1272 | v[9].sourceCoordinate[0] = rw * sourceCoordTransform.x() + sourceCoordTransform.z(); |
2231 | 681 | vertices[10].shapeCoordinate[0] = shapeCoordinate[10][0]; | 1273 | v[9].sourceCoordinate[1] = (1.0f - rh) * sourceCoordTransform.y() + sourceCoordTransform.w(); |
2232 | 682 | vertices[10].shapeCoordinate[1] = shapeCoordinate[10][1]; | 1274 | v[9].sourceCoordinate[2] = rw * sourceMaskTransform.x() + sourceMaskTransform.z(); |
2233 | 683 | vertices[10].imageCoordinate[0] = rightCoordinate - radiusCoordinateWidth; | 1275 | v[9].sourceCoordinate[3] = (1.0f - rh) * sourceMaskTransform.y() + sourceMaskTransform.w(); |
2234 | 684 | vertices[10].imageCoordinate[1] = bottomCoordinate - radiusCoordinateHeight; | 1276 | v[9].backgroundColor = backgroundColor[2]; |
2235 | 685 | vertices[11].position[0] = width; | 1277 | v[10].position[0] = width - radius; |
2236 | 686 | vertices[11].position[1] = height - radius; | 1278 | v[10].position[1] = height - radius; |
2237 | 687 | vertices[11].shapeCoordinate[0] = shapeCoordinate[11][0]; | 1279 | v[10].shapeCoordinate[0] = shapeCoordinate[10][0]; |
2238 | 688 | vertices[11].shapeCoordinate[1] = shapeCoordinate[11][1]; | 1280 | v[10].shapeCoordinate[1] = shapeCoordinate[10][1]; |
2239 | 689 | vertices[11].imageCoordinate[0] = rightCoordinate; | 1281 | v[10].sourceCoordinate[0] = (1.0f - rw) * sourceCoordTransform.x() + sourceCoordTransform.z(); |
2240 | 690 | vertices[11].imageCoordinate[1] = bottomCoordinate - radiusCoordinateHeight; | 1282 | v[10].sourceCoordinate[1] = (1.0f - rh) * sourceCoordTransform.y() + sourceCoordTransform.w(); |
2241 | 1283 | v[10].sourceCoordinate[2] = (1.0f - rw) * sourceMaskTransform.x() + sourceMaskTransform.z(); | ||
2242 | 1284 | v[10].sourceCoordinate[3] = (1.0f - rh) * sourceMaskTransform.y() + sourceMaskTransform.w(); | ||
2243 | 1285 | v[10].backgroundColor = backgroundColor[2]; | ||
2244 | 1286 | v[11].position[0] = width; | ||
2245 | 1287 | v[11].position[1] = height - radius; | ||
2246 | 1288 | v[11].shapeCoordinate[0] = shapeCoordinate[11][0]; | ||
2247 | 1289 | v[11].shapeCoordinate[1] = shapeCoordinate[11][1]; | ||
2248 | 1290 | v[11].sourceCoordinate[0] = sourceCoordTransform.x() + sourceCoordTransform.z(); | ||
2249 | 1291 | v[11].sourceCoordinate[1] = (1.0f - rh) * sourceCoordTransform.y() + sourceCoordTransform.w(); | ||
2250 | 1292 | v[11].sourceCoordinate[2] = sourceMaskTransform.x() + sourceMaskTransform.z(); | ||
2251 | 1293 | v[11].sourceCoordinate[3] = (1.0f - rh) * sourceMaskTransform.y() + sourceMaskTransform.w(); | ||
2252 | 1294 | v[11].backgroundColor = backgroundColor[2]; | ||
2253 | 691 | 1295 | ||
2254 | 692 | // Set bottom row of 4 vertices. | 1296 | // Set bottom row of 4 vertices. |
2515 | 693 | vertices[12].position[0] = 0.0f; | 1297 | v[12].position[0] = 0.0f; |
2516 | 694 | vertices[12].position[1] = height; | 1298 | v[12].position[1] = height; |
2517 | 695 | vertices[12].shapeCoordinate[0] = shapeCoordinate[12][0]; | 1299 | v[12].shapeCoordinate[0] = shapeCoordinate[12][0]; |
2518 | 696 | vertices[12].shapeCoordinate[1] = shapeCoordinate[12][1]; | 1300 | v[12].shapeCoordinate[1] = shapeCoordinate[12][1]; |
2519 | 697 | vertices[12].imageCoordinate[0] = leftCoordinate; | 1301 | v[12].sourceCoordinate[0] = sourceCoordTransform.z(); |
2520 | 698 | vertices[12].imageCoordinate[1] = bottomCoordinate; | 1302 | v[12].sourceCoordinate[1] = sourceCoordTransform.y() + sourceCoordTransform.w(); |
2521 | 699 | vertices[13].position[0] = radius; | 1303 | v[12].sourceCoordinate[2] = sourceMaskTransform.z(); |
2522 | 700 | vertices[13].position[1] = height; | 1304 | v[12].sourceCoordinate[3] = sourceMaskTransform.y() + sourceMaskTransform.w(); |
2523 | 701 | vertices[13].shapeCoordinate[0] = shapeCoordinate[13][0]; | 1305 | v[12].backgroundColor = backgroundColor[3]; |
2524 | 702 | vertices[13].shapeCoordinate[1] = shapeCoordinate[13][1]; | 1306 | v[13].position[0] = radius; |
2525 | 703 | vertices[13].imageCoordinate[0] = leftCoordinate + radiusCoordinateWidth; | 1307 | v[13].position[1] = height; |
2526 | 704 | vertices[13].imageCoordinate[1] = bottomCoordinate; | 1308 | v[13].shapeCoordinate[0] = shapeCoordinate[13][0]; |
2527 | 705 | vertices[14].position[0] = width - radius; | 1309 | v[13].shapeCoordinate[1] = shapeCoordinate[13][1]; |
2528 | 706 | vertices[14].position[1] = height; | 1310 | v[13].sourceCoordinate[0] = rw * sourceCoordTransform.x() + sourceCoordTransform.z(); |
2529 | 707 | vertices[14].shapeCoordinate[0] = shapeCoordinate[14][0]; | 1311 | v[13].sourceCoordinate[1] = sourceCoordTransform.y() + sourceCoordTransform.w(); |
2530 | 708 | vertices[14].shapeCoordinate[1] = shapeCoordinate[14][1]; | 1312 | v[13].sourceCoordinate[2] = rw * sourceMaskTransform.x() + sourceMaskTransform.z(); |
2531 | 709 | vertices[14].imageCoordinate[0] = rightCoordinate - radiusCoordinateWidth; | 1313 | v[13].sourceCoordinate[3] = sourceMaskTransform.y() + sourceMaskTransform.w(); |
2532 | 710 | vertices[14].imageCoordinate[1] = bottomCoordinate; | 1314 | v[13].backgroundColor = backgroundColor[3]; |
2533 | 711 | vertices[15].position[0] = width; | 1315 | v[14].position[0] = width - radius; |
2534 | 712 | vertices[15].position[1] = height; | 1316 | v[14].position[1] = height; |
2535 | 713 | vertices[15].shapeCoordinate[0] = shapeCoordinate[15][0]; | 1317 | v[14].shapeCoordinate[0] = shapeCoordinate[14][0]; |
2536 | 714 | vertices[15].shapeCoordinate[1] = shapeCoordinate[15][1]; | 1318 | v[14].shapeCoordinate[1] = shapeCoordinate[14][1]; |
2537 | 715 | vertices[15].imageCoordinate[0] = rightCoordinate; | 1319 | v[14].sourceCoordinate[0] = (1.0f - rw) * sourceCoordTransform.x() + sourceCoordTransform.z(); |
2538 | 716 | vertices[15].imageCoordinate[1] = bottomCoordinate; | 1320 | v[14].sourceCoordinate[1] = sourceCoordTransform.y() + sourceCoordTransform.w(); |
2539 | 717 | 1321 | v[14].sourceCoordinate[2] = (1.0f - rw) * sourceMaskTransform.x() + sourceMaskTransform.z(); | |
2540 | 718 | markDirty(DirtyGeometry); | 1322 | v[14].sourceCoordinate[3] = sourceMaskTransform.y() + sourceMaskTransform.w(); |
2541 | 719 | } | 1323 | v[14].backgroundColor = backgroundColor[3]; |
2542 | 720 | 1324 | v[15].position[0] = width; | |
2543 | 721 | void ShapeNode::setMaterialType(ShapeNode::MaterialType material) | 1325 | v[15].position[1] = height; |
2544 | 722 | { | 1326 | v[15].shapeCoordinate[0] = shapeCoordinate[15][0]; |
2545 | 723 | if (currentMaterial_ != material) { | 1327 | v[15].shapeCoordinate[1] = shapeCoordinate[15][1]; |
2546 | 724 | if (material == ShapeNode::ColoredMaterial) | 1328 | v[15].sourceCoordinate[0] = sourceCoordTransform.x() + sourceCoordTransform.z(); |
2547 | 725 | setMaterial(&coloredMaterial_); | 1329 | v[15].sourceCoordinate[1] = sourceCoordTransform.y() + sourceCoordTransform.w(); |
2548 | 726 | else | 1330 | v[15].sourceCoordinate[2] = sourceMaskTransform.x() + sourceMaskTransform.z(); |
2549 | 727 | setMaterial(&texturedMaterial_); | 1331 | v[15].sourceCoordinate[3] = sourceMaskTransform.y() + sourceMaskTransform.w(); |
2550 | 728 | currentMaterial_ = material; | 1332 | v[15].backgroundColor = backgroundColor[3]; |
2551 | 729 | markDirty(DirtyMaterial); | 1333 | |
2552 | 730 | } | 1334 | node->markDirty(QSGNode::DirtyGeometry); |
2293 | 731 | } | ||
2294 | 732 | |||
2295 | 733 | // --- Scene graph textured material --- | ||
2296 | 734 | |||
2297 | 735 | ShapeTexturedMaterial::ShapeTexturedMaterial() | ||
2298 | 736 | : imageTextureProvider_(NULL) | ||
2299 | 737 | , shapeTexture_(NULL) | ||
2300 | 738 | , filtering_(QSGTexture::Nearest) | ||
2301 | 739 | { | ||
2302 | 740 | setFlag(Blending); | ||
2303 | 741 | } | ||
2304 | 742 | |||
2305 | 743 | QSGMaterialType* ShapeTexturedMaterial::type() const | ||
2306 | 744 | { | ||
2307 | 745 | static QSGMaterialType type; | ||
2308 | 746 | return &type; | ||
2309 | 747 | } | ||
2310 | 748 | |||
2311 | 749 | QSGMaterialShader* ShapeTexturedMaterial::createShader() const | ||
2312 | 750 | { | ||
2313 | 751 | return new ShapeTexturedShader; | ||
2314 | 752 | } | ||
2315 | 753 | |||
2316 | 754 | int ShapeTexturedMaterial::compare(const QSGMaterial* other) const | ||
2317 | 755 | { | ||
2318 | 756 | const ShapeTexturedMaterial* otherMaterial = static_cast<const ShapeTexturedMaterial*>(other); | ||
2319 | 757 | const QSGTextureProvider* otherTextureProvider = otherMaterial->imageTextureProvider(); | ||
2320 | 758 | const QSGTexture* otherTexture = otherTextureProvider ? otherTextureProvider->texture() : NULL; | ||
2321 | 759 | const int otherTextureId = otherTexture ? otherTexture->textureId() : 0; | ||
2322 | 760 | const QSGTexture* texture = imageTextureProvider_ ? imageTextureProvider_->texture() : NULL; | ||
2323 | 761 | const int textureId = texture ? texture->textureId() : 0; | ||
2324 | 762 | return textureId - otherTextureId; | ||
2325 | 763 | } | ||
2326 | 764 | |||
2327 | 765 | void ShapeTexturedMaterial::setImage(QQuickItem* image) | ||
2328 | 766 | { | ||
2329 | 767 | imageTextureProvider_ = image ? image->textureProvider() : NULL; | ||
2330 | 768 | } | ||
2331 | 769 | |||
2332 | 770 | QSGTextureProvider* ShapeTexturedMaterial::imageTextureProvider() const | ||
2333 | 771 | { | ||
2334 | 772 | return imageTextureProvider_; | ||
2335 | 773 | } | ||
2336 | 774 | |||
2337 | 775 | void ShapeTexturedMaterial::setShapeTexture(QSGTexture* texture, bool scaledDown) | ||
2338 | 776 | { | ||
2339 | 777 | shapeTexture_ = texture; | ||
2340 | 778 | filtering_ = scaledDown ? QSGTexture::Linear : QSGTexture::Nearest; | ||
2341 | 779 | } | ||
2342 | 780 | |||
2343 | 781 | // -- Scene graph textured material shader --- | ||
2344 | 782 | |||
2345 | 783 | const char *ShapeTexturedShader::vertexShader() const | ||
2346 | 784 | { | ||
2347 | 785 | return shapeVertexShader; | ||
2348 | 786 | } | ||
2349 | 787 | |||
2350 | 788 | const char* ShapeTexturedShader::fragmentShader() const | ||
2351 | 789 | { | ||
2352 | 790 | return shapeTexturedFragmentShader; | ||
2353 | 791 | } | ||
2354 | 792 | |||
2355 | 793 | char const* const* ShapeTexturedShader::attributeNames() const | ||
2356 | 794 | { | ||
2357 | 795 | static char const* const attributes[] = { | ||
2358 | 796 | "positionAttrib", "shapeCoordAttrib", "imageCoordAttrib", 0 | ||
2359 | 797 | }; | ||
2360 | 798 | return attributes; | ||
2361 | 799 | } | ||
2362 | 800 | |||
2363 | 801 | void ShapeTexturedShader::initialize() | ||
2364 | 802 | { | ||
2365 | 803 | QSGMaterialShader::initialize(); | ||
2366 | 804 | program()->bind(); | ||
2367 | 805 | program()->setUniformValue("shapeTexture", 0); | ||
2368 | 806 | program()->setUniformValue("imageTexture", 1); | ||
2369 | 807 | matrixId_ = program()->uniformLocation("matrix"); | ||
2370 | 808 | opacityId_ = program()->uniformLocation("opacity"); | ||
2371 | 809 | glFuncs_ = QOpenGLContext::currentContext()->functions(); | ||
2372 | 810 | } | ||
2373 | 811 | |||
2374 | 812 | void ShapeTexturedShader::updateState(const RenderState& state, QSGMaterial* newEffect, | ||
2375 | 813 | QSGMaterial* oldEffect) | ||
2376 | 814 | { | ||
2377 | 815 | Q_UNUSED(oldEffect); | ||
2378 | 816 | ShapeTexturedMaterial* material = static_cast<ShapeTexturedMaterial*>(newEffect); | ||
2379 | 817 | |||
2380 | 818 | // Bind textures. | ||
2381 | 819 | glFuncs_->glActiveTexture(GL_TEXTURE1); | ||
2382 | 820 | QSGTextureProvider* provider = material->imageTextureProvider(); | ||
2383 | 821 | QSGTexture* texture = provider ? provider->texture() : NULL; | ||
2384 | 822 | if (texture) | ||
2385 | 823 | texture->bind(); | ||
2386 | 824 | else | ||
2387 | 825 | glBindTexture(GL_TEXTURE_2D, 0); | ||
2388 | 826 | glFuncs_->glActiveTexture(GL_TEXTURE0); | ||
2389 | 827 | QSGTexture* shapeTexture = material->shapeTexture(); | ||
2390 | 828 | if (shapeTexture) { | ||
2391 | 829 | shapeTexture->setFiltering(material->filtering()); | ||
2392 | 830 | shapeTexture->setHorizontalWrapMode(QSGTexture::ClampToEdge); | ||
2393 | 831 | shapeTexture->setVerticalWrapMode(QSGTexture::ClampToEdge); | ||
2394 | 832 | shapeTexture->bind(); | ||
2395 | 833 | } else { | ||
2396 | 834 | glBindTexture(GL_TEXTURE_2D, 0); | ||
2397 | 835 | } | ||
2398 | 836 | |||
2399 | 837 | // Bind uniforms. | ||
2400 | 838 | if (state.isMatrixDirty()) | ||
2401 | 839 | program()->setUniformValue(matrixId_, state.combinedMatrix()); | ||
2402 | 840 | if (state.isOpacityDirty()) | ||
2403 | 841 | program()->setUniformValue(opacityId_, state.opacity()); | ||
2404 | 842 | } | ||
2405 | 843 | |||
2406 | 844 | // --- Scene graph colored material --- | ||
2407 | 845 | |||
2408 | 846 | ShapeColoredMaterial::ShapeColoredMaterial() | ||
2409 | 847 | : color_(0.0, 0.0, 0.0, 0.0) | ||
2410 | 848 | , gradientColor_(0.0, 0.0, 0.0, 0.0) | ||
2411 | 849 | , shapeTexture_(NULL) | ||
2412 | 850 | , filtering_(QSGTexture::Nearest) | ||
2413 | 851 | { | ||
2414 | 852 | setFlag(Blending); | ||
2415 | 853 | } | ||
2416 | 854 | |||
2417 | 855 | QSGMaterialType* ShapeColoredMaterial::type() const | ||
2418 | 856 | { | ||
2419 | 857 | static QSGMaterialType type; | ||
2420 | 858 | return &type; | ||
2421 | 859 | } | ||
2422 | 860 | |||
2423 | 861 | QSGMaterialShader* ShapeColoredMaterial::createShader() const | ||
2424 | 862 | { | ||
2425 | 863 | return new ShapeColoredShader; | ||
2426 | 864 | } | ||
2427 | 865 | |||
2428 | 866 | int ShapeColoredMaterial::compare(const QSGMaterial* other) const | ||
2429 | 867 | { | ||
2430 | 868 | const ShapeColoredMaterial* otherMaterial = static_cast<const ShapeColoredMaterial*>(other); | ||
2431 | 869 | if ((color_ != otherMaterial->color()) || (gradientColor_ != otherMaterial->gradientColor())) { | ||
2432 | 870 | return -1; | ||
2433 | 871 | } else { | ||
2434 | 872 | return 0; | ||
2435 | 873 | } | ||
2436 | 874 | } | ||
2437 | 875 | |||
2438 | 876 | void ShapeColoredMaterial::setColor(const QColor& color) | ||
2439 | 877 | { | ||
2440 | 878 | // Premultiply color components by alpha. | ||
2441 | 879 | const float alpha = color.alphaF(); | ||
2442 | 880 | color_ = QVector4D(color.redF() * alpha, color.greenF() * alpha, | ||
2443 | 881 | color.blueF() * alpha, alpha); | ||
2444 | 882 | } | ||
2445 | 883 | |||
2446 | 884 | void ShapeColoredMaterial::setGradientColor(const QColor& gradientColor) | ||
2447 | 885 | { | ||
2448 | 886 | // Premultiply color components by alpha. | ||
2449 | 887 | const float alpha = gradientColor.alphaF(); | ||
2450 | 888 | gradientColor_ = QVector4D(gradientColor.redF() * alpha, gradientColor.greenF() * alpha, | ||
2451 | 889 | gradientColor.blueF() * alpha, alpha); | ||
2452 | 890 | } | ||
2453 | 891 | |||
2454 | 892 | void ShapeColoredMaterial::setShapeTexture(QSGTexture* texture, bool scaledDown) | ||
2455 | 893 | { | ||
2456 | 894 | shapeTexture_ = texture; | ||
2457 | 895 | filtering_ = scaledDown ? QSGTexture::Linear : QSGTexture::Nearest; | ||
2458 | 896 | } | ||
2459 | 897 | |||
2460 | 898 | // -- Scene graph colored material shader --- | ||
2461 | 899 | |||
2462 | 900 | const char *ShapeColoredShader::vertexShader() const | ||
2463 | 901 | { | ||
2464 | 902 | return shapeVertexShader; | ||
2465 | 903 | } | ||
2466 | 904 | |||
2467 | 905 | const char* ShapeColoredShader::fragmentShader() const | ||
2468 | 906 | { | ||
2469 | 907 | return shapeColoredFragmentShader; | ||
2470 | 908 | } | ||
2471 | 909 | |||
2472 | 910 | char const* const* ShapeColoredShader::attributeNames() const | ||
2473 | 911 | { | ||
2474 | 912 | static char const* const attributes[] = { | ||
2475 | 913 | "positionAttrib", "shapeCoordAttrib", "imageCoordAttrib", 0 | ||
2476 | 914 | }; | ||
2477 | 915 | return attributes; | ||
2478 | 916 | } | ||
2479 | 917 | |||
2480 | 918 | void ShapeColoredShader::initialize() | ||
2481 | 919 | { | ||
2482 | 920 | QSGMaterialShader::initialize(); | ||
2483 | 921 | program()->bind(); | ||
2484 | 922 | program()->setUniformValue("shapeTexture", 0); | ||
2485 | 923 | matrixId_ = program()->uniformLocation("matrix"); | ||
2486 | 924 | opacityId_ = program()->uniformLocation("opacity"); | ||
2487 | 925 | colorId_ = program()->uniformLocation("color"); | ||
2488 | 926 | gradientColorId_ = program()->uniformLocation("gradientColor"); | ||
2489 | 927 | } | ||
2490 | 928 | |||
2491 | 929 | void ShapeColoredShader::updateState(const RenderState& state, QSGMaterial* newEffect, | ||
2492 | 930 | QSGMaterial* oldEffect) | ||
2493 | 931 | { | ||
2494 | 932 | Q_UNUSED(oldEffect); | ||
2495 | 933 | ShapeColoredMaterial* material = static_cast<ShapeColoredMaterial*>(newEffect); | ||
2496 | 934 | |||
2497 | 935 | // Bind texture. | ||
2498 | 936 | QSGTexture* shapeTexture = material->shapeTexture(); | ||
2499 | 937 | if (shapeTexture) { | ||
2500 | 938 | shapeTexture->setFiltering(material->filtering()); | ||
2501 | 939 | shapeTexture->setHorizontalWrapMode(QSGTexture::ClampToEdge); | ||
2502 | 940 | shapeTexture->setVerticalWrapMode(QSGTexture::ClampToEdge); | ||
2503 | 941 | shapeTexture->bind(); | ||
2504 | 942 | } else { | ||
2505 | 943 | glBindTexture(GL_TEXTURE_2D, 0); | ||
2506 | 944 | } | ||
2507 | 945 | |||
2508 | 946 | // Bind uniforms. | ||
2509 | 947 | if (state.isMatrixDirty()) | ||
2510 | 948 | program()->setUniformValue(matrixId_, state.combinedMatrix()); | ||
2511 | 949 | if (state.isOpacityDirty()) | ||
2512 | 950 | program()->setUniformValue(opacityId_, state.opacity()); | ||
2513 | 951 | program()->setUniformValue(colorId_, material->color()); | ||
2514 | 952 | program()->setUniformValue(gradientColorId_, material->gradientColor()); | ||
2553 | 953 | } | 1335 | } |
2554 | 954 | 1336 | ||
2555 | === renamed file 'modules/Ubuntu/Components/plugin/shapeitem.h' => 'modules/Ubuntu/Components/plugin/ucubuntushape.h' | |||
2556 | --- modules/Ubuntu/Components/plugin/shapeitem.h 2014-09-10 18:04:50 +0000 | |||
2557 | +++ modules/Ubuntu/Components/plugin/ucubuntushape.h 2015-03-02 15:41:23 +0000 | |||
2558 | @@ -1,5 +1,5 @@ | |||
2559 | 1 | /* | 1 | /* |
2561 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright 2013-2015 Canonical Ltd. |
2562 | 3 | * | 3 | * |
2563 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
2564 | 5 | * it under the terms of the GNU Lesser General Public License as published by | 5 | * it under the terms of the GNU Lesser General Public License as published by |
2565 | @@ -16,227 +16,314 @@ | |||
2566 | 16 | * Author: Loïc Molinari <loic.molinari@canonical.com> | 16 | * Author: Loïc Molinari <loic.molinari@canonical.com> |
2567 | 17 | */ | 17 | */ |
2568 | 18 | 18 | ||
2571 | 19 | #ifndef UBUNTU_COMPONENTS_SHAPE_H | 19 | #ifndef UCUBUNTUSHAPE_H |
2572 | 20 | #define UBUNTU_COMPONENTS_SHAPE_H | 20 | #define UCUBUNTUSHAPE_H |
2573 | 21 | 21 | ||
2574 | 22 | #include <QtQuick/QQuickItem> | 22 | #include <QtQuick/QQuickItem> |
2575 | 23 | #include <QtQuick/QSGNode> | 23 | #include <QtQuick/QSGNode> |
2576 | 24 | #include <QtQuick/qsgflatcolormaterial.h> | ||
2577 | 25 | #include <QtQuick/qsgtexture.h> | 24 | #include <QtQuick/qsgtexture.h> |
2578 | 25 | #include <QtQuick/qsgmaterial.h> | ||
2579 | 26 | #include <QtGui/QOpenGLFunctions> | 26 | #include <QtGui/QOpenGLFunctions> |
2580 | 27 | 27 | ||
2584 | 28 | // QtQuick item. | 28 | class UCUbuntuShape; |
2585 | 29 | 29 | ||
2586 | 30 | class ShapeItem : public QQuickItem | 30 | // --- Scene graph shader --- |
2587 | 31 | |||
2588 | 32 | class ShapeShader : public QSGMaterialShader | ||
2589 | 33 | { | ||
2590 | 34 | public: | ||
2591 | 35 | ShapeShader(); | ||
2592 | 36 | virtual char const* const* attributeNames() const; | ||
2593 | 37 | virtual void initialize(); | ||
2594 | 38 | virtual void updateState( | ||
2595 | 39 | const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect); | ||
2596 | 40 | |||
2597 | 41 | private: | ||
2598 | 42 | QOpenGLFunctions* m_functions; | ||
2599 | 43 | int m_matrixId; | ||
2600 | 44 | int m_opacityId; | ||
2601 | 45 | int m_sourceOpacityId; | ||
2602 | 46 | int m_texturedId; | ||
2603 | 47 | }; | ||
2604 | 48 | |||
2605 | 49 | // --- Scene graph material --- | ||
2606 | 50 | |||
2607 | 51 | class ShapeMaterial : public QSGMaterial | ||
2608 | 52 | { | ||
2609 | 53 | public: | ||
2610 | 54 | struct Data { | ||
2611 | 55 | enum { | ||
2612 | 56 | Textured = (1 << 0), | ||
2613 | 57 | HorizontallyRepeated = (1 << 1), | ||
2614 | 58 | VerticallyRepeated = (1 << 2), | ||
2615 | 59 | Repeated = (HorizontallyRepeated | VerticallyRepeated) | ||
2616 | 60 | }; | ||
2617 | 61 | QSGTexture* shapeTexture; | ||
2618 | 62 | QSGTextureProvider* sourceTextureProvider; | ||
2619 | 63 | quint8 sourceOpacity; | ||
2620 | 64 | quint8 shapeTextureFiltering; | ||
2621 | 65 | quint8 flags; | ||
2622 | 66 | }; | ||
2623 | 67 | |||
2624 | 68 | ShapeMaterial(); | ||
2625 | 69 | virtual QSGMaterialType* type() const; | ||
2626 | 70 | virtual QSGMaterialShader* createShader() const; | ||
2627 | 71 | virtual int compare(const QSGMaterial* other) const; | ||
2628 | 72 | const Data* constData() const { return &m_data; } | ||
2629 | 73 | Data* data() { return &m_data; } | ||
2630 | 74 | |||
2631 | 75 | private: | ||
2632 | 76 | Data m_data; | ||
2633 | 77 | }; | ||
2634 | 78 | |||
2635 | 79 | // --- Scene graph node --- | ||
2636 | 80 | |||
2637 | 81 | class ShapeNode : public QSGGeometryNode | ||
2638 | 82 | { | ||
2639 | 83 | public: | ||
2640 | 84 | struct Vertex { | ||
2641 | 85 | float position[2]; | ||
2642 | 86 | float shapeCoordinate[2]; | ||
2643 | 87 | float sourceCoordinate[4]; | ||
2644 | 88 | quint32 backgroundColor; | ||
2645 | 89 | }; | ||
2646 | 90 | |||
2647 | 91 | static const int indexCount = 28; | ||
2648 | 92 | static const int indexType = GL_UNSIGNED_SHORT; | ||
2649 | 93 | static const int indexTypeSize = sizeof(unsigned short); | ||
2650 | 94 | static const int vertexCount = 16; | ||
2651 | 95 | static const QSGGeometry::DataPattern indexDataPattern = QSGGeometry::StaticPattern; | ||
2652 | 96 | static const QSGGeometry::DataPattern vertexDataPattern = QSGGeometry::AlwaysUploadPattern; | ||
2653 | 97 | static const GLenum drawingMode = GL_TRIANGLE_STRIP; | ||
2654 | 98 | static const unsigned short* indices(); | ||
2655 | 99 | static const QSGGeometry::AttributeSet& attributeSet(); | ||
2656 | 100 | |||
2657 | 101 | ShapeNode(); | ||
2658 | 102 | ShapeMaterial* material() { return &m_material; } | ||
2659 | 103 | QSGGeometry* geometry() { return &m_geometry; } | ||
2660 | 104 | |||
2661 | 105 | private: | ||
2662 | 106 | ShapeMaterial m_material; | ||
2663 | 107 | QSGGeometry m_geometry; | ||
2664 | 108 | }; | ||
2665 | 109 | |||
2666 | 110 | // --- QtQuick item --- | ||
2667 | 111 | |||
2668 | 112 | class UCUbuntuShape : public QQuickItem | ||
2669 | 31 | { | 113 | { |
2670 | 32 | Q_OBJECT | 114 | Q_OBJECT |
2671 | 115 | |||
2672 | 116 | // Shape properties. | ||
2673 | 117 | Q_PROPERTY(QString radius READ radius WRITE setRadius NOTIFY radiusChanged) | ||
2674 | 118 | Q_PROPERTY(QString borderSource READ borderSource WRITE setBorderSource | ||
2675 | 119 | NOTIFY borderSourceChanged) | ||
2676 | 120 | |||
2677 | 121 | // Source properties. | ||
2678 | 122 | Q_ENUMS(FillMode) | ||
2679 | 123 | Q_ENUMS(WrapMode) | ||
2680 | 33 | Q_ENUMS(HAlignment) | 124 | Q_ENUMS(HAlignment) |
2681 | 34 | Q_ENUMS(VAlignment) | 125 | Q_ENUMS(VAlignment) |
2682 | 126 | Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged REVISION 1) | ||
2683 | 127 | Q_PROPERTY(float sourceOpacity READ sourceOpacity WRITE setSourceOpacity | ||
2684 | 128 | NOTIFY sourceOpacityChanged REVISION 1) | ||
2685 | 129 | Q_PROPERTY(FillMode sourceFillMode READ sourceFillMode WRITE setSourceFillMode | ||
2686 | 130 | NOTIFY sourceFillModeChanged REVISION 1) | ||
2687 | 131 | Q_PROPERTY(WrapMode sourceHorizontalWrapMode READ sourceHorizontalWrapMode | ||
2688 | 132 | WRITE setSourceHorizontalWrapMode NOTIFY sourceHorizontalWrapModeChanged REVISION 1) | ||
2689 | 133 | Q_PROPERTY(WrapMode sourceVerticalWrapMode READ sourceVerticalWrapMode | ||
2690 | 134 | WRITE setSourceVerticalWrapMode NOTIFY sourceVerticalWrapModeChanged REVISION 1) | ||
2691 | 135 | Q_PROPERTY(HAlignment sourceHorizontalAlignment READ sourceHorizontalAlignment | ||
2692 | 136 | WRITE setSourceHorizontalAlignment NOTIFY sourceHorizontalAlignmentChanged | ||
2693 | 137 | REVISION 1) | ||
2694 | 138 | Q_PROPERTY(VAlignment sourceVerticalAlignment READ sourceVerticalAlignment | ||
2695 | 139 | WRITE setSourceVerticalAlignment NOTIFY sourceVerticalAlignmentChanged REVISION 1) | ||
2696 | 140 | Q_PROPERTY(QVector2D sourceTranslation READ sourceTranslation WRITE setSourceTranslation | ||
2697 | 141 | NOTIFY sourceTranslationChanged REVISION 1) | ||
2698 | 142 | Q_PROPERTY(QVector2D sourceScale READ sourceScale WRITE setSourceScale | ||
2699 | 143 | NOTIFY sourceScaleChanged REVISION 1) | ||
2700 | 144 | |||
2701 | 145 | // Background properties. | ||
2702 | 146 | Q_ENUMS(BackgroundMode) | ||
2703 | 147 | Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor | ||
2704 | 148 | NOTIFY backgroundColorChanged REVISION 1) | ||
2705 | 149 | Q_PROPERTY(QColor secondaryBackgroundColor READ secondaryBackgroundColor | ||
2706 | 150 | WRITE setSecondaryBackgroundColor NOTIFY secondaryBackgroundColorChanged REVISION 1) | ||
2707 | 151 | Q_PROPERTY(BackgroundMode backgroundMode READ backgroundMode WRITE setBackgroundMode | ||
2708 | 152 | NOTIFY backgroundModeChanged REVISION 1) | ||
2709 | 153 | |||
2710 | 154 | // Deprecated properties. | ||
2711 | 35 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) | 155 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) |
2712 | 36 | Q_PROPERTY(QColor gradientColor READ gradientColor WRITE setGradientColor | 156 | Q_PROPERTY(QColor gradientColor READ gradientColor WRITE setGradientColor |
2713 | 37 | NOTIFY gradientColorChanged) | 157 | NOTIFY gradientColorChanged) |
2714 | 38 | Q_PROPERTY(QString radius READ radius WRITE setRadius NOTIFY radiusChanged) | ||
2715 | 39 | Q_PROPERTY(QVariant image READ image WRITE setImage NOTIFY imageChanged) | 158 | Q_PROPERTY(QVariant image READ image WRITE setImage NOTIFY imageChanged) |
2716 | 40 | Q_PROPERTY(bool stretched READ stretched WRITE setStretched NOTIFY stretchedChanged) | 159 | Q_PROPERTY(bool stretched READ stretched WRITE setStretched NOTIFY stretchedChanged) |
2720 | 41 | Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged) | 160 | Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment |
2721 | 42 | Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged) | 161 | NOTIFY horizontalAlignmentChanged) |
2722 | 43 | Q_PROPERTY(QString borderSource READ borderSource WRITE setBorderSource NOTIFY borderSourceChanged) | 162 | Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment |
2723 | 163 | NOTIFY verticalAlignmentChanged) | ||
2724 | 44 | 164 | ||
2725 | 45 | public: | 165 | public: |
2727 | 46 | ShapeItem(QQuickItem* parent=0); | 166 | UCUbuntuShape(QQuickItem* parent=0); |
2728 | 47 | 167 | ||
2731 | 48 | enum Radius { SmallRadius, MediumRadius }; | 168 | enum BackgroundMode { SolidColor = 0, VerticalGradient = 1 }; |
2730 | 49 | enum Border { RawBorder, IdleBorder, PressedBorder }; | ||
2732 | 50 | enum HAlignment { AlignLeft = 0, AlignHCenter = 1, AlignRight = 2 }; | 169 | enum HAlignment { AlignLeft = 0, AlignHCenter = 1, AlignRight = 2 }; |
2733 | 51 | enum VAlignment { AlignTop = 0, AlignVCenter = 1, AlignBottom = 2 }; | 170 | enum VAlignment { AlignTop = 0, AlignVCenter = 1, AlignBottom = 2 }; |
2734 | 171 | enum FillMode { Stretch = 0, PreserveAspectFit = 1, PreserveAspectCrop = 2, Pad = 3 }; | ||
2735 | 172 | enum WrapMode { Transparent = 0, Repeat = 1 }; | ||
2736 | 52 | 173 | ||
2742 | 53 | QColor color() const { return color_; } | 174 | QString radius() const { return (m_radius == SmallRadius) ? "small" : "medium"; } |
2738 | 54 | void setColor(const QColor& color); | ||
2739 | 55 | QColor gradientColor() const { return gradientColor_; } | ||
2740 | 56 | void setGradientColor(const QColor& gradientColor); | ||
2741 | 57 | QString radius() const { return radiusString_; } | ||
2743 | 58 | void setRadius(const QString& radius); | 175 | void setRadius(const QString& radius); |
2745 | 59 | QString borderSource() const { return borderSource_; } | 176 | QString borderSource() const { |
2746 | 177 | return (m_border == IdleBorder) ? "radius_idle.sci" : | ||
2747 | 178 | ((m_border == PressedBorder) ? "radius_pressed.sci" : ""); } | ||
2748 | 60 | void setBorderSource(const QString& borderSource); | 179 | void setBorderSource(const QString& borderSource); |
2750 | 61 | QVariant image() const { return QVariant::fromValue(image_); } | 180 | |
2751 | 181 | QVariant source() const { | ||
2752 | 182 | return QVariant::fromValue((m_flags & SourceApiSet) ? m_source : NULL); } | ||
2753 | 183 | void setSource(const QVariant& source); | ||
2754 | 184 | float sourceOpacity() const { return m_sourceOpacity / static_cast<float>(0xff); } | ||
2755 | 185 | void setSourceOpacity(float sourceOpacity); | ||
2756 | 186 | FillMode sourceFillMode() const { return m_sourceFillMode; } | ||
2757 | 187 | void setSourceFillMode(FillMode sourceFillMode); | ||
2758 | 188 | WrapMode sourceHorizontalWrapMode() const { return m_sourceHorizontalWrapMode; } | ||
2759 | 189 | void setSourceHorizontalWrapMode(WrapMode sourceHorizontalWrapMode); | ||
2760 | 190 | WrapMode sourceVerticalWrapMode() const { return m_sourceVerticalWrapMode; } | ||
2761 | 191 | void setSourceVerticalWrapMode(WrapMode sourceVerticalWrapMode); | ||
2762 | 192 | HAlignment sourceHorizontalAlignment() const { return m_sourceHorizontalAlignment; } | ||
2763 | 193 | void setSourceHorizontalAlignment(HAlignment sourceHorizontalAlignment); | ||
2764 | 194 | VAlignment sourceVerticalAlignment() const { return m_sourceVerticalAlignment; } | ||
2765 | 195 | void setSourceVerticalAlignment(VAlignment sourceVerticalAlignment); | ||
2766 | 196 | QVector2D sourceTranslation() const { return m_sourceTranslation; } | ||
2767 | 197 | void setSourceTranslation(const QVector2D& sourceTranslation); | ||
2768 | 198 | QVector2D sourceScale() const { return m_sourceScale; } | ||
2769 | 199 | void setSourceScale(const QVector2D& sourceScale); | ||
2770 | 200 | QColor backgroundColor() const { | ||
2771 | 201 | return (m_flags & BackgroundApiSet) ? | ||
2772 | 202 | QColor(qRed(m_backgroundColor), qGreen(m_backgroundColor), qBlue(m_backgroundColor), | ||
2773 | 203 | qAlpha(m_backgroundColor)) : | ||
2774 | 204 | QColor(0, 0, 0, 0); } | ||
2775 | 205 | void setBackgroundColor(const QColor& backgroundColor); | ||
2776 | 206 | QColor secondaryBackgroundColor() const { | ||
2777 | 207 | return (m_flags & BackgroundApiSet) ? | ||
2778 | 208 | QColor(qRed(m_secondaryBackgroundColor), qGreen(m_secondaryBackgroundColor), | ||
2779 | 209 | qBlue(m_secondaryBackgroundColor), qAlpha(m_secondaryBackgroundColor)) : | ||
2780 | 210 | QColor(0, 0, 0, 0); } | ||
2781 | 211 | void setSecondaryBackgroundColor(const QColor& secondaryBackgroundColor); | ||
2782 | 212 | BackgroundMode backgroundMode() const { return m_backgroundMode; } | ||
2783 | 213 | void setBackgroundMode(BackgroundMode backgroundMode); | ||
2784 | 214 | |||
2785 | 215 | QColor color() const { | ||
2786 | 216 | return (m_flags & BackgroundApiSet) ? | ||
2787 | 217 | QColor(0, 0, 0, 0) : | ||
2788 | 218 | QColor(qRed(m_backgroundColor), qGreen(m_backgroundColor), qBlue(m_backgroundColor), | ||
2789 | 219 | qAlpha(m_backgroundColor)); } | ||
2790 | 220 | void setColor(const QColor& color); | ||
2791 | 221 | QColor gradientColor() const { | ||
2792 | 222 | return (m_flags & BackgroundApiSet) ? | ||
2793 | 223 | QColor(0, 0, 0, 0) : | ||
2794 | 224 | QColor(qRed(m_secondaryBackgroundColor), qGreen(m_secondaryBackgroundColor), | ||
2795 | 225 | qBlue(m_secondaryBackgroundColor), qAlpha(m_secondaryBackgroundColor)); } | ||
2796 | 226 | void setGradientColor(const QColor& gradientColor); | ||
2797 | 227 | QVariant image() const { | ||
2798 | 228 | return QVariant::fromValue((m_flags & SourceApiSet) ? NULL : m_source); } | ||
2799 | 62 | void setImage(const QVariant& image); | 229 | void setImage(const QVariant& image); |
2801 | 63 | bool stretched() const { return stretched_; } | 230 | bool stretched() const { return !!(m_flags & Stretched); } |
2802 | 64 | void setStretched(bool stretched); | 231 | void setStretched(bool stretched); |
2804 | 65 | HAlignment horizontalAlignment() const { return hAlignment_; } | 232 | HAlignment horizontalAlignment() const { return m_imageHorizontalAlignment; } |
2805 | 66 | void setHorizontalAlignment(HAlignment horizontalAlignment); | 233 | void setHorizontalAlignment(HAlignment horizontalAlignment); |
2807 | 67 | VAlignment verticalAlignment() const { return vAlignment_; } | 234 | VAlignment verticalAlignment() const { return m_imageVerticalAlignment; } |
2808 | 68 | void setVerticalAlignment(VAlignment verticalAlignment); | 235 | void setVerticalAlignment(VAlignment verticalAlignment); |
2809 | 69 | Q_SLOT void gridUnitChanged(); | ||
2810 | 70 | 236 | ||
2811 | 71 | Q_SIGNALS: | 237 | Q_SIGNALS: |
2812 | 238 | void radiusChanged(); | ||
2813 | 239 | void borderSourceChanged(); | ||
2814 | 240 | |||
2815 | 241 | Q_REVISION(1) void sourceChanged(); | ||
2816 | 242 | Q_REVISION(1) void sourceOpacityChanged(); | ||
2817 | 243 | Q_REVISION(1) void sourceFillModeChanged(); | ||
2818 | 244 | Q_REVISION(1) void sourceHorizontalWrapModeChanged(); | ||
2819 | 245 | Q_REVISION(1) void sourceVerticalWrapModeChanged(); | ||
2820 | 246 | Q_REVISION(1) void sourceHorizontalAlignmentChanged(); | ||
2821 | 247 | Q_REVISION(1) void sourceVerticalAlignmentChanged(); | ||
2822 | 248 | Q_REVISION(1) void sourceTranslationChanged(); | ||
2823 | 249 | Q_REVISION(1) void sourceScaleChanged(); | ||
2824 | 250 | |||
2825 | 251 | Q_REVISION(1) void backgroundColorChanged(); | ||
2826 | 252 | Q_REVISION(1) void secondaryBackgroundColorChanged(); | ||
2827 | 253 | Q_REVISION(1) void backgroundModeChanged(); | ||
2828 | 254 | |||
2829 | 72 | void colorChanged(); | 255 | void colorChanged(); |
2830 | 73 | void gradientColorChanged(); | 256 | void gradientColorChanged(); |
2831 | 74 | void radiusChanged(); | ||
2832 | 75 | void borderChanged(); | ||
2833 | 76 | void imageChanged(); | 257 | void imageChanged(); |
2834 | 77 | void stretchedChanged(); | 258 | void stretchedChanged(); |
2835 | 78 | void horizontalAlignmentChanged(); | 259 | void horizontalAlignmentChanged(); |
2836 | 79 | void verticalAlignmentChanged(); | 260 | void verticalAlignmentChanged(); |
2837 | 80 | void borderSourceChanged(); | ||
2838 | 81 | 261 | ||
2839 | 82 | protected: | 262 | protected: |
2840 | 263 | virtual QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data); | ||
2841 | 83 | virtual void geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry); | 264 | virtual void geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry); |
2843 | 84 | virtual QSGNode* updatePaintNode(QSGNode*, UpdatePaintNodeData*); | 265 | |
2844 | 266 | // Virtual functions for extended shapes. | ||
2845 | 267 | virtual QSGNode* createSceneGraphNode() const; | ||
2846 | 268 | virtual void updateMaterial( | ||
2847 | 269 | QSGNode* node, QSGTexture* shapeTexture, QSGTexture::Filtering shapeTextureFiltering, | ||
2848 | 270 | QSGTexture* sourceTexture); | ||
2849 | 271 | virtual void updateGeometry( | ||
2850 | 272 | QSGNode* node, float width, float height, float radius, const float shapeCoordinate[][2], | ||
2851 | 273 | const QVector4D& sourceCoordTransform, const QVector4D& sourceMaskTransform, | ||
2852 | 274 | const quint32 backgroundColor[4]); | ||
2853 | 275 | |||
2854 | 276 | private Q_SLOTS: | ||
2855 | 277 | void _q_imagePropertiesChanged(); | ||
2856 | 278 | void _q_openglContextDestroyed(); | ||
2857 | 279 | void _q_gridUnitChanged(); | ||
2858 | 280 | void _q_providerDestroyed(QObject* object=0); | ||
2859 | 281 | void _q_textureChanged(); | ||
2860 | 85 | 282 | ||
2861 | 86 | private: | 283 | private: |
2862 | 87 | void updateFromImageProperties(QQuickItem* image); | 284 | void updateFromImageProperties(QQuickItem* image); |
2865 | 88 | void connectToPropertyChange(QObject* sender, const char* property, | 285 | void connectToPropertyChange( |
2866 | 89 | QObject* receiver, const char* slot); | 286 | QObject* sender, const char* property, QObject* receiver, const char* slot); |
2867 | 90 | void connectToImageProperties(QQuickItem* image); | 287 | void connectToImageProperties(QQuickItem* image); |
3020 | 91 | 288 | void dropColorSupport(); | |
3021 | 92 | private Q_SLOTS: | 289 | void dropImageSupport(); |
3022 | 93 | void onImagePropertiesChanged(); | 290 | void updateSourceTransform( |
3023 | 94 | void onOpenglContextDestroyed(); | 291 | float itemWidth, float itemHeight, FillMode fillMode, HAlignment horizontalAlignment, |
3024 | 95 | void providerDestroyed(QObject* object=0); | 292 | VAlignment verticalAlignment, const QSize& textureSize); |
3025 | 96 | 293 | ||
3026 | 97 | private: | 294 | enum Radius { SmallRadius, MediumRadius }; |
3027 | 98 | struct TextureHandles { | 295 | enum Border { RawBorder, IdleBorder, PressedBorder }; |
3028 | 99 | TextureHandles(): high(0), low(0) {} | 296 | enum { |
3029 | 100 | QSGTexture* high; | 297 | GradientColorSet = (1 << 0), |
3030 | 101 | QSGTexture* low; | 298 | Stretched = (1 << 1), |
3031 | 102 | }; | 299 | BackgroundApiSet = (1 << 2), |
3032 | 103 | 300 | SourceApiSet = (1 << 3), | |
3033 | 104 | QSGTextureProvider* provider_; | 301 | DirtySourceTransform = (1 << 4) |
3034 | 105 | QColor color_; | 302 | }; |
3035 | 106 | QColor gradientColor_; | 303 | |
3036 | 107 | bool gradientColorSet_; | 304 | QQuickItem* m_source; |
3037 | 108 | QString radiusString_; | 305 | QSGTextureProvider* m_sourceTextureProvider; |
3038 | 109 | Radius radius_; | 306 | QRgb m_backgroundColor; |
3039 | 110 | QString borderSource_; | 307 | QRgb m_secondaryBackgroundColor; |
3040 | 111 | Border border_; | 308 | QVector2D m_sourceScale; |
3041 | 112 | QQuickItem* image_; | 309 | QVector2D m_sourceTranslation; |
3042 | 113 | bool stretched_; | 310 | QVector4D m_sourceTransform; |
3043 | 114 | HAlignment hAlignment_; | 311 | Radius m_radius : 1; |
3044 | 115 | VAlignment vAlignment_; | 312 | Border m_border : 2; |
3045 | 116 | float gridUnit_; | 313 | HAlignment m_imageHorizontalAlignment : 2; |
3046 | 117 | QRectF geometry_; | 314 | VAlignment m_imageVerticalAlignment : 2; |
3047 | 118 | static QHash<QOpenGLContext*, TextureHandles> textures_; | 315 | BackgroundMode m_backgroundMode : 1; |
3048 | 119 | 316 | HAlignment m_sourceHorizontalAlignment : 2; | |
3049 | 120 | Q_DISABLE_COPY(ShapeItem) | 317 | VAlignment m_sourceVerticalAlignment : 2; |
3050 | 121 | }; | 318 | FillMode m_sourceFillMode : 2; |
3051 | 122 | 319 | WrapMode m_sourceHorizontalWrapMode : 1; | |
3052 | 123 | // Scene graph textured material. | 320 | WrapMode m_sourceVerticalWrapMode : 1; |
3053 | 124 | 321 | quint8 m_sourceOpacity; | |
3054 | 125 | class ShapeTexturedMaterial : public QSGMaterial | 322 | quint8 m_flags; |
3055 | 126 | { | 323 | |
3056 | 127 | public: | 324 | Q_DISABLE_COPY(UCUbuntuShape) |
3057 | 128 | ShapeTexturedMaterial(); | 325 | }; |
3058 | 129 | virtual QSGMaterialType* type() const; | 326 | |
3059 | 130 | virtual QSGMaterialShader* createShader() const; | 327 | QML_DECLARE_TYPE(UCUbuntuShape) |
3060 | 131 | virtual int compare(const QSGMaterial* other) const; | 328 | |
3061 | 132 | QSGTextureProvider* imageTextureProvider() const; | 329 | #endif // UCUBUNTUSHAPE_H |
2910 | 133 | void setImage(QQuickItem* image); | ||
2911 | 134 | QSGTexture* shapeTexture() const { return shapeTexture_; } | ||
2912 | 135 | QSGTexture::Filtering filtering() const { return filtering_; } | ||
2913 | 136 | void setShapeTexture(QSGTexture* shapeTexture, bool scaledDown); | ||
2914 | 137 | |||
2915 | 138 | private: | ||
2916 | 139 | QSGTextureProvider* imageTextureProvider_; | ||
2917 | 140 | QSGTexture* shapeTexture_; | ||
2918 | 141 | QSGTexture::Filtering filtering_; | ||
2919 | 142 | }; | ||
2920 | 143 | |||
2921 | 144 | // Scene graph textured material shader. | ||
2922 | 145 | |||
2923 | 146 | class ShapeTexturedShader : public QSGMaterialShader | ||
2924 | 147 | { | ||
2925 | 148 | public: | ||
2926 | 149 | virtual char const* const* attributeNames() const; | ||
2927 | 150 | virtual void initialize(); | ||
2928 | 151 | virtual void updateState( | ||
2929 | 152 | const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect); | ||
2930 | 153 | |||
2931 | 154 | private: | ||
2932 | 155 | virtual const char* vertexShader() const; | ||
2933 | 156 | virtual const char* fragmentShader() const; | ||
2934 | 157 | |||
2935 | 158 | int matrixId_; | ||
2936 | 159 | int opacityId_; | ||
2937 | 160 | QOpenGLFunctions* glFuncs_; | ||
2938 | 161 | }; | ||
2939 | 162 | |||
2940 | 163 | // Scene graph colored material. | ||
2941 | 164 | |||
2942 | 165 | class ShapeColoredMaterial : public QSGMaterial | ||
2943 | 166 | { | ||
2944 | 167 | public: | ||
2945 | 168 | ShapeColoredMaterial(); | ||
2946 | 169 | virtual QSGMaterialType* type() const; | ||
2947 | 170 | virtual QSGMaterialShader* createShader() const; | ||
2948 | 171 | virtual int compare(const QSGMaterial* other) const; | ||
2949 | 172 | const QVector4D& color() const { return color_; } | ||
2950 | 173 | void setColor(const QColor& color); | ||
2951 | 174 | const QVector4D& gradientColor() const { return gradientColor_; } | ||
2952 | 175 | void setGradientColor(const QColor& gradientColor); | ||
2953 | 176 | QSGTexture* shapeTexture() const { return shapeTexture_; } | ||
2954 | 177 | QSGTexture::Filtering filtering() const { return filtering_; } | ||
2955 | 178 | void setShapeTexture(QSGTexture* shapeTexture, bool scaledDown); | ||
2956 | 179 | |||
2957 | 180 | private: | ||
2958 | 181 | QVector4D color_; | ||
2959 | 182 | QVector4D gradientColor_; | ||
2960 | 183 | QSGTexture* shapeTexture_; | ||
2961 | 184 | QSGTexture::Filtering filtering_; | ||
2962 | 185 | }; | ||
2963 | 186 | |||
2964 | 187 | // Scene graph colored material shader. | ||
2965 | 188 | |||
2966 | 189 | class ShapeColoredShader : public QSGMaterialShader | ||
2967 | 190 | { | ||
2968 | 191 | public: | ||
2969 | 192 | virtual char const* const* attributeNames() const; | ||
2970 | 193 | virtual void initialize(); | ||
2971 | 194 | virtual void updateState( | ||
2972 | 195 | const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect); | ||
2973 | 196 | |||
2974 | 197 | private: | ||
2975 | 198 | virtual const char* vertexShader() const; | ||
2976 | 199 | virtual const char* fragmentShader() const; | ||
2977 | 200 | |||
2978 | 201 | int matrixId_; | ||
2979 | 202 | int opacityId_; | ||
2980 | 203 | int colorId_; | ||
2981 | 204 | int gradientColorId_; | ||
2982 | 205 | }; | ||
2983 | 206 | |||
2984 | 207 | // Scene graph node. | ||
2985 | 208 | |||
2986 | 209 | struct TextureData; | ||
2987 | 210 | |||
2988 | 211 | class ShapeNode : public QObject, public QSGGeometryNode | ||
2989 | 212 | { | ||
2990 | 213 | Q_OBJECT | ||
2991 | 214 | |||
2992 | 215 | public: | ||
2993 | 216 | struct Vertex { | ||
2994 | 217 | float position[2]; | ||
2995 | 218 | float shapeCoordinate[2]; | ||
2996 | 219 | float imageCoordinate[2]; | ||
2997 | 220 | float padding[2]; // Ensure a 32 bytes stride. | ||
2998 | 221 | }; | ||
2999 | 222 | enum MaterialType { TexturedMaterial, ColoredMaterial }; | ||
3000 | 223 | |||
3001 | 224 | ShapeNode(ShapeItem* item); | ||
3002 | 225 | ShapeTexturedMaterial* texturedMaterial() { return &texturedMaterial_; } | ||
3003 | 226 | ShapeColoredMaterial* coloredMaterial() { return &coloredMaterial_; } | ||
3004 | 227 | void setVertices(const QRectF& geometry, float radius, QQuickItem* image, bool stretched, | ||
3005 | 228 | ShapeItem::HAlignment hAlignment, ShapeItem::VAlignment vAlignment, | ||
3006 | 229 | float shapeCoordinate[][2]); | ||
3007 | 230 | void setMaterialType(MaterialType material); | ||
3008 | 231 | |||
3009 | 232 | private: | ||
3010 | 233 | ShapeItem* item_; | ||
3011 | 234 | QSGGeometry geometry_; | ||
3012 | 235 | ShapeTexturedMaterial texturedMaterial_; | ||
3013 | 236 | ShapeColoredMaterial coloredMaterial_; | ||
3014 | 237 | MaterialType currentMaterial_; | ||
3015 | 238 | }; | ||
3016 | 239 | |||
3017 | 240 | QML_DECLARE_TYPE(ShapeItem) | ||
3018 | 241 | |||
3019 | 242 | #endif // UBUNTU_COMPONENTS_SHAPE_H | ||
3062 | 243 | 330 | ||
3063 | === renamed file 'modules/Ubuntu/Components/plugin/shapeitemtexture.h' => 'modules/Ubuntu/Components/plugin/ucubuntushapetexture.h' | |||
3064 | --- modules/Ubuntu/Components/plugin/shapeitemtexture.h 2014-03-24 15:24:31 +0000 | |||
3065 | +++ modules/Ubuntu/Components/plugin/ucubuntushapetexture.h 2015-03-02 15:41:23 +0000 | |||
3066 | @@ -1,5 +1,5 @@ | |||
3067 | 1 | /* | 1 | /* |
3069 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright 2013-2014 Canonical Ltd. |
3070 | 3 | * | 3 | * |
3071 | 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
3072 | 5 | * it under the terms of the GNU Lesser General Public License as published by | 5 | * it under the terms of the GNU Lesser General Public License as published by |
3073 | @@ -18,7 +18,7 @@ | |||
3074 | 18 | 18 | ||
3075 | 19 | class QSGTexture; | 19 | class QSGTexture; |
3076 | 20 | 20 | ||
3078 | 21 | struct TextureData { | 21 | struct ShapeTextureData { |
3079 | 22 | const unsigned char* const data; | 22 | const unsigned char* const data; |
3080 | 23 | int width; | 23 | int width; |
3081 | 24 | int height; | 24 | int height; |
3082 | @@ -5158,7 +5158,7 @@ | |||
3083 | 5158 | const float hh = 1.0f / 512.0f; | 5158 | const float hh = 1.0f / 512.0f; |
3084 | 5159 | 5159 | ||
3085 | 5160 | // High resolution shape texture. | 5160 | // High resolution shape texture. |
3087 | 5161 | TextureData shapeTextureHigh __attribute__((aligned(16))) = { | 5161 | ShapeTextureData shapeTextureHigh __attribute__((aligned(16))) = { |
3088 | 5162 | shapeTextureHighData, 256, 128, 4, 32.0f, 64.0f, 18.0f, | 5162 | shapeTextureHighData, 256, 128, 4, 32.0f, 64.0f, 18.0f, |
3089 | 5163 | { | 5163 | { |
3090 | 5164 | { // Medium raw coords. | 5164 | { // Medium raw coords. |
3091 | @@ -6482,7 +6482,7 @@ | |||
3092 | 6482 | const float hl = 1.0f / 256.0f; | 6482 | const float hl = 1.0f / 256.0f; |
3093 | 6483 | 6483 | ||
3094 | 6484 | // Low resolution shape texture. | 6484 | // Low resolution shape texture. |
3096 | 6485 | TextureData shapeTextureLow __attribute__((aligned(16))) = { | 6485 | ShapeTextureData shapeTextureLow __attribute__((aligned(16))) = { |
3097 | 6486 | shapeTextureLowData, 128, 64, 4, 16.0f, 32.0f, 9.0f, | 6486 | shapeTextureLowData, 128, 64, 4, 16.0f, 32.0f, 9.0f, |
3098 | 6487 | { | 6487 | { |
3099 | 6488 | { // Medium raw coords. | 6488 | { // Medium raw coords. |
3100 | 6489 | 6489 | ||
3101 | === added directory 'tests/resources/ubuntushape' | |||
3102 | === added file 'tests/resources/ubuntushape/UbuntuShapeTest.qml' | |||
3103 | --- tests/resources/ubuntushape/UbuntuShapeTest.qml 1970-01-01 00:00:00 +0000 | |||
3104 | +++ tests/resources/ubuntushape/UbuntuShapeTest.qml 2015-03-02 15:41:23 +0000 | |||
3105 | @@ -0,0 +1,299 @@ | |||
3106 | 1 | /* | ||
3107 | 2 | * Copyright 2015 Canonical Ltd. | ||
3108 | 3 | * | ||
3109 | 4 | * This program is free software; you can redistribute it and/or modify | ||
3110 | 5 | * it under the terms of the GNU Lesser General Public License as published by | ||
3111 | 6 | * the Free Software Foundation; version 3. | ||
3112 | 7 | * | ||
3113 | 8 | * This program is distributed in the hope that it will be useful, | ||
3114 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
3115 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
3116 | 11 | * GNU Lesser General Public License for more details. | ||
3117 | 12 | * | ||
3118 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
3119 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
3120 | 15 | */ | ||
3121 | 16 | |||
3122 | 17 | import QtQuick 2.0 | ||
3123 | 18 | import Ubuntu.Components 1.2 | ||
3124 | 19 | |||
3125 | 20 | Item { | ||
3126 | 21 | id: root | ||
3127 | 22 | width: 1000 | ||
3128 | 23 | height: 600 | ||
3129 | 24 | focus: true | ||
3130 | 25 | |||
3131 | 26 | // Enum to string tables. | ||
3132 | 27 | property variant backgroundModeTable: [ | ||
3133 | 28 | "SolidColor", "VerticalGradient" | ||
3134 | 29 | ] | ||
3135 | 30 | property variant sourceHAlignmentTable: [ | ||
3136 | 31 | "AlignLeft", "AlignHCenter", "AlignRight" | ||
3137 | 32 | ] | ||
3138 | 33 | property variant sourceVAlignmentTable: [ | ||
3139 | 34 | "AlignTop", "AlignVCenter", "AlignBottom" | ||
3140 | 35 | ] | ||
3141 | 36 | property variant sourceFillModeTable: [ | ||
3142 | 37 | "Stretch", "PreserveAspectFit", "PreserveAspectCrop", "Pad" | ||
3143 | 38 | ] | ||
3144 | 39 | property variant wrapModeTable: [ | ||
3145 | 40 | "Transparent", "Repeat" | ||
3146 | 41 | ] | ||
3147 | 42 | property variant imageFillModeTable: [ | ||
3148 | 43 | "Stretch", "PreserveAspectFit", "PreserveAspectCrop", "Tile", "TileVertically", | ||
3149 | 44 | "TileHorizontally", "Pad" | ||
3150 | 45 | ] | ||
3151 | 46 | |||
3152 | 47 | // Zoom properties. | ||
3153 | 48 | property variant translation: Qt.point(0.0, 0.0) | ||
3154 | 49 | property real scaleBase: 1.1 | ||
3155 | 50 | property real scaleExponent: 0.0 | ||
3156 | 51 | property real minScaleExponent: 0.0 | ||
3157 | 52 | property real maxScaleExponent: 48.317715856 // Logarithm of 100 to base 1.1 (scaleBase). | ||
3158 | 53 | property real scaleFactor: 1.0 | ||
3159 | 54 | property real scale: 1.0 | ||
3160 | 55 | |||
3161 | 56 | // Overlay text properties. French keymapping... :) | ||
3162 | 57 | property string textOverlayString: | ||
3163 | 58 | "Zoom (scroll): x " + root.scaleFactor.toFixed(1) + "\n\n" + | ||
3164 | 59 | "Background colors (a/z): " + shape.backgroundColor + ", " + shape.secondaryBackgroundColor + "\n" + | ||
3165 | 60 | "Background mode (e): " + root.backgroundModeTable[shape.backgroundMode] + "\n\n" + | ||
3166 | 61 | "Source (o): " + shape.source + "\n" + | ||
3167 | 62 | "Source opacity (p): " + shape.sourceOpacity.toFixed(2) + "\n" + | ||
3168 | 63 | "Source fill (q): " + root.sourceFillModeTable[shape.sourceFillMode] + "\n" + | ||
3169 | 64 | "Source hwrap (s): " + root.wrapModeTable[shape.sourceHorizontalWrapMode] + "\n" + | ||
3170 | 65 | "Source vwrap (d): " + root.wrapModeTable[shape.sourceVerticalWrapMode] + "\n" + | ||
3171 | 66 | "Source halign (f): " + root.sourceHAlignmentTable[shape.sourceHorizontalAlignment] + "\n" + | ||
3172 | 67 | "Source valign (g): " + root.sourceVAlignmentTable[shape.sourceVerticalAlignment] + "\n" + | ||
3173 | 68 | "Source translation (h/j): " + shape.sourceTranslation.x.toFixed(2) + ", " + shape.sourceTranslation.y.toFixed(2) + "\n" + | ||
3174 | 69 | "Source scale (k/l): " + shape.sourceScale.x.toFixed(2) + ", " + shape.sourceScale.y.toFixed(2) + "\n\n" + | ||
3175 | 70 | "Image (deprecated) (m): " + shape.image + "\n" + | ||
3176 | 71 | "Image fill (w): " + root.imageFillModeTable[img1.fillMode] + "\n" + | ||
3177 | 72 | "Image halign (x): " + img1.horizontalAlignment + "\n" + | ||
3178 | 73 | "Image valign (c): " + img1.verticalAlignment + "\n\n" + | ||
3179 | 74 | "Radius (v): " + "\"" + shape.radius + "\"\n" + | ||
3180 | 75 | "Border (b): " + "\"" + shape.borderSource + "\"\n\n" + | ||
3181 | 76 | "Colors (deprecated) (n/,): " + shape.color + ", " + shape.gradientColor | ||
3182 | 77 | |||
3183 | 78 | // Main scene. | ||
3184 | 79 | Item { | ||
3185 | 80 | id: scene | ||
3186 | 81 | anchors.fill: parent | ||
3187 | 82 | |||
3188 | 83 | Image { | ||
3189 | 84 | id: background | ||
3190 | 85 | anchors.fill: parent | ||
3191 | 86 | source: "background.jpg" | ||
3192 | 87 | fillMode: Image.Tile | ||
3193 | 88 | } | ||
3194 | 89 | |||
3195 | 90 | // Put the UbuntuShape source image in the middle of a texture atlas. We use img1. | ||
3196 | 91 | Image { id: img1; visible: false; source: "img1.png"; } | ||
3197 | 92 | Image { id: img2; visible: false; source: "img2.png"; } | ||
3198 | 93 | Image { id: img3; visible: false; source: "img3.png"; } | ||
3199 | 94 | Image { id: img4; visible: false; source: "img4.png"; } | ||
3200 | 95 | |||
3201 | 96 | UbuntuShape { | ||
3202 | 97 | id: shape | ||
3203 | 98 | anchors.fill: parent | ||
3204 | 99 | anchors.leftMargin: 400 | ||
3205 | 100 | anchors.rightMargin: 100 | ||
3206 | 101 | anchors.topMargin: 100 | ||
3207 | 102 | anchors.bottomMargin: 100 | ||
3208 | 103 | } | ||
3209 | 104 | } | ||
3210 | 105 | |||
3211 | 106 | // Zoom support. | ||
3212 | 107 | ShaderEffectSource { | ||
3213 | 108 | id: shaderEffectSource | ||
3214 | 109 | anchors.fill: scene | ||
3215 | 110 | sourceItem: scene | ||
3216 | 111 | hideSource: true | ||
3217 | 112 | visible: false | ||
3218 | 113 | smooth: false | ||
3219 | 114 | } | ||
3220 | 115 | ShaderEffect { | ||
3221 | 116 | anchors.fill: scene | ||
3222 | 117 | property variant tex: shaderEffectSource | ||
3223 | 118 | property variant translation: root.translation | ||
3224 | 119 | property real scaleFactor: root.scale | ||
3225 | 120 | vertexShader: " | ||
3226 | 121 | uniform mat4 qt_Matrix; | ||
3227 | 122 | uniform float scaleFactor; | ||
3228 | 123 | uniform vec2 translation; | ||
3229 | 124 | attribute vec4 qt_Vertex; | ||
3230 | 125 | attribute vec2 qt_MultiTexCoord0; | ||
3231 | 126 | varying vec2 texCoord; | ||
3232 | 127 | void main() { | ||
3233 | 128 | texCoord = vec2(scaleFactor) * qt_MultiTexCoord0 + translation; | ||
3234 | 129 | gl_Position = qt_Matrix * qt_Vertex; | ||
3235 | 130 | }" | ||
3236 | 131 | fragmentShader: " | ||
3237 | 132 | uniform sampler2D tex; | ||
3238 | 133 | uniform float qt_Opacity; | ||
3239 | 134 | varying vec2 texCoord; | ||
3240 | 135 | void main() { | ||
3241 | 136 | gl_FragColor = texture2D(tex, texCoord) * qt_Opacity; | ||
3242 | 137 | }" | ||
3243 | 138 | } | ||
3244 | 139 | |||
3245 | 140 | // Text overlay. | ||
3246 | 141 | Text { | ||
3247 | 142 | id: textOverlay | ||
3248 | 143 | width:200 | ||
3249 | 144 | anchors.top: parent.top | ||
3250 | 145 | anchors.topMargin: 10 | ||
3251 | 146 | anchors.left: parent.left | ||
3252 | 147 | anchors.leftMargin: 10 | ||
3253 | 148 | font.family: "Ubuntu Mono" | ||
3254 | 149 | font.pixelSize: 14 | ||
3255 | 150 | font.weight: Font.Bold | ||
3256 | 151 | color: "black" | ||
3257 | 152 | text: textOverlayString | ||
3258 | 153 | } | ||
3259 | 154 | |||
3260 | 155 | // Mouse handling. | ||
3261 | 156 | MouseArea { | ||
3262 | 157 | id: mouseArea | ||
3263 | 158 | anchors.fill: parent | ||
3264 | 159 | acceptedButtons: Qt.LeftButton | ||
3265 | 160 | hoverEnabled: true | ||
3266 | 161 | |||
3267 | 162 | property real lastX: 0.0 | ||
3268 | 163 | property real lastY: 0.0 | ||
3269 | 164 | |||
3270 | 165 | onPressed: { | ||
3271 | 166 | if (pressedButtons & Qt.LeftButton) { | ||
3272 | 167 | lastX = mouseX; | ||
3273 | 168 | lastY = mouseY; | ||
3274 | 169 | } | ||
3275 | 170 | } | ||
3276 | 171 | onPositionChanged: { | ||
3277 | 172 | if (pressedButtons & Qt.LeftButton) { | ||
3278 | 173 | var tx = root.translation.x; | ||
3279 | 174 | var ty = root.translation.y; | ||
3280 | 175 | var sx = root.scale / root.width; | ||
3281 | 176 | var sy = root.scale / root.height; | ||
3282 | 177 | var x = mouseX - lastX; | ||
3283 | 178 | var y = mouseY - lastY; | ||
3284 | 179 | root.translation = Qt.point(Math.max(0.0, Math.min(1.0 - root.scale, tx - sx * x)), | ||
3285 | 180 | Math.max(0.0, Math.min(1.0 - root.scale, ty - sy * y))); | ||
3286 | 181 | lastX = mouseX; | ||
3287 | 182 | lastY = mouseY; | ||
3288 | 183 | } | ||
3289 | 184 | } | ||
3290 | 185 | onWheel: { | ||
3291 | 186 | root.scaleExponent = Math.max(minScaleExponent, Math.min(maxScaleExponent, | ||
3292 | 187 | root.scaleExponent + (wheel.angleDelta.y < 0.0 ? -1.0 : 1.0))); | ||
3293 | 188 | root.scaleFactor = Math.pow(root.scaleBase, root.scaleExponent); | ||
3294 | 189 | var oldScale = root.scale; | ||
3295 | 190 | root.scale = 1.0 / root.scaleFactor; | ||
3296 | 191 | var s = oldScale - root.scale; | ||
3297 | 192 | var tx = root.translation.x; | ||
3298 | 193 | var ty = root.translation.y; | ||
3299 | 194 | var x = mouseX / root.width; | ||
3300 | 195 | var y = mouseY / root.height; | ||
3301 | 196 | root.translation = Qt.point(Math.max(0.0, Math.min(1.0 - root.scale, tx + s * x)), | ||
3302 | 197 | Math.max(0.0, Math.min(1.0 - root.scale, ty + s * y))); | ||
3303 | 198 | } | ||
3304 | 199 | } | ||
3305 | 200 | |||
3306 | 201 | // Keyboard handling. | ||
3307 | 202 | Keys.onPressed: { | ||
3308 | 203 | var shift = Qt.ShiftModifier; | ||
3309 | 204 | |||
3310 | 205 | // Background. | ||
3311 | 206 | if (event.key == Qt.Key_A) { | ||
3312 | 207 | shape.backgroundColor = Qt.rgba( | ||
3313 | 208 | Math.random(), Math.random(), Math.random(), Math.random()); | ||
3314 | 209 | } else if (event.key == Qt.Key_Z) { | ||
3315 | 210 | shape.secondaryBackgroundColor = Qt.rgba( | ||
3316 | 211 | Math.random(), Math.random(), Math.random(), Math.random()); | ||
3317 | 212 | } else if (event.key == Qt.Key_E) { | ||
3318 | 213 | shape.backgroundMode = (shape.backgroundMode + 1) % 3; | ||
3319 | 214 | |||
3320 | 215 | // Source. | ||
3321 | 216 | } else if (event.key == Qt.Key_O) { | ||
3322 | 217 | if (shape.source == null) { | ||
3323 | 218 | shape.source = img1; | ||
3324 | 219 | } else { | ||
3325 | 220 | shape.source = null; | ||
3326 | 221 | } | ||
3327 | 222 | } else if (event.key == Qt.Key_P) { | ||
3328 | 223 | shape.sourceOpacity = Math.max(0.0, Math.min( | ||
3329 | 224 | 1.0, shape.sourceOpacity + ((event.modifiers & shift) ? 0.01 : -0.01))); | ||
3330 | 225 | } else if (event.key == Qt.Key_Q) { | ||
3331 | 226 | shape.sourceFillMode = (shape.sourceFillMode + 1) % 4; | ||
3332 | 227 | } else if (event.key == Qt.Key_S) { | ||
3333 | 228 | shape.sourceHorizontalWrapMode = (shape.sourceHorizontalWrapMode + 1) % 3; | ||
3334 | 229 | } else if (event.key == Qt.Key_D) { | ||
3335 | 230 | shape.sourceVerticalWrapMode = (shape.sourceVerticalWrapMode + 1) % 3; | ||
3336 | 231 | } else if (event.key == Qt.Key_F) { | ||
3337 | 232 | shape.sourceHorizontalAlignment = (shape.sourceHorizontalAlignment + 1) % 3; | ||
3338 | 233 | } else if (event.key == Qt.Key_G) { | ||
3339 | 234 | shape.sourceVerticalAlignment = (shape.sourceVerticalAlignment + 1) % 3; | ||
3340 | 235 | } else if (event.key == Qt.Key_H) { | ||
3341 | 236 | shape.sourceTranslation = Qt.vector2d( | ||
3342 | 237 | shape.sourceTranslation.x + ((event.modifiers & shift) ? 0.01 : -0.01), | ||
3343 | 238 | shape.sourceTranslation.y); | ||
3344 | 239 | } else if (event.key == Qt.Key_J) { | ||
3345 | 240 | shape.sourceTranslation = Qt.vector2d( | ||
3346 | 241 | shape.sourceTranslation.x, | ||
3347 | 242 | shape.sourceTranslation.y + ((event.modifiers & shift) ? 0.01 : -0.01)); | ||
3348 | 243 | } else if (event.key == Qt.Key_K) { | ||
3349 | 244 | shape.sourceScale = Qt.vector2d( | ||
3350 | 245 | shape.sourceScale.x + ((event.modifiers & shift) ? 0.02 : -0.02), | ||
3351 | 246 | shape.sourceScale.y); | ||
3352 | 247 | } else if (event.key == Qt.Key_L) { | ||
3353 | 248 | shape.sourceScale = Qt.vector2d( | ||
3354 | 249 | shape.sourceScale.x, | ||
3355 | 250 | shape.sourceScale.y + ((event.modifiers & shift) ? 0.02 : -0.02)); | ||
3356 | 251 | |||
3357 | 252 | // Image. | ||
3358 | 253 | } else if (event.key == Qt.Key_M) { | ||
3359 | 254 | if (shape.image == null) { | ||
3360 | 255 | shape.image = img1; | ||
3361 | 256 | } else { | ||
3362 | 257 | shape.image = null; | ||
3363 | 258 | } | ||
3364 | 259 | } else if (event.key == Qt.Key_W) { | ||
3365 | 260 | img1.fillMode = (img1.fillMode + 1) % 7; | ||
3366 | 261 | } else if (event.key == Qt.Key_X) { | ||
3367 | 262 | if (img1.horizontalAlignment == Image.AlignLeft) { | ||
3368 | 263 | img1.horizontalAlignment = Image.AlignHCenter; | ||
3369 | 264 | } else if (img1.horizontalAlignment == Image.AlignHCenter) { | ||
3370 | 265 | img1.horizontalAlignment = Image.AlignRight; | ||
3371 | 266 | } else { | ||
3372 | 267 | img1.horizontalAlignment = Image.AlignLeft; | ||
3373 | 268 | } | ||
3374 | 269 | } else if (event.key == Qt.Key_C) { | ||
3375 | 270 | if (img1.verticalAlignment == Image.AlignTop) { | ||
3376 | 271 | img1.verticalAlignment = Image.AlignVCenter; | ||
3377 | 272 | } else if (img1.verticalAlignment == Image.AlignVCenter) { | ||
3378 | 273 | img1.verticalAlignment = Image.AlignBottom; | ||
3379 | 274 | } else { | ||
3380 | 275 | img1.verticalAlignment = Image.AlignTop; | ||
3381 | 276 | } | ||
3382 | 277 | |||
3383 | 278 | // Styling. | ||
3384 | 279 | } else if (event.key == Qt.Key_V) { | ||
3385 | 280 | shape.radius = (shape.radius == "medium") ? "small" : "medium"; | ||
3386 | 281 | } else if (event.key == Qt.Key_B) { | ||
3387 | 282 | if (shape.borderSource == "radius_idle.sci") { | ||
3388 | 283 | shape.borderSource = "radius_pressed.sci"; | ||
3389 | 284 | } else if (shape.borderSource == "radius_pressed.sci") { | ||
3390 | 285 | shape.borderSource = ""; | ||
3391 | 286 | } else { | ||
3392 | 287 | shape.borderSource = "radius_idle.sci"; | ||
3393 | 288 | } | ||
3394 | 289 | |||
3395 | 290 | // Colors. | ||
3396 | 291 | } else if (event.key == Qt.Key_N) { | ||
3397 | 292 | shape.color = Qt.rgba( | ||
3398 | 293 | Math.random(), Math.random(), Math.random(), Math.random()); | ||
3399 | 294 | } else if (event.key == Qt.Key_Comma) { | ||
3400 | 295 | shape.gradientColor = Qt.rgba( | ||
3401 | 296 | Math.random(), Math.random(), Math.random(), Math.random()); | ||
3402 | 297 | } | ||
3403 | 298 | } | ||
3404 | 299 | } | ||
3405 | 0 | 300 | ||
3406 | === added file 'tests/resources/ubuntushape/background.jpg' | |||
3407 | 1 | Binary files tests/resources/ubuntushape/background.jpg 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/background.jpg 2015-03-02 15:41:23 +0000 differ | 301 | Binary files tests/resources/ubuntushape/background.jpg 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/background.jpg 2015-03-02 15:41:23 +0000 differ |
3408 | === added file 'tests/resources/ubuntushape/img1.png' | |||
3409 | 2 | Binary files tests/resources/ubuntushape/img1.png 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/img1.png 2015-03-02 15:41:23 +0000 differ | 302 | Binary files tests/resources/ubuntushape/img1.png 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/img1.png 2015-03-02 15:41:23 +0000 differ |
3410 | === added file 'tests/resources/ubuntushape/img2.png' | |||
3411 | 3 | Binary files tests/resources/ubuntushape/img2.png 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/img2.png 2015-03-02 15:41:23 +0000 differ | 303 | Binary files tests/resources/ubuntushape/img2.png 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/img2.png 2015-03-02 15:41:23 +0000 differ |
3412 | === added file 'tests/resources/ubuntushape/img3.png' | |||
3413 | 4 | Binary files tests/resources/ubuntushape/img3.png 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/img3.png 2015-03-02 15:41:23 +0000 differ | 304 | Binary files tests/resources/ubuntushape/img3.png 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/img3.png 2015-03-02 15:41:23 +0000 differ |
3414 | === added file 'tests/resources/ubuntushape/img4.png' | |||
3415 | 5 | Binary files tests/resources/ubuntushape/img4.png 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/img4.png 2015-03-02 15:41:23 +0000 differ | 305 | Binary files tests/resources/ubuntushape/img4.png 1970-01-01 00:00:00 +0000 and tests/resources/ubuntushape/img4.png 2015-03-02 15:41:23 +0000 differ |
FAILED: Continuous integration, rev:1318 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- ci/1269/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 349/console jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-amd64- ci/2/console jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-armhf- ci/2/console jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-i386- ci/2/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 349/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- sdk-team- ubuntu- ui-toolkit- staging- ci/1269/ rebuild
http://