Merge lp:~loic.molinari/ubuntu-ui-toolkit/uitk-quad into lp:ubuntu-ui-toolkit/staging

Proposed by Loïc Molinari
Status: Work in progress
Proposed branch: lp:~loic.molinari/ubuntu-ui-toolkit/uitk-quad
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 7380 lines (+6275/-617)
51 files modified
src/UbuntuToolkit/UbuntuToolkit.pro (+43/-8)
src/UbuntuToolkit/privates/shaders/color.frag (+7/-0)
src/UbuntuToolkit/privates/shaders/color.vert (+12/-0)
src/UbuntuToolkit/privates/shaders/color_opaque.frag (+6/-0)
src/UbuntuToolkit/privates/shaders/colormask.frag (+10/-0)
src/UbuntuToolkit/privates/shaders/colormask.vert (+15/-0)
src/UbuntuToolkit/privates/shaders/colormask_opaque.frag (+9/-0)
src/UbuntuToolkit/privates/shaders/fillcenterborder.frag (+14/-0)
src/UbuntuToolkit/privates/shaders/fillcenterborder.vert (+18/-0)
src/UbuntuToolkit/privates/shaders/fillcenterborder_opaque.frag (+12/-0)
src/UbuntuToolkit/privates/shaders/fillcentershadow.frag (+16/-0)
src/UbuntuToolkit/privates/shaders/fillcentershadow.vert (+21/-0)
src/UbuntuToolkit/privates/shaders/fillcentershadow_opaque.frag (+14/-0)
src/UbuntuToolkit/privates/shaders/fillcentershadowborder.frag (+22/-0)
src/UbuntuToolkit/privates/shaders/fillcentershadowborder.vert (+27/-0)
src/UbuntuToolkit/privates/shaders/fillcentershadowborder_opaque.frag (+20/-0)
src/UbuntuToolkit/privates/shaders/fillcornersborder.frag (+17/-0)
src/UbuntuToolkit/privates/shaders/fillcornersborder.vert (+21/-0)
src/UbuntuToolkit/privates/shaders/fillcornersborder_opaque.frag (+16/-0)
src/UbuntuToolkit/privates/shaders/fillcornersshadow.frag (+18/-0)
src/UbuntuToolkit/privates/shaders/fillcornersshadow.vert (+24/-0)
src/UbuntuToolkit/privates/shaders/fillcornersshadow_opaque.frag (+17/-0)
src/UbuntuToolkit/privates/shaders/fillcornersshadowborder.frag (+24/-0)
src/UbuntuToolkit/privates/shaders/fillcornersshadowborder.vert (+30/-0)
src/UbuntuToolkit/privates/shaders/fillcornersshadowborder_opaque.frag (+23/-0)
src/UbuntuToolkit/privates/shaders/frame.frag (+10/-28)
src/UbuntuToolkit/privates/shaders/frame.vert (+0/-34)
src/UbuntuToolkit/privates/shaders/texture2.vert (+18/-0)
src/UbuntuToolkit/privates/ucshape.cpp (+434/-0)
src/UbuntuToolkit/privates/ucshape_p.h (+162/-0)
src/UbuntuToolkit/privates/ucshapedropshadownodes.cpp (+175/-0)
src/UbuntuToolkit/privates/ucshapedropshadownodes_p.h (+57/-0)
src/UbuntuToolkit/privates/ucshapefillnodes.cpp (+1431/-0)
src/UbuntuToolkit/privates/ucshapefillnodes_p.h (+999/-0)
src/UbuntuToolkit/privates/ucshapeframenodes.cpp (+392/-326)
src/UbuntuToolkit/privates/ucshapeframenodes_p.h (+67/-78)
src/UbuntuToolkit/privates/ucshaperesources.cpp (+19/-0)
src/UbuntuToolkit/privates/ucshaperesources_p.h (+285/-0)
src/UbuntuToolkit/privates/ucshapetexturefactory.cpp (+728/-0)
src/UbuntuToolkit/privates/ucshapetexturefactory_p.h (+142/-0)
src/UbuntuToolkit/privates/ucshapeutils_p.h (+134/-0)
src/UbuntuToolkit/resources.qrc (+28/-4)
src/UbuntuToolkit/tools/privates/createprivateshapetextures.cpp (+0/-125)
src/UbuntuToolkit/tools/privates/privates.pro (+0/-5)
src/UbuntuToolkit/ubuntutoolkitmodule.cpp (+2/-2)
src/UbuntuToolkit/ucbottomedge.cpp (+1/-0)
src/UbuntuToolkit/ucbottomedge_p.h (+0/-2)
src/UbuntuToolkit/ucbottomedgeregion.cpp (+2/-0)
src/imports/Components/Themes/Ambiance/1.3/FocusShape.qml (+3/-5)
tests/resources/ubuntushape/QuadTest.qml (+549/-0)
tests/resources/ubuntushape/ZoomPan.qml (+181/-0)
To merge this branch: bzr merge lp:~loic.molinari/ubuntu-ui-toolkit/uitk-quad
Reviewer Review Type Date Requested Status
Emanuele Antonio Faraone (community) Approve
Ubuntu SDK team Pending
Review via email: mp+307535@code.launchpad.net

Commit message

Added new nodes and item with fast and dynamic shadow rendering.

Description of the change

Added new nodes and item with fast and dynamic shadow rendering.

To post a comment you must log in.
2130. By Loïc Molinari

Improved test.

2131. By Loïc Molinari

Renamed color to fillColor.

2132. By Loïc Molinari

Removed a bunch of useless casts.

2133. By Loïc Molinari

Removed useless RESTRICT define.

2134. By Loïc Molinari

Added aligned allocs support.

2135. By Loïc Molinari

Simplified texture factory code.

2136. By Loïc Molinari

Cleaned up texture factory.

2137. By Loïc Molinari

Clean up.

2138. By Loïc Molinari

Added inner shadow support.

2139. By Loïc Molinari

Moved fill corners to new resources arch.

2140. By Loïc Molinari

Moved drop shadow to new resources arch.

2141. By Loïc Molinari

Added fill corners shadow.

2142. By Loïc Molinari

Added initial border support.

2143. By Loïc Molinari

Fixed ZoomPan.qml.

2144. By Loïc Molinari

Cleaned up shaders.

2145. By Loïc Molinari

Made a nice Quad tweaker tool.

2146. By Loïc Molinari

Added border support to fill center nodes.

2147. By Loïc Molinari

Merged lp:ubuntu-ui-toolkit/staging.

2148. By Loïc Molinari

Added shadow border support fill corners node.

2149. By Loïc Molinari

Added border support fill corners node.

2150. By Loïc Molinari

Improved quad tdeak colors.

2151. By Loïc Molinari

Fixed Quad Tweak color picking system.

2152. By Loïc Molinari

Fixed and cleaned up mask texture creation when radius=0.

2153. By Loïc Molinari

Reverted to 0 default radius in quad tweak.

2154. By Loïc Molinari

Cleaned up shadow texture creation code.

2155. By Loïc Molinari

Shadow texture fixes.

2156. By Loïc Molinari

Fixed 0 radius and shadow size issues.

2157. By Loïc Molinari

Fixed drop shadow visiblity states.

2158. By Loïc Molinari

Replaced shadow blur with extended box filtering algorithm.

2159. By Loïc Molinari

Cleaned up alignment strategies.

Revision history for this message
Emanuele Antonio Faraone (emanueleant03) :
review: Approve

Unmerged revisions

2159. By Loïc Molinari

Cleaned up alignment strategies.

2158. By Loïc Molinari

Replaced shadow blur with extended box filtering algorithm.

2157. By Loïc Molinari

Fixed drop shadow visiblity states.

2156. By Loïc Molinari

Fixed 0 radius and shadow size issues.

2155. By Loïc Molinari

Shadow texture fixes.

2154. By Loïc Molinari

Cleaned up shadow texture creation code.

2153. By Loïc Molinari

Reverted to 0 default radius in quad tweak.

2152. By Loïc Molinari

Fixed and cleaned up mask texture creation when radius=0.

2151. By Loïc Molinari

Fixed Quad Tweak color picking system.

2150. By Loïc Molinari

Improved quad tdeak colors.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/UbuntuToolkit/UbuntuToolkit.pro'
2--- src/UbuntuToolkit/UbuntuToolkit.pro 2016-11-04 09:37:32 +0000
3+++ src/UbuntuToolkit/UbuntuToolkit.pro 2016-12-14 07:25:05 +0000
4@@ -45,13 +45,19 @@
5 $$PWD/mousetouchadaptor_p.h \
6 $$PWD/mousetouchadaptor_p_p.h \
7 $$PWD/privates/appheaderbase_p.h \
8- $$PWD/privates/frame_p.h \
9 $$PWD/privates/listitemdragarea_p.h \
10 $$PWD/privates/listitemdraghandler_p.h \
11 $$PWD/privates/listitemselection_p.h \
12 $$PWD/privates/listviewextensions_p.h \
13 $$PWD/privates/splitviewhandler_p.h \
14 $$PWD/privates/threelabelsslot_p.h \
15+ $$PWD/privates/ucshape_p.h \
16+ $$PWD/privates/ucshapedropshadownodes_p.h \
17+ $$PWD/privates/ucshapefillnodes_p.h \
18+ $$PWD/privates/ucshapeframenodes_p.h \
19+ $$PWD/privates/ucshaperesources_p.h \
20+ $$PWD/privates/ucshapetexturefactory_p.h \
21+ $$PWD/privates/ucshapeutils_p.h \
22 $$PWD/privates/ucpagewrapper_p.h \
23 $$PWD/privates/ucpagewrapper_p_p.h \
24 $$PWD/privates/ucpagewrapperincubator_p.h \
25@@ -155,7 +161,6 @@
26 $$PWD/menugroup.cpp \
27 $$PWD/mousetouchadaptor.cpp \
28 $$PWD/privates/appheaderbase.cpp \
29- $$PWD/privates/frame.cpp \
30 $$PWD/privates/listitemdragarea.cpp \
31 $$PWD/privates/listitemdraghandler.cpp \
32 $$PWD/privates/listitemexpansion.cpp \
33@@ -163,6 +168,12 @@
34 $$PWD/privates/listviewextensions.cpp \
35 $$PWD/privates/splitviewhandler.cpp \
36 $$PWD/privates/threelabelsslot_p.cpp \
37+ $$PWD/privates/ucshape.cpp \
38+ $$PWD/privates/ucshapedropshadownodes.cpp \
39+ $$PWD/privates/ucshapefillnodes.cpp \
40+ $$PWD/privates/ucshapeframenodes.cpp \
41+ $$PWD/privates/ucshaperesources.cpp \
42+ $$PWD/privates/ucshapetexturefactory.cpp \
43 $$PWD/privates/ucpagewrapper.cpp \
44 $$PWD/privates/ucpagewrapperincubator.cpp \
45 $$PWD/privates/ucscrollbarutils.cpp \
46@@ -231,13 +242,37 @@
47 $$PWD/resources.qrc
48
49 OTHER_FILES += \
50+ $$PWD/privates/shaders/color.frag \
51+ $$PWD/privates/shaders/color.vert \
52+ $$PWD/privates/shaders/color_opaque.frag \
53+ $$PWD/privates/shaders/colormask.frag \
54+ $$PWD/privates/shaders/colormask.vert \
55+ $$PWD/privates/shaders/colormask_opaque.frag \
56+ $$PWD/privates/shaders/fillcenterborder.frag \
57+ $$PWD/privates/shaders/fillcenterborder.vert \
58+ $$PWD/privates/shaders/fillcenterborder_opaque.frag \
59+ $$PWD/privates/shaders/fillcentershadow.frag \
60+ $$PWD/privates/shaders/fillcentershadow.vert \
61+ $$PWD/privates/shaders/fillcentershadow_opaque.frag \
62+ $$PWD/privates/shaders/fillcentershadowborder.frag \
63+ $$PWD/privates/shaders/fillcentershadowborder.vert \
64+ $$PWD/privates/shaders/fillcentershadowborder_opaque.frag \
65+ $$PWD/privates/shaders/fillcornersborder.frag \
66+ $$PWD/privates/shaders/fillcornersborder.vert \
67+ $$PWD/privates/shaders/fillcornersborder_opaque.frag \
68+ $$PWD/privates/shaders/fillcornersshadow.frag \
69+ $$PWD/privates/shaders/fillcornersshadow.vert \
70+ $$PWD/privates/shaders/fillcornersshadow_opaque.frag \
71+ $$PWD/privates/shaders/fillcornersshadowborder.frag \
72+ $$PWD/privates/shaders/fillcornersshadowborder.vert \
73+ $$PWD/privates/shaders/fillcornersshadowborder_opaque.frag \
74+ $$PWD/privates/shaders/frame.frag \
75+ $$PWD/privates/shaders/texture2.vert \
76+ $$PWD/shaders/shape.frag \
77 $$PWD/shaders/shape.vert \
78- $$PWD/shaders/shape.frag \
79- $$PWD/shaders/shape_no_dfdy.frag \
80+ $$PWD/shaders/shape_mipmap.frag \
81+ $$PWD/shaders/shapeoverlay.frag \
82 $$PWD/shaders/shapeoverlay.vert \
83- $$PWD/shaders/shapeoverlay.frag \
84- $$PWD/shaders/shapeoverlay_no_dfdy.frag \
85- $$PWD/privates/shaders/frame.vert \
86- $$PWD/privates/shaders/frame.frag
87+ $$PWD/shaders/shapeoverlay_mipmap.frag
88
89 load(ubuntu_qt_module)
90
91=== added file 'src/UbuntuToolkit/privates/shaders/color.frag'
92--- src/UbuntuToolkit/privates/shaders/color.frag 1970-01-01 00:00:00 +0000
93+++ src/UbuntuToolkit/privates/shaders/color.frag 2016-12-14 07:25:05 +0000
94@@ -0,0 +1,7 @@
95+uniform lowp float opacity;
96+varying lowp vec4 color;
97+
98+void main()
99+{
100+ gl_FragColor = vec4(opacity) * color;
101+}
102
103=== added file 'src/UbuntuToolkit/privates/shaders/color.vert'
104--- src/UbuntuToolkit/privates/shaders/color.vert 1970-01-01 00:00:00 +0000
105+++ src/UbuntuToolkit/privates/shaders/color.vert 2016-12-14 07:25:05 +0000
106@@ -0,0 +1,12 @@
107+uniform highp mat4 matrix;
108+
109+attribute highp vec4 positionAttrib;
110+attribute lowp vec4 colorAttrib;
111+
112+varying lowp vec4 color;
113+
114+void main()
115+{
116+ color = colorAttrib;
117+ gl_Position = matrix * positionAttrib;
118+}
119
120=== added file 'src/UbuntuToolkit/privates/shaders/color_opaque.frag'
121--- src/UbuntuToolkit/privates/shaders/color_opaque.frag 1970-01-01 00:00:00 +0000
122+++ src/UbuntuToolkit/privates/shaders/color_opaque.frag 2016-12-14 07:25:05 +0000
123@@ -0,0 +1,6 @@
124+varying lowp vec4 color;
125+
126+void main()
127+{
128+ gl_FragColor = color;
129+}
130
131=== added file 'src/UbuntuToolkit/privates/shaders/colormask.frag'
132--- src/UbuntuToolkit/privates/shaders/colormask.frag 1970-01-01 00:00:00 +0000
133+++ src/UbuntuToolkit/privates/shaders/colormask.frag 2016-12-14 07:25:05 +0000
134@@ -0,0 +1,10 @@
135+uniform sampler2D maskTexture;
136+uniform lowp float opacity;
137+
138+varying mediump vec2 maskCoord;
139+varying lowp vec4 color;
140+
141+void main()
142+{
143+ gl_FragColor = color * vec4(texture2D(maskTexture, maskCoord).r * opacity);
144+}
145
146=== added file 'src/UbuntuToolkit/privates/shaders/colormask.vert'
147--- src/UbuntuToolkit/privates/shaders/colormask.vert 1970-01-01 00:00:00 +0000
148+++ src/UbuntuToolkit/privates/shaders/colormask.vert 2016-12-14 07:25:05 +0000
149@@ -0,0 +1,15 @@
150+uniform highp mat4 matrix;
151+
152+attribute highp vec4 positionAttrib;
153+attribute mediump vec2 maskCoordAttrib;
154+attribute lowp vec4 colorAttrib;
155+
156+varying mediump vec2 maskCoord;
157+varying lowp vec4 color;
158+
159+void main()
160+{
161+ maskCoord = maskCoordAttrib;
162+ color = colorAttrib;
163+ gl_Position = matrix * positionAttrib;
164+}
165
166=== added file 'src/UbuntuToolkit/privates/shaders/colormask_opaque.frag'
167--- src/UbuntuToolkit/privates/shaders/colormask_opaque.frag 1970-01-01 00:00:00 +0000
168+++ src/UbuntuToolkit/privates/shaders/colormask_opaque.frag 2016-12-14 07:25:05 +0000
169@@ -0,0 +1,9 @@
170+uniform sampler2D maskTexture;
171+
172+varying mediump vec2 maskCoord;
173+varying lowp vec4 color;
174+
175+void main()
176+{
177+ gl_FragColor = color * vec4(texture2D(maskTexture, maskCoord).r);
178+}
179
180=== added file 'src/UbuntuToolkit/privates/shaders/fillcenterborder.frag'
181--- src/UbuntuToolkit/privates/shaders/fillcenterborder.frag 1970-01-01 00:00:00 +0000
182+++ src/UbuntuToolkit/privates/shaders/fillcenterborder.frag 2016-12-14 07:25:05 +0000
183@@ -0,0 +1,14 @@
184+uniform sampler2D borderTexture;
185+uniform lowp float opacity;
186+
187+varying mediump vec2 borderCoord;
188+varying lowp vec4 color;
189+varying lowp vec4 borderColor;
190+
191+void main()
192+{
193+ lowp float borderCoverage = 1.0 - texture2D(borderTexture, borderCoord).r;
194+ lowp vec4 border = borderColor * vec4(borderCoverage);
195+ lowp vec4 blend = border + (vec4(1.0 - border.a) * color);
196+ gl_FragColor = blend * vec4(opacity);
197+}
198
199=== added file 'src/UbuntuToolkit/privates/shaders/fillcenterborder.vert'
200--- src/UbuntuToolkit/privates/shaders/fillcenterborder.vert 1970-01-01 00:00:00 +0000
201+++ src/UbuntuToolkit/privates/shaders/fillcenterborder.vert 2016-12-14 07:25:05 +0000
202@@ -0,0 +1,18 @@
203+uniform highp mat4 matrix;
204+
205+attribute highp vec4 positionAttrib;
206+attribute mediump vec2 borderCoordAttrib;
207+attribute lowp vec4 colorAttrib;
208+attribute lowp vec4 borderColorAttrib;
209+
210+varying mediump vec2 borderCoord;
211+varying lowp vec4 color;
212+varying lowp vec4 borderColor;
213+
214+void main()
215+{
216+ borderCoord = borderCoordAttrib;
217+ color = colorAttrib;
218+ borderColor = borderColorAttrib;
219+ gl_Position = matrix * positionAttrib;
220+}
221
222=== added file 'src/UbuntuToolkit/privates/shaders/fillcenterborder_opaque.frag'
223--- src/UbuntuToolkit/privates/shaders/fillcenterborder_opaque.frag 1970-01-01 00:00:00 +0000
224+++ src/UbuntuToolkit/privates/shaders/fillcenterborder_opaque.frag 2016-12-14 07:25:05 +0000
225@@ -0,0 +1,12 @@
226+uniform sampler2D borderTexture;
227+
228+varying mediump vec2 borderCoord;
229+varying lowp vec4 color;
230+varying lowp vec4 borderColor;
231+
232+void main()
233+{
234+ lowp float borderCoverage = 1.0 - texture2D(borderTexture, borderCoord).r;
235+ lowp vec4 border = borderColor * vec4(borderCoverage);
236+ gl_FragColor = border + (vec4(1.0 - border.a) * color);
237+}
238
239=== added file 'src/UbuntuToolkit/privates/shaders/fillcentershadow.frag'
240--- src/UbuntuToolkit/privates/shaders/fillcentershadow.frag 1970-01-01 00:00:00 +0000
241+++ src/UbuntuToolkit/privates/shaders/fillcentershadow.frag 2016-12-14 07:25:05 +0000
242@@ -0,0 +1,16 @@
243+uniform sampler2D shadowTexture;
244+uniform lowp float opacity;
245+
246+varying mediump vec2 shadowCoord;
247+varying mediump vec2 midShadowCoord;
248+varying lowp vec4 color;
249+varying lowp vec4 shadowColor;
250+
251+void main()
252+{
253+ mediump vec2 shadowTextureCoord = midShadowCoord - abs(shadowCoord - midShadowCoord);
254+ lowp float shadowCoverage = 1.0 - texture2D(shadowTexture, shadowTextureCoord).r;
255+ lowp vec4 shadow = shadowColor * vec4(shadowCoverage);
256+ lowp vec4 blend = shadow + (vec4(1.0 - shadow.a) * color);
257+ gl_FragColor = blend * vec4(opacity);
258+}
259
260=== added file 'src/UbuntuToolkit/privates/shaders/fillcentershadow.vert'
261--- src/UbuntuToolkit/privates/shaders/fillcentershadow.vert 1970-01-01 00:00:00 +0000
262+++ src/UbuntuToolkit/privates/shaders/fillcentershadow.vert 2016-12-14 07:25:05 +0000
263@@ -0,0 +1,21 @@
264+uniform highp mat4 matrix;
265+
266+attribute highp vec4 positionAttrib;
267+attribute mediump vec2 shadowCoordAttrib;
268+attribute mediump vec2 midShadowCoordAttrib;
269+attribute lowp vec4 colorAttrib;
270+attribute lowp vec4 shadowColorAttrib;
271+
272+varying mediump vec2 shadowCoord;
273+varying mediump vec2 midShadowCoord;
274+varying lowp vec4 color;
275+varying lowp vec4 shadowColor;
276+
277+void main()
278+{
279+ shadowCoord = shadowCoordAttrib;
280+ midShadowCoord = midShadowCoordAttrib;
281+ color = colorAttrib;
282+ shadowColor = shadowColorAttrib;
283+ gl_Position = matrix * positionAttrib;
284+}
285
286=== added file 'src/UbuntuToolkit/privates/shaders/fillcentershadow_opaque.frag'
287--- src/UbuntuToolkit/privates/shaders/fillcentershadow_opaque.frag 1970-01-01 00:00:00 +0000
288+++ src/UbuntuToolkit/privates/shaders/fillcentershadow_opaque.frag 2016-12-14 07:25:05 +0000
289@@ -0,0 +1,14 @@
290+uniform sampler2D shadowTexture;
291+
292+varying mediump vec2 shadowCoord;
293+varying mediump vec2 midShadowCoord;
294+varying lowp vec4 color;
295+varying lowp vec4 shadowColor;
296+
297+void main()
298+{
299+ mediump vec2 shadowTextureCoord = midShadowCoord - abs(shadowCoord - midShadowCoord);
300+ lowp float shadowCoverage = 1.0 - texture2D(shadowTexture, shadowTextureCoord).r;
301+ lowp vec4 shadow = shadowColor * vec4(shadowCoverage);
302+ gl_FragColor = shadow + (vec4(1.0 - shadow.a) * color);
303+}
304
305=== added file 'src/UbuntuToolkit/privates/shaders/fillcentershadowborder.frag'
306--- src/UbuntuToolkit/privates/shaders/fillcentershadowborder.frag 1970-01-01 00:00:00 +0000
307+++ src/UbuntuToolkit/privates/shaders/fillcentershadowborder.frag 2016-12-14 07:25:05 +0000
308@@ -0,0 +1,22 @@
309+uniform sampler2D shadowTexture;
310+uniform sampler2D borderTexture;
311+uniform lowp float opacity;
312+
313+varying mediump vec2 shadowCoord;
314+varying mediump vec2 midShadowCoord;
315+varying mediump vec2 borderCoord;
316+varying lowp vec4 color;
317+varying lowp vec4 shadowColor;
318+varying lowp vec4 borderColor;
319+
320+void main()
321+{
322+ mediump vec2 shadowTextureCoord = midShadowCoord - abs(shadowCoord - midShadowCoord);
323+ lowp float shadowCoverage = 1.0 - texture2D(shadowTexture, shadowTextureCoord).r;
324+ lowp vec4 shadow = shadowColor * vec4(shadowCoverage);
325+ lowp vec4 blend = shadow + (vec4(1.0 - shadow.a) * color);
326+ lowp float borderCoverage = 1.0 - texture2D(borderTexture, borderCoord).r;
327+ lowp vec4 border = borderColor * vec4(borderCoverage);
328+ blend = border + (vec4(1.0 - border.a) * blend);
329+ gl_FragColor = blend * vec4(opacity);
330+}
331
332=== added file 'src/UbuntuToolkit/privates/shaders/fillcentershadowborder.vert'
333--- src/UbuntuToolkit/privates/shaders/fillcentershadowborder.vert 1970-01-01 00:00:00 +0000
334+++ src/UbuntuToolkit/privates/shaders/fillcentershadowborder.vert 2016-12-14 07:25:05 +0000
335@@ -0,0 +1,27 @@
336+uniform highp mat4 matrix;
337+
338+attribute highp vec4 positionAttrib;
339+attribute mediump vec2 shadowCoordAttrib;
340+attribute mediump vec2 midShadowCoordAttrib;
341+attribute mediump vec2 borderCoordAttrib;
342+attribute lowp vec4 colorAttrib;
343+attribute lowp vec4 shadowColorAttrib;
344+attribute lowp vec4 borderColorAttrib;
345+
346+varying mediump vec2 shadowCoord;
347+varying mediump vec2 midShadowCoord;
348+varying mediump vec2 borderCoord;
349+varying lowp vec4 color;
350+varying lowp vec4 shadowColor;
351+varying lowp vec4 borderColor;
352+
353+void main()
354+{
355+ shadowCoord = shadowCoordAttrib;
356+ midShadowCoord = midShadowCoordAttrib;
357+ borderCoord = borderCoordAttrib;
358+ color = colorAttrib;
359+ shadowColor = shadowColorAttrib;
360+ borderColor = borderColorAttrib;
361+ gl_Position = matrix * positionAttrib;
362+}
363
364=== added file 'src/UbuntuToolkit/privates/shaders/fillcentershadowborder_opaque.frag'
365--- src/UbuntuToolkit/privates/shaders/fillcentershadowborder_opaque.frag 1970-01-01 00:00:00 +0000
366+++ src/UbuntuToolkit/privates/shaders/fillcentershadowborder_opaque.frag 2016-12-14 07:25:05 +0000
367@@ -0,0 +1,20 @@
368+uniform sampler2D shadowTexture;
369+uniform sampler2D borderTexture;
370+
371+varying mediump vec2 shadowCoord;
372+varying mediump vec2 midShadowCoord;
373+varying mediump vec2 borderCoord;
374+varying lowp vec4 color;
375+varying lowp vec4 shadowColor;
376+varying lowp vec4 borderColor;
377+
378+void main()
379+{
380+ mediump vec2 shadowTextureCoord = midShadowCoord - abs(shadowCoord - midShadowCoord);
381+ lowp float shadowCoverage = 1.0 - texture2D(shadowTexture, shadowTextureCoord).r;
382+ lowp vec4 shadow = shadowColor * vec4(shadowCoverage);
383+ lowp vec4 blend = shadow + (vec4(1.0 - shadow.a) * color);
384+ lowp float borderCoverage = 1.0 - texture2D(borderTexture, borderCoord).r;
385+ lowp vec4 border = borderColor * vec4(borderCoverage);
386+ gl_FragColor = border + (vec4(1.0 - border.a) * blend);
387+}
388
389=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersborder.frag'
390--- src/UbuntuToolkit/privates/shaders/fillcornersborder.frag 1970-01-01 00:00:00 +0000
391+++ src/UbuntuToolkit/privates/shaders/fillcornersborder.frag 2016-12-14 07:25:05 +0000
392@@ -0,0 +1,17 @@
393+uniform sampler2D maskTexture;
394+uniform sampler2D borderTexture;
395+uniform lowp float opacity;
396+
397+varying mediump vec2 maskCoord;
398+varying mediump vec2 borderCoord;
399+varying lowp vec4 color;
400+varying lowp vec4 borderColor;
401+
402+void main()
403+{
404+ lowp float borderCoverage = 1.0 - texture2D(borderTexture, borderCoord).r;
405+ lowp vec4 border = borderColor * vec4(borderCoverage);
406+ lowp vec4 blend = border + (vec4(1.0 - border.a) * color);
407+ lowp float maskCoverage = texture2D(maskTexture, maskCoord).r;
408+ gl_FragColor = blend * vec4(maskCoverage * opacity);
409+}
410
411=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersborder.vert'
412--- src/UbuntuToolkit/privates/shaders/fillcornersborder.vert 1970-01-01 00:00:00 +0000
413+++ src/UbuntuToolkit/privates/shaders/fillcornersborder.vert 2016-12-14 07:25:05 +0000
414@@ -0,0 +1,21 @@
415+uniform highp mat4 matrix;
416+
417+attribute highp vec4 positionAttrib;
418+attribute mediump vec2 maskCoordAttrib;
419+attribute mediump vec2 borderCoordAttrib;
420+attribute lowp vec4 colorAttrib;
421+attribute lowp vec4 borderColorAttrib;
422+
423+varying mediump vec2 maskCoord;
424+varying mediump vec2 borderCoord;
425+varying lowp vec4 color;
426+varying lowp vec4 borderColor;
427+
428+void main()
429+{
430+ maskCoord = maskCoordAttrib;
431+ borderCoord = borderCoordAttrib;
432+ color = colorAttrib;
433+ borderColor = borderColorAttrib;
434+ gl_Position = matrix * positionAttrib;
435+}
436
437=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersborder_opaque.frag'
438--- src/UbuntuToolkit/privates/shaders/fillcornersborder_opaque.frag 1970-01-01 00:00:00 +0000
439+++ src/UbuntuToolkit/privates/shaders/fillcornersborder_opaque.frag 2016-12-14 07:25:05 +0000
440@@ -0,0 +1,16 @@
441+uniform sampler2D maskTexture;
442+uniform sampler2D borderTexture;
443+
444+varying mediump vec2 maskCoord;
445+varying mediump vec2 borderCoord;
446+varying lowp vec4 color;
447+varying lowp vec4 borderColor;
448+
449+void main()
450+{
451+ lowp float borderCoverage = 1.0 - texture2D(borderTexture, borderCoord).r;
452+ lowp vec4 border = borderColor * vec4(borderCoverage);
453+ lowp vec4 blend = border + (vec4(1.0 - border.a) * color);
454+ lowp float maskCoverage = texture2D(maskTexture, maskCoord).r;
455+ gl_FragColor = blend * vec4(maskCoverage);
456+}
457
458=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersshadow.frag'
459--- src/UbuntuToolkit/privates/shaders/fillcornersshadow.frag 1970-01-01 00:00:00 +0000
460+++ src/UbuntuToolkit/privates/shaders/fillcornersshadow.frag 2016-12-14 07:25:05 +0000
461@@ -0,0 +1,18 @@
462+uniform sampler2D shadowTexture;
463+uniform lowp float opacity;
464+
465+varying mediump vec2 maskCoord;
466+varying mediump vec2 shadowCoord;
467+varying mediump vec2 midShadowCoord;
468+varying lowp vec4 color;
469+varying lowp vec4 shadowColor;
470+
471+void main()
472+{
473+ lowp float maskCoverage = texture2D(shadowTexture, maskCoord).a;
474+ mediump vec2 shadowTextureCoord = midShadowCoord - abs(shadowCoord - midShadowCoord);
475+ lowp float shadowCoverage = 1.0 - texture2D(shadowTexture, shadowTextureCoord).r;
476+ lowp vec4 shadow = shadowColor * vec4(shadowCoverage);
477+ lowp vec4 blend = shadow + (vec4(1.0 - shadow.a) * color);
478+ gl_FragColor = blend * vec4(maskCoverage * opacity);
479+}
480
481=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersshadow.vert'
482--- src/UbuntuToolkit/privates/shaders/fillcornersshadow.vert 1970-01-01 00:00:00 +0000
483+++ src/UbuntuToolkit/privates/shaders/fillcornersshadow.vert 2016-12-14 07:25:05 +0000
484@@ -0,0 +1,24 @@
485+uniform highp mat4 matrix;
486+
487+attribute highp vec4 positionAttrib;
488+attribute mediump vec2 maskCoordAttrib;
489+attribute mediump vec2 shadowCoordAttrib;
490+attribute mediump vec2 midShadowCoordAttrib;
491+attribute lowp vec4 colorAttrib;
492+attribute lowp vec4 shadowColorAttrib;
493+
494+varying mediump vec2 maskCoord;
495+varying mediump vec2 shadowCoord;
496+varying mediump vec2 midShadowCoord;
497+varying lowp vec4 color;
498+varying lowp vec4 shadowColor;
499+
500+void main()
501+{
502+ maskCoord = maskCoordAttrib;
503+ shadowCoord = shadowCoordAttrib;
504+ midShadowCoord = midShadowCoordAttrib;
505+ color = colorAttrib;
506+ shadowColor = shadowColorAttrib;
507+ gl_Position = matrix * positionAttrib;
508+}
509
510=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersshadow_opaque.frag'
511--- src/UbuntuToolkit/privates/shaders/fillcornersshadow_opaque.frag 1970-01-01 00:00:00 +0000
512+++ src/UbuntuToolkit/privates/shaders/fillcornersshadow_opaque.frag 2016-12-14 07:25:05 +0000
513@@ -0,0 +1,17 @@
514+uniform sampler2D shadowTexture;
515+
516+varying mediump vec2 maskCoord;
517+varying mediump vec2 shadowCoord;
518+varying mediump vec2 midShadowCoord;
519+varying lowp vec4 color;
520+varying lowp vec4 shadowColor;
521+
522+void main()
523+{
524+ lowp float maskCoverage = texture2D(shadowTexture, maskCoord).a;
525+ mediump vec2 shadowTextureCoord = midShadowCoord - abs(shadowCoord - midShadowCoord);
526+ lowp float shadowCoverage = 1.0 - texture2D(shadowTexture, shadowTextureCoord).r;
527+ lowp vec4 shadow = shadowColor * vec4(shadowCoverage);
528+ lowp vec4 blend = shadow + (vec4(1.0 - shadow.a) * color);
529+ gl_FragColor = blend * vec4(maskCoverage);
530+}
531
532=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersshadowborder.frag'
533--- src/UbuntuToolkit/privates/shaders/fillcornersshadowborder.frag 1970-01-01 00:00:00 +0000
534+++ src/UbuntuToolkit/privates/shaders/fillcornersshadowborder.frag 2016-12-14 07:25:05 +0000
535@@ -0,0 +1,24 @@
536+uniform sampler2D shadowTexture;
537+uniform sampler2D borderTexture;
538+uniform lowp float opacity;
539+
540+varying mediump vec2 maskCoord;
541+varying mediump vec2 shadowCoord;
542+varying mediump vec2 midShadowCoord;
543+varying mediump vec2 borderCoord;
544+varying lowp vec4 color;
545+varying lowp vec4 shadowColor;
546+varying lowp vec4 borderColor;
547+
548+void main()
549+{
550+ lowp float maskCoverage = texture2D(shadowTexture, maskCoord).a;
551+ mediump vec2 shadowTextureCoord = midShadowCoord - abs(shadowCoord - midShadowCoord);
552+ lowp float shadowCoverage = 1.0 - texture2D(shadowTexture, shadowTextureCoord).r;
553+ lowp vec4 shadow = shadowColor * vec4(shadowCoverage);
554+ lowp vec4 blend = shadow + (vec4(1.0 - shadow.a) * color);
555+ lowp float borderCoverage = 1.0 - texture2D(borderTexture, borderCoord).r;
556+ lowp vec4 border = borderColor * vec4(borderCoverage);
557+ blend = border + (vec4(1.0 - border.a) * blend);
558+ gl_FragColor = blend * vec4(maskCoverage * opacity);
559+}
560
561=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersshadowborder.vert'
562--- src/UbuntuToolkit/privates/shaders/fillcornersshadowborder.vert 1970-01-01 00:00:00 +0000
563+++ src/UbuntuToolkit/privates/shaders/fillcornersshadowborder.vert 2016-12-14 07:25:05 +0000
564@@ -0,0 +1,30 @@
565+uniform highp mat4 matrix;
566+
567+attribute highp vec4 positionAttrib;
568+attribute mediump vec2 maskCoordAttrib;
569+attribute mediump vec2 shadowCoordAttrib;
570+attribute mediump vec2 midShadowCoordAttrib;
571+attribute mediump vec2 borderCoordAttrib;
572+attribute lowp vec4 colorAttrib;
573+attribute lowp vec4 shadowColorAttrib;
574+attribute lowp vec4 borderColorAttrib;
575+
576+varying mediump vec2 maskCoord;
577+varying mediump vec2 shadowCoord;
578+varying mediump vec2 midShadowCoord;
579+varying mediump vec2 borderCoord;
580+varying lowp vec4 color;
581+varying lowp vec4 shadowColor;
582+varying lowp vec4 borderColor;
583+
584+void main()
585+{
586+ maskCoord = maskCoordAttrib;
587+ shadowCoord = shadowCoordAttrib;
588+ midShadowCoord = midShadowCoordAttrib;
589+ borderCoord = borderCoordAttrib;
590+ color = colorAttrib;
591+ shadowColor = shadowColorAttrib;
592+ borderColor = borderColorAttrib;
593+ gl_Position = matrix * positionAttrib;
594+}
595
596=== added file 'src/UbuntuToolkit/privates/shaders/fillcornersshadowborder_opaque.frag'
597--- src/UbuntuToolkit/privates/shaders/fillcornersshadowborder_opaque.frag 1970-01-01 00:00:00 +0000
598+++ src/UbuntuToolkit/privates/shaders/fillcornersshadowborder_opaque.frag 2016-12-14 07:25:05 +0000
599@@ -0,0 +1,23 @@
600+uniform sampler2D shadowTexture;
601+uniform sampler2D borderTexture;
602+
603+varying mediump vec2 maskCoord;
604+varying mediump vec2 shadowCoord;
605+varying mediump vec2 midShadowCoord;
606+varying mediump vec2 borderCoord;
607+varying lowp vec4 color;
608+varying lowp vec4 shadowColor;
609+varying lowp vec4 borderColor;
610+
611+void main()
612+{
613+ lowp float maskCoverage = texture2D(shadowTexture, maskCoord).a;
614+ mediump vec2 shadowTextureCoord = midShadowCoord - abs(shadowCoord - midShadowCoord);
615+ lowp float shadowCoverage = 1.0 - texture2D(shadowTexture, shadowTextureCoord).r;
616+ lowp vec4 shadow = shadowColor * vec4(shadowCoverage);
617+ lowp vec4 blend = shadow + (vec4(1.0 - shadow.a) * color);
618+ lowp float borderCoverage = 1.0 - texture2D(borderTexture, borderCoord).r;
619+ lowp vec4 border = borderColor * vec4(borderCoverage);
620+ blend = border + (vec4(1.0 - border.a) * blend);
621+ gl_FragColor = blend * vec4(maskCoverage);
622+}
623
624=== modified file 'src/UbuntuToolkit/privates/shaders/frame.frag'
625--- src/UbuntuToolkit/privates/shaders/frame.frag 2016-01-21 11:46:11 +0000
626+++ src/UbuntuToolkit/privates/shaders/frame.frag 2016-12-14 07:25:05 +0000
627@@ -1,33 +1,15 @@
628-/*
629- * Copyright 2016 Canonical Ltd.
630- *
631- * This program is free software; you can redistribute it and/or modify
632- * it under the terms of the GNU Lesser General Public License as published by
633- * the Free Software Foundation; version 3.
634- *
635- * This program is distributed in the hope that it will be useful,
636- * but WITHOUT ANY WARRANTY; without even the implied warranty of
637- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
638- * GNU Lesser General Public License for more details.
639- *
640- * You should have received a copy of the GNU Lesser General Public License
641- * along with this program. If not, see <http://www.gnu.org/licenses/>.
642- *
643- * Author: Loïc Molinari <loic.molinari@canonical.com>
644- */
645-
646-uniform sampler2D texture;
647+uniform sampler2D texture[2];
648 uniform lowp float opacity;
649-varying mediump vec2 outerCoord;
650-varying mediump vec2 innerCoord;
651+
652+varying mediump vec2 texCoord1;
653+varying mediump vec2 texCoord2;
654 varying lowp vec4 color;
655
656-void main(void)
657+void main()
658 {
659- lowp float shapeOut = texture2D(texture, outerCoord).r;
660- lowp float shapeIn = texture2D(texture, innerCoord).r;
661- // Fused multiply-add friendly version of (shapeOut * (1.0 - shapeIn))
662- lowp float shape = (shapeOut * -shapeIn) + shapeOut;
663- // shape is squared to make thinner corners (particularly visible at stroke 1).
664- gl_FragColor = vec4(shape * shape * opacity) * color;
665+ lowp float outerShape = texture2D(texture[0], texCoord1).r;
666+ lowp float innerShape = texture2D(texture[1], texCoord2).r;
667+ // Fused multiply-add friendly version of (outerShape * (1.0 - innerShape))
668+ lowp float shape = (outerShape * -innerShape) + outerShape;
669+ gl_FragColor = vec4(shape * opacity) * color;
670 }
671
672=== removed file 'src/UbuntuToolkit/privates/shaders/frame.vert'
673--- src/UbuntuToolkit/privates/shaders/frame.vert 2016-01-21 11:46:11 +0000
674+++ src/UbuntuToolkit/privates/shaders/frame.vert 1970-01-01 00:00:00 +0000
675@@ -1,34 +0,0 @@
676-/*
677- * Copyright 2016 Canonical Ltd.
678- *
679- * This program is free software; you can redistribute it and/or modify
680- * it under the terms of the GNU Lesser General Public License as published by
681- * the Free Software Foundation; version 3.
682- *
683- * This program is distributed in the hope that it will be useful,
684- * but WITHOUT ANY WARRANTY; without even the implied warranty of
685- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
686- * GNU Lesser General Public License for more details.
687- *
688- * You should have received a copy of the GNU Lesser General Public License
689- * along with this program. If not, see <http://www.gnu.org/licenses/>.
690- *
691- * Author: Loïc Molinari <loic.molinari@canonical.com>
692- */
693-
694-uniform highp mat4 matrix;
695-attribute highp vec4 positionAttrib;
696-attribute mediump vec2 outerCoordAttrib;
697-attribute mediump vec2 innerCoordAttrib;
698-attribute lowp vec4 colorAttrib;
699-varying mediump vec2 outerCoord;
700-varying mediump vec2 innerCoord;
701-varying lowp vec4 color;
702-
703-void main()
704-{
705- outerCoord = outerCoordAttrib;
706- innerCoord = innerCoordAttrib;
707- color = colorAttrib;
708- gl_Position = matrix * positionAttrib;
709-}
710
711=== added file 'src/UbuntuToolkit/privates/shaders/texture2.vert'
712--- src/UbuntuToolkit/privates/shaders/texture2.vert 1970-01-01 00:00:00 +0000
713+++ src/UbuntuToolkit/privates/shaders/texture2.vert 2016-12-14 07:25:05 +0000
714@@ -0,0 +1,18 @@
715+uniform highp mat4 matrix;
716+
717+attribute highp vec4 positionAttrib;
718+attribute mediump vec2 texCoord1Attrib;
719+attribute mediump vec2 texCoord2Attrib;
720+attribute lowp vec4 colorAttrib;
721+
722+varying mediump vec2 texCoord1;
723+varying mediump vec2 texCoord2;
724+varying lowp vec4 color;
725+
726+void main()
727+{
728+ texCoord1 = texCoord1Attrib;
729+ texCoord2 = texCoord2Attrib;
730+ color = colorAttrib;
731+ gl_Position = matrix * positionAttrib;
732+}
733
734=== added file 'src/UbuntuToolkit/privates/ucshape.cpp'
735--- src/UbuntuToolkit/privates/ucshape.cpp 1970-01-01 00:00:00 +0000
736+++ src/UbuntuToolkit/privates/ucshape.cpp 2016-12-14 07:25:05 +0000
737@@ -0,0 +1,434 @@
738+/*
739+ * Copyright 2016 Canonical Ltd.
740+ *
741+ * This program is free software; you can redistribute it and/or modify
742+ * it under the terms of the GNU Lesser General Public License as published by
743+ * the Free Software Foundation; version 3.
744+ *
745+ * This program is distributed in the hope that it will be useful,
746+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
747+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
748+ * GNU Lesser General Public License for more details.
749+ *
750+ * You should have received a copy of the GNU Lesser General Public License
751+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
752+ *
753+ * Author: Loïc Molinari <loic.molinari@canonical.com>
754+ */
755+
756+// FIXME(loicm) Add a description of the techniques and terms used in the shape
757+// item and nodes.
758+
759+// TODO(loicm): Try using half-sized textures to speed up CPU-based shadow
760+// rendering, switching to bilinear texture sampling at runtime. Evaluate
761+// the trade-off between texture creation (faster generation allows higher
762+// max radius and shadow sizes) and rendering speed.
763+
764+// TODO(loicm): Outer shadow rendering should provide a clippedShape (or
765+// knockedOutShape) mode that knocks out the pixels of the shape area. This
766+// is often what we need and that would allow to optimise rendering by
767+// removing transparent pixels (that are still rasterised, shaded and
768+// blended by the GPU...) with a dedicated mesh.
769+
770+// TODO(loicm): Add support for negative distances.
771+
772+#include "ucshape_p.h"
773+
774+#include <math.h>
775+
776+#include "ucshapedropshadownodes_p.h"
777+#include "ucshapefillnodes_p.h"
778+
779+UCShape::UCShape(QQuickItem* parent)
780+ : QQuickItem(parent)
781+ , m_fillColor(qRgba(0xe9, 0x54, 0x20, 0xff)) // Ubuntu orange.
782+ , m_dropShadowColor(qRgba(0, 0, 0, 0xff))
783+ , m_innerShadowColor(qRgba(0, 0, 0, 0xff))
784+ , m_borderColor(qRgba(0xff, 0xff, 0xff, 0xff))
785+ , m_radius(0)
786+ , m_dropShadowSize(0)
787+ , m_dropShadowDistance(0)
788+ , m_dropShadowAngle(0)
789+ , m_innerShadowSize(0)
790+ , m_innerShadowDistance(0)
791+ , m_innerShadowAngle(0)
792+ , m_borderSize(0)
793+ // the flags must be in sync with the default values above!
794+ , m_flags(FillCenterVisible)
795+ , m_shape(Squircle)
796+{
797+ setFlag(ItemHasContents);
798+}
799+
800+UCShape::Shape UCShape::shape() const
801+{
802+ return static_cast<Shape>(m_shape);
803+}
804+
805+void UCShape::setShape(Shape shape)
806+{
807+ const quint8 newShape = shape;
808+ if (m_shape != newShape) {
809+ m_shape = newShape;
810+ update();
811+ Q_EMIT shapeChanged();
812+ }
813+}
814+
815+qreal UCShape::radius() const
816+{
817+ return unquantizeFromU16(m_radius);
818+}
819+
820+void UCShape::setRadius(qreal radius)
821+{
822+ const quint16 quantizedRadius = quantizeToU16(radius);
823+ if (m_radius != quantizedRadius) {
824+ if ((m_radius > 0) != (quantizedRadius > 0)) {
825+ if (qAlpha(m_fillColor) > 0) {
826+ if (quantizedRadius > 0) {
827+ m_flags |= FillCornersVisible | DirtyFillCornersVisibility;
828+ } else {
829+ m_flags = (m_flags & ~FillCornersVisible) | DirtyFillCornersVisibility;
830+ }
831+ }
832+ }
833+ m_radius = quantizedRadius;
834+ update();
835+ Q_EMIT radiusChanged();
836+ }
837+}
838+
839+QColor UCShape::fillColor() const
840+{
841+ return QColor(qRed(m_fillColor), qGreen(m_fillColor), qBlue(m_fillColor), qAlpha(m_fillColor));
842+}
843+
844+void UCShape::setFillColor(const QColor& color)
845+{
846+ const QRgb rgbColor = qRgba(color.red(), color.green(), color.blue(), color.alpha());
847+ if (m_fillColor != rgbColor) {
848+ if ((qAlpha(m_fillColor) > 0) != (qAlpha(rgbColor) > 0)) {
849+ if (qAlpha(rgbColor) > 0) {
850+ m_flags |= FillCenterVisible | DirtyFillCenterVisibility;
851+ if (m_radius > 0) {
852+ m_flags |= FillCornersVisible | DirtyFillCornersVisibility;
853+ }
854+ } else {
855+ m_flags &= ~FillCenterVisible;
856+ m_flags |= DirtyFillCenterVisibility;
857+ if (m_radius > 0) {
858+ m_flags &= ~FillCornersVisible;
859+ m_flags |= DirtyFillCornersVisibility;
860+ }
861+ }
862+ }
863+ m_fillColor = rgbColor;
864+ update();
865+ Q_EMIT fillColorChanged();
866+ }
867+}
868+
869+qreal UCShape::dropShadowSize() const
870+{
871+ return unquantizeFromU16(m_dropShadowSize);
872+}
873+
874+void UCShape::setDropShadowSize(qreal size)
875+{
876+ const quint16 quantizedSize = quantizeToU16(size);
877+ if (m_dropShadowSize != quantizedSize) {
878+ if (((m_dropShadowSize > 0) != (quantizedSize > 0))
879+ && ((m_dropShadowDistance == 0) && (qAlpha(m_dropShadowColor) > 0))) {
880+ if (quantizedSize > 0) {
881+ m_flags |= DropShadowVisible;
882+ } else {
883+ m_flags &= ~DropShadowVisible;
884+ }
885+ m_flags |= DirtyDropShadowVisibility;
886+ }
887+ m_dropShadowSize = quantizedSize;
888+ update();
889+ Q_EMIT dropShadowSizeChanged();
890+ }
891+}
892+
893+qreal UCShape::dropShadowDistance() const
894+{
895+ return unquantizeFromU16(m_dropShadowDistance);
896+}
897+
898+void UCShape::setDropShadowDistance(qreal distance)
899+{
900+ const quint16 quantizedDistance = quantizeToU16(distance);
901+ if (m_dropShadowDistance != quantizedDistance) {
902+ if ((m_dropShadowDistance > 0) != (quantizedDistance > 0)
903+ && ((m_dropShadowSize == 0) && (qAlpha(m_dropShadowColor) > 0))) {
904+ if (quantizedDistance > 0) {
905+ m_flags |= DropShadowVisible;
906+ } else {
907+ m_flags &= ~DropShadowVisible;
908+ }
909+ m_flags |= DirtyDropShadowVisibility;
910+ }
911+ m_dropShadowDistance = quantizedDistance;
912+ update();
913+ Q_EMIT dropShadowDistanceChanged();
914+ }
915+}
916+
917+qreal UCShape::dropShadowAngle() const
918+{
919+ return unquantizeFromU16(m_dropShadowAngle);
920+}
921+
922+void UCShape::setDropShadowAngle(qreal angle)
923+{
924+ double clampedAngle = fmod(static_cast<double>(angle), 360.0);
925+ if (clampedAngle < 0.0) {
926+ clampedAngle += 360.0;
927+ }
928+ const quint16 quantizedAngle = quantizeToU16Clamped(clampedAngle);
929+ if (m_dropShadowAngle != quantizedAngle) {
930+ m_dropShadowAngle = quantizedAngle;
931+ update();
932+ Q_EMIT dropShadowAngleChanged();
933+ }
934+}
935+
936+QColor UCShape::dropShadowColor() const
937+{
938+ return QColor(
939+ qRed(m_dropShadowColor), qGreen(m_dropShadowColor), qBlue(m_dropShadowColor),
940+ qAlpha(m_dropShadowColor));
941+}
942+
943+void UCShape::setDropShadowColor(const QColor& color)
944+{
945+ const QRgb rgbColor = qRgba(color.red(), color.green(), color.blue(), color.alpha());
946+ if (m_dropShadowColor != rgbColor) {
947+ if (((qAlpha(m_dropShadowColor) > 0) != (qAlpha(rgbColor) > 0))
948+ && ((m_dropShadowDistance > 0) || (m_dropShadowSize > 0))) {
949+ if (qAlpha(rgbColor) > 0) {
950+ m_flags |= DropShadowVisible;
951+ } else {
952+ m_flags &= ~DropShadowVisible;
953+ }
954+ m_flags |= DirtyDropShadowVisibility;
955+ }
956+ m_dropShadowColor = rgbColor;
957+ update();
958+ Q_EMIT dropShadowColorChanged();
959+ }
960+}
961+
962+qreal UCShape::innerShadowSize() const
963+{
964+ return unquantizeFromU16(m_innerShadowSize);
965+}
966+
967+void UCShape::setInnerShadowSize(qreal size)
968+{
969+ const quint16 quantizedSize = quantizeToU16(size);
970+ if (m_innerShadowSize != quantizedSize) {
971+ m_innerShadowSize = quantizedSize;
972+ update();
973+ Q_EMIT innerShadowSizeChanged();
974+ }
975+}
976+
977+qreal UCShape::innerShadowDistance() const
978+{
979+ return unquantizeFromU16(m_innerShadowDistance);
980+}
981+
982+void UCShape::setInnerShadowDistance(qreal distance)
983+{
984+ const quint16 quantizedDistance = quantizeToU16(distance);
985+ if (m_innerShadowDistance != quantizedDistance) {
986+ m_innerShadowDistance = quantizedDistance;
987+ update();
988+ Q_EMIT innerShadowDistanceChanged();
989+ }
990+}
991+
992+qreal UCShape::innerShadowAngle() const
993+{
994+ return unquantizeFromU16(m_innerShadowAngle);
995+}
996+
997+void UCShape::setInnerShadowAngle(qreal angle)
998+{
999+ double clampedAngle = fmod(static_cast<double>(angle), 360.0);
1000+ if (clampedAngle < 0.0) {
1001+ clampedAngle += 360.0;
1002+ }
1003+ const quint16 quantizedAngle = quantizeToU16Clamped(clampedAngle);
1004+ if (m_innerShadowAngle != quantizedAngle) {
1005+ m_innerShadowAngle = quantizedAngle;
1006+ update();
1007+ Q_EMIT innerShadowAngleChanged();
1008+ }
1009+}
1010+
1011+QColor UCShape::innerShadowColor() const
1012+{
1013+ return QColor(
1014+ qRed(m_innerShadowColor), qGreen(m_innerShadowColor), qBlue(m_innerShadowColor),
1015+ qAlpha(m_innerShadowColor));
1016+}
1017+
1018+void UCShape::setInnerShadowColor(const QColor& color)
1019+{
1020+ const QRgb rgbColor = qRgba(color.red(), color.green(), color.blue(), color.alpha());
1021+ if (m_innerShadowColor != rgbColor) {
1022+ m_innerShadowColor = rgbColor;
1023+ update();
1024+ Q_EMIT innerShadowColorChanged();
1025+ }
1026+}
1027+
1028+qreal UCShape::borderSize() const
1029+{
1030+ return unquantizeFromU16(m_borderSize);
1031+}
1032+
1033+void UCShape::setBorderSize(qreal size)
1034+{
1035+ const quint16 quantizedSize = quantizeToU16(size);
1036+ if (m_borderSize != quantizedSize) {
1037+ m_borderSize = quantizedSize;
1038+ update();
1039+ Q_EMIT borderSizeChanged();
1040+ }
1041+}
1042+
1043+QColor UCShape::borderColor() const
1044+{
1045+ return QColor(
1046+ qRed(m_borderColor), qGreen(m_borderColor), qBlue(m_borderColor), qAlpha(m_borderColor));
1047+}
1048+
1049+void UCShape::setBorderColor(const QColor& color)
1050+{
1051+ const QRgb rgbColor = qRgba(color.red(), color.green(), color.blue(), color.alpha());
1052+ if (m_borderColor != rgbColor) {
1053+ m_borderColor = rgbColor;
1054+ update();
1055+ Q_EMIT borderColorChanged();
1056+ }
1057+}
1058+
1059+class UCShapeNode : public QSGNode
1060+{
1061+public:
1062+ UCShapeNode() : QSGNode(), m_nodes{} { DLOG("creating UCShapeNode"); }
1063+ ~UCShapeNode() { DLOG("detroying UCShapeNode"); }
1064+
1065+ // Sorted by rendering order from back to front.
1066+ enum NodeType { DropShadow = 0, FillCenter, FillCorners, NodeTypeCount };
1067+
1068+ QSGNode* node(NodeType type, bool instantiate = true)
1069+ {
1070+ DASSERT(static_cast<quint32>(type) < NodeTypeCount);
1071+
1072+ if (m_nodes[type]) {
1073+ return m_nodes[type];
1074+ } else if (!instantiate) {
1075+ return Q_NULLPTR;
1076+ } else {
1077+ switch (type) {
1078+ case DropShadow: m_nodes[DropShadow] = new UCShapeDropShadowNode; break;
1079+ case FillCenter: m_nodes[FillCenter] = new UCShapeFillCenterNode; break;
1080+ case FillCorners: m_nodes[FillCorners] = new UCShapeFillCornersNode; break;
1081+ default: DNOT_REACHED(); return Q_NULLPTR;
1082+ }
1083+ for (int i = type + 1; i < NodeTypeCount; ++i) {
1084+ if (m_nodes[i]) {
1085+ insertChildNodeBefore(m_nodes[type], m_nodes[i]);
1086+ return m_nodes[type];
1087+ }
1088+ }
1089+ appendChildNode(m_nodes[type]);
1090+ return m_nodes[type];
1091+ }
1092+ }
1093+
1094+private:
1095+ QSGNode* m_nodes[NodeTypeCount];
1096+};
1097+
1098+QSGNode* UCShape::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*)
1099+{
1100+ const QSizeF itemSize(width(), height());
1101+ if (itemSize.isEmpty()) {
1102+ delete oldNode;
1103+ return Q_NULLPTR;
1104+ }
1105+
1106+ UCShapeNode* shapeNode;
1107+ if (oldNode) {
1108+ shapeNode = static_cast<UCShapeNode*>(oldNode);
1109+ } else {
1110+ shapeNode = new UCShapeNode;
1111+ // Make sure the right visibility is set on the nodes.
1112+ m_flags |= DirtyFlags;
1113+ }
1114+
1115+ // The strategy here is to instantiate shape node's children only when
1116+ // required (for instance corner nodes are instantiated only when radius is
1117+ // greater than 0). Once instantiated a child node is freed only when the
1118+ // parent is freed (for instance corner nodes are not freed when radius goes
1119+ // back to 0). That allows to minimise the memory usage to what the user
1120+ // needs (properties like radius and shadow sizes are set to 0 by default on
1121+ // purpose), to avoid complexifying the code and to avoid costly memory
1122+ // allocations when animating for instance a color back and forth to
1123+ // transparent (which would require a node deletion).
1124+
1125+ // Drop shadow node.
1126+ const bool dropShadowVisible = static_cast<bool>(m_flags & DropShadowVisible);
1127+ if (dropShadowVisible) {
1128+ static_cast<UCShapeDropShadowNode*>(shapeNode->node(UCShapeNode::DropShadow))->update(
1129+ itemSize, static_cast<UCShapeType>(m_shape), unquantizeFromU16(m_radius),
1130+ unquantizeFromU16(m_dropShadowSize), unquantizeFromU16(m_dropShadowAngle),
1131+ unquantizeFromU16(m_dropShadowDistance), m_dropShadowColor);
1132+ }
1133+ if (m_flags & DirtyDropShadowVisibility) {
1134+ static_cast<UCShapeDropShadowNode*>(shapeNode->node(UCShapeNode::DropShadow))->setVisible(
1135+ dropShadowVisible);
1136+ }
1137+
1138+ // Fill center node.
1139+ const bool fillCenterVisible = static_cast<bool>(m_flags & FillCenterVisible);
1140+ if (fillCenterVisible) {
1141+ static_cast<UCShapeFillCenterNode*>(shapeNode->node(UCShapeNode::FillCenter))->update(
1142+ itemSize, static_cast<UCShapeType>(m_shape), unquantizeFromU16(m_radius), m_fillColor,
1143+ unquantizeFromU16(m_innerShadowSize), unquantizeFromU16(m_innerShadowAngle),
1144+ unquantizeFromU16(m_innerShadowDistance), m_innerShadowColor,
1145+ unquantizeFromU16(m_borderSize), m_borderColor);
1146+ }
1147+ if (m_flags & DirtyFillCenterVisibility) {
1148+ static_cast<UCShapeFillCenterNode*>(shapeNode->node(UCShapeNode::FillCenter))->setVisible(
1149+ fillCenterVisible);
1150+ }
1151+
1152+ // Fill corners node.
1153+ const bool fillCornersVisible = static_cast<bool>(m_flags & FillCornersVisible);
1154+ if (fillCornersVisible) {
1155+ static_cast<UCShapeFillCornersNode*>(shapeNode->node(UCShapeNode::FillCorners))->update(
1156+ itemSize, static_cast<UCShapeType>(m_shape), unquantizeFromU16(m_radius), m_fillColor,
1157+ unquantizeFromU16(m_innerShadowSize), unquantizeFromU16(m_innerShadowAngle),
1158+ unquantizeFromU16(m_innerShadowDistance), m_innerShadowColor,
1159+ unquantizeFromU16(m_borderSize), m_borderColor);
1160+ }
1161+ if (m_flags & DirtyFillCornersVisibility) {
1162+ UCShapeFillCornersNode* node = static_cast<UCShapeFillCornersNode*>(
1163+ shapeNode->node(UCShapeNode::FillCorners, false));
1164+ if (node) {
1165+ node->setVisible(fillCornersVisible);
1166+ }
1167+ }
1168+
1169+ m_flags &= ~DirtyFlags;
1170+ return shapeNode;
1171+}
1172
1173=== added file 'src/UbuntuToolkit/privates/ucshape_p.h'
1174--- src/UbuntuToolkit/privates/ucshape_p.h 1970-01-01 00:00:00 +0000
1175+++ src/UbuntuToolkit/privates/ucshape_p.h 2016-12-14 07:25:05 +0000
1176@@ -0,0 +1,162 @@
1177+/*
1178+ * Copyright 2016 Canonical Ltd.
1179+ *
1180+ * This program is free software; you can redistribute it and/or modify
1181+ * it under the terms of the GNU Lesser General Public License as published by
1182+ * the Free Software Foundation; version 3.
1183+ *
1184+ * This program is distributed in the hope that it will be useful,
1185+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1186+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1187+ * GNU Lesser General Public License for more details.
1188+ *
1189+ * You should have received a copy of the GNU Lesser General Public License
1190+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1191+ *
1192+ * Author: Loïc Molinari <loic.molinari@canonical.com>
1193+ */
1194+
1195+#ifndef UCSHAPE_P_H
1196+#define UCSHAPE_P_H
1197+
1198+#include <QtQuick/QQuickItem>
1199+
1200+#include <UbuntuToolkit/private/ucshapetexturefactory_p.h>
1201+
1202+class UCShape : public QQuickItem
1203+{
1204+ Q_OBJECT
1205+ Q_ENUMS(Shape)
1206+
1207+ // Shape of the corner.
1208+ Q_PROPERTY(Shape shape READ shape WRITE setShape NOTIFY shapeChanged)
1209+
1210+ // Radius of the corners in pixels.
1211+ Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
1212+
1213+ // Fill color of the shape.
1214+ Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged)
1215+
1216+ // Size of the drop shadow in pixels.
1217+ Q_PROPERTY(qreal dropShadowSize READ dropShadowSize WRITE setDropShadowSize
1218+ NOTIFY dropShadowSizeChanged)
1219+
1220+ // Offset of the drop shadow in pixels.
1221+ Q_PROPERTY(qreal dropShadowDistance READ dropShadowDistance WRITE setDropShadowDistance
1222+ NOTIFY dropShadowDistanceChanged)
1223+
1224+ // Offset angle of the drop shadow in degrees. The virtual light points to
1225+ // the left by default and is rotated counter clockwise.
1226+ Q_PROPERTY(qreal dropShadowAngle READ dropShadowAngle WRITE setDropShadowAngle
1227+ NOTIFY dropShadowAngleChanged)
1228+
1229+ // Color of the drop shadow.
1230+ Q_PROPERTY(QColor dropShadowColor READ dropShadowColor WRITE setDropShadowColor
1231+ NOTIFY dropShadowColorChanged)
1232+
1233+ // Size of the inner shadow in pixels.
1234+ Q_PROPERTY(qreal innerShadowSize READ innerShadowSize WRITE setInnerShadowSize
1235+ NOTIFY innerShadowSizeChanged)
1236+
1237+ // Offset of the inner shadow in pixels.
1238+ Q_PROPERTY(qreal innerShadowDistance READ innerShadowDistance WRITE setInnerShadowDistance
1239+ NOTIFY innerShadowDistanceChanged)
1240+
1241+ // Offset angle of the inner shadow in degrees. The virtual light points to
1242+ // the left by default and is rotated counter clockwise.
1243+ Q_PROPERTY(qreal innerShadowAngle READ innerShadowAngle WRITE setInnerShadowAngle
1244+ NOTIFY innerShadowAngleChanged)
1245+
1246+ // Color of the inner shadow.
1247+ Q_PROPERTY(QColor innerShadowColor READ innerShadowColor WRITE setInnerShadowColor
1248+ NOTIFY innerShadowColorChanged)
1249+
1250+ // Size of the border in pixels.
1251+ Q_PROPERTY(qreal borderSize READ borderSize WRITE setBorderSize NOTIFY borderSizeChanged)
1252+
1253+ // Color of the border.
1254+ Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged)
1255+
1256+public:
1257+ UCShape(QQuickItem* parent = 0);
1258+
1259+ enum Shape { Squircle = UCShapeType::Squircle, Circle = UCShapeType::Circle };
1260+
1261+ Shape shape() const;
1262+ void setShape(Shape shape);
1263+ qreal radius() const;
1264+ void setRadius(qreal radius);
1265+ QColor fillColor() const;
1266+ void setFillColor(const QColor& fillColor);
1267+ qreal dropShadowSize() const;
1268+ void setDropShadowSize(qreal size);
1269+ qreal dropShadowDistance() const;
1270+ void setDropShadowDistance(qreal distance);
1271+ qreal dropShadowAngle() const;
1272+ void setDropShadowAngle(qreal angle);
1273+ QColor dropShadowColor() const;
1274+ void setDropShadowColor(const QColor& color);
1275+ qreal innerShadowSize() const;
1276+ void setInnerShadowSize(qreal size);
1277+ qreal innerShadowDistance() const;
1278+ void setInnerShadowDistance(qreal distance);
1279+ qreal innerShadowAngle() const;
1280+ void setInnerShadowAngle(qreal angle);
1281+ QColor innerShadowColor() const;
1282+ void setInnerShadowColor(const QColor& color);
1283+ qreal borderSize() const;
1284+ void setBorderSize(qreal size);
1285+ QColor borderColor() const;
1286+ void setBorderColor(const QColor& color);
1287+
1288+Q_SIGNALS:
1289+ void shapeChanged();
1290+ void radiusChanged();
1291+ void fillColorChanged();
1292+ void dropShadowSizeChanged();
1293+ void dropShadowDistanceChanged();
1294+ void dropShadowAngleChanged();
1295+ void dropShadowColorChanged();
1296+ void innerShadowSizeChanged();
1297+ void innerShadowDistanceChanged();
1298+ void innerShadowAngleChanged();
1299+ void innerShadowColorChanged();
1300+ void borderSizeChanged();
1301+ void borderColorChanged();
1302+
1303+private:
1304+ QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data) Q_DECL_OVERRIDE;
1305+
1306+ enum {
1307+ DropShadowVisible = (1 << 0),
1308+ FillCenterVisible = (1 << 1),
1309+ FillCornersVisible = (1 << 2),
1310+ DirtyDropShadowVisibility = (1 << 3),
1311+ DirtyFillCenterVisibility = (1 << 4),
1312+ DirtyFillCornersVisibility = (1 << 5),
1313+ DirtyFlags =
1314+ DirtyDropShadowVisibility | DirtyFillCenterVisibility | DirtyFillCornersVisibility
1315+ };
1316+
1317+ QRgb m_fillColor;
1318+ QRgb m_dropShadowColor;
1319+ QRgb m_innerShadowColor;
1320+ QRgb m_borderColor;
1321+ quint16 m_radius;
1322+ quint16 m_dropShadowSize;
1323+ quint16 m_dropShadowDistance;
1324+ quint16 m_dropShadowAngle;
1325+ quint16 m_innerShadowSize;
1326+ quint16 m_innerShadowDistance;
1327+ quint16 m_innerShadowAngle;
1328+ quint16 m_borderSize;
1329+ quint16 m_flags;
1330+ quint8 m_shape : 1;
1331+ quint8 __padding : 7;
1332+
1333+ Q_DISABLE_COPY(UCShape)
1334+};
1335+
1336+QML_DECLARE_TYPE(UCShape)
1337+
1338+#endif // UCSHAPE_P_H
1339
1340=== added file 'src/UbuntuToolkit/privates/ucshapedropshadownodes.cpp'
1341--- src/UbuntuToolkit/privates/ucshapedropshadownodes.cpp 1970-01-01 00:00:00 +0000
1342+++ src/UbuntuToolkit/privates/ucshapedropshadownodes.cpp 2016-12-14 07:25:05 +0000
1343@@ -0,0 +1,175 @@
1344+/*
1345+ * Copyright 2016 Canonical Ltd.
1346+ *
1347+ * This program is free software; you can redistribute it and/or modify
1348+ * it under the terms of the GNU Lesser General Public License as published by
1349+ * the Free Software Foundation; version 3.
1350+ *
1351+ * This program is distributed in the hope that it will be useful,
1352+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1353+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1354+ * GNU Lesser General Public License for more details.
1355+ *
1356+ * You should have received a copy of the GNU Lesser General Public License
1357+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1358+ *
1359+ * Author: Loïc Molinari <loic.molinari@canonical.com>
1360+ */
1361+
1362+#include "ucshapedropshadownodes_p.h"
1363+
1364+#include <QtGui/QGuiApplication>
1365+#include <QtGui/QOpenGLFunctions>
1366+
1367+#include "ucshaperesources_p.h"
1368+
1369+// The geometry is made of 9 vertices indexed with a triangle strip mode.
1370+// 0 --- 1 --- 2
1371+// | / | / |
1372+// 3 --- 4 --- 5
1373+// | / | / |
1374+// 6 --- 7 --- 8
1375+const quint16 indices[] = {
1376+ 0, 3, 1, 4, 2, 5,
1377+ 5, 3, // Degenerate triangle.
1378+ 3, 6, 4, 7, 5, 8
1379+};
1380+const int indexCount = ARRAY_SIZE(indices);
1381+const int vertexCount = 9;
1382+
1383+UCShapeDropShadowNode::UCShapeDropShadowNode()
1384+ : QSGGeometryNode()
1385+ , m_resources(vertexCount, indexCount)
1386+ , m_radius(0)
1387+ , m_shadow(0)
1388+ , m_shape(UCShapeType::Squircle)
1389+ , m_flags(0)
1390+{
1391+ DLOG("creating UCShapeDropShadowNode");
1392+ setFlag(QSGNode::UsePreprocess, true);
1393+ setMaterial(m_resources.material());
1394+ m_resources.opaqueMaterial()->setFlag(QSGMaterial::Blending);
1395+ setOpaqueMaterial(m_resources.opaqueMaterial());
1396+ memcpy(m_resources.geometry()->indexData(), indices, indexCount * sizeof(quint16));
1397+ setGeometry(m_resources.geometry());
1398+ qsgnode_set_description(this, QLatin1String("shapedropshadow"));
1399+}
1400+
1401+UCShapeDropShadowNode::~UCShapeDropShadowNode()
1402+{
1403+ DLOG("detroying UCShapeDropShadowNode");
1404+}
1405+
1406+void UCShapeDropShadowNode::preprocess()
1407+{
1408+ if (m_flags & DirtyMask) {
1409+ static_cast<UCShapeColorMaskMaterial<false>*>(
1410+ m_resources.material())->updateShadowTexture(
1411+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
1412+ static_cast<UCShapeColorMaskMaterial<true>*>(
1413+ m_resources.opaqueMaterial())->updateShadowTexture(
1414+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
1415+ }
1416+ m_flags &= ~DirtyMask;
1417+}
1418+
1419+void UCShapeDropShadowNode::setVisible(bool visible)
1420+{
1421+ DLOG("UCShapeDropShadowNode::setVisible %d", visible);
1422+ if (static_cast<bool>(m_flags & Visible) != visible) {
1423+ m_flags = (m_flags & ~Visible) | (visible ? Visible : 0);
1424+ markDirty(DirtySubtreeBlocked);
1425+ }
1426+}
1427+
1428+void UCShapeDropShadowNode::update(
1429+ const QSizeF& itemSize, UCShapeType type, float radius, float shadowSize, float shadowAngle,
1430+ float shadowDistance, QRgb shadowColor)
1431+{
1432+ UCShapeColorMaskResources::Vertex* v =
1433+ reinterpret_cast<UCShapeColorMaskResources::Vertex*>(m_resources.geometry()->vertexData());
1434+ float s, c;
1435+ sincosf((shadowAngle + 180.0f) * -(M_PI / 180.0f), &s, &c);
1436+ const float offsetX = roundf(c * shadowDistance);
1437+ const float offsetY = roundf(s * shadowDistance);
1438+ const float dpr = qGuiApp->devicePixelRatio();
1439+ const float w = floorf(static_cast<float>(itemSize.width()));
1440+ const float h = floorf(static_cast<float>(itemSize.height()));
1441+ // Rounded down since renderShape() doesn't support sub-pixel rendering.
1442+ const float maxSize = floorf(qMin(w, h) * 0.5f);
1443+ const float clampedRadius = qMin(floorf(radius), maxSize);
1444+ const quint32 packedShadowColor = packColor(shadowColor);
1445+ const float clampedShadow = qMin(floorf(shadowSize), maxSize);
1446+ const float border = 1.0f;
1447+ const float textureSize = (2.0f * clampedShadow + 2.0f * border + clampedRadius) * dpr;
1448+ const float textureSizeRounded = roundUp(static_cast<int>(textureSize), textureRounding);
1449+ const float textureOffset = (textureSizeRounded - textureSize) / textureSizeRounded;
1450+ const float textureFactor = ((1.0f - textureOffset) * dpr) / textureSize;
1451+ const float midW = w * 0.5f;
1452+ const float midH = h * 0.5f;
1453+ const float midShadowS = (border + clampedShadow + midW) * textureFactor + textureOffset;
1454+ const float midShadowT = (border + clampedShadow + midH) * textureFactor + textureOffset;
1455+
1456+ v[0].x = -clampedShadow + offsetX;
1457+ v[0].y = -clampedShadow + offsetY;
1458+ v[0].maskS = border * textureFactor + textureOffset;
1459+ v[0].maskT = border * textureFactor + textureOffset;
1460+ v[0].color = packedShadowColor;
1461+ v[1].x = midW + offsetX;
1462+ v[1].y = -clampedShadow + offsetY;
1463+ v[1].maskS = midShadowS;
1464+ v[1].maskT = border * textureFactor + textureOffset;
1465+ v[1].color = packedShadowColor;
1466+ v[2].x = w + clampedShadow + offsetX;
1467+ v[2].y = -clampedShadow + offsetY;
1468+ v[2].maskS = border * textureFactor + textureOffset;
1469+ v[2].maskT = border * textureFactor + textureOffset;
1470+ v[2].color = packedShadowColor;
1471+ v[3].x = -clampedShadow + offsetX;
1472+ v[3].y = midH + offsetY;
1473+ v[3].maskS = border * textureFactor + textureOffset;
1474+ v[3].maskT = midShadowT;
1475+ v[3].color = packedShadowColor;
1476+ v[4].x = midW + offsetX;
1477+ v[4].y = midH + offsetY;
1478+ v[4].maskS = midShadowS;
1479+ v[4].maskT = midShadowT;
1480+ v[4].color = packedShadowColor;
1481+ v[5].x = w + clampedShadow + offsetX;
1482+ v[5].y = midH + offsetY;
1483+ v[5].maskS = border * textureFactor + textureOffset;
1484+ v[5].maskT = midShadowT;
1485+ v[5].color = packedShadowColor;
1486+ v[6].x = -clampedShadow + offsetX;
1487+ v[6].y = h + clampedShadow + offsetY;
1488+ v[6].maskS = border * textureFactor + textureOffset;
1489+ v[6].maskT = border * textureFactor + textureOffset;
1490+ v[6].color = packedShadowColor;
1491+ v[7].x = midW + offsetX;
1492+ v[7].y = h + clampedShadow + offsetY;
1493+ v[7].maskS = midShadowS;
1494+ v[7].maskT = border * textureFactor + textureOffset;
1495+ v[7].color = packedShadowColor;
1496+ v[8].x = w + clampedShadow + offsetX;
1497+ v[8].y = h + clampedShadow + offsetY;
1498+ v[8].maskS = border * textureFactor + textureOffset;
1499+ v[8].maskT = border * textureFactor + textureOffset;
1500+ v[8].color = packedShadowColor;
1501+ markDirty(QSGNode::DirtyGeometry);
1502+
1503+ // Update data for the preprocess() call.
1504+ const quint16 deviceShadow = static_cast<quint16>(clampedShadow * dpr);
1505+ if (m_shadow != deviceShadow) {
1506+ m_shadow = deviceShadow;
1507+ m_flags |= DirtyShadow;
1508+ }
1509+ const quint16 deviceRadius = static_cast<quint16>(clampedRadius * dpr);
1510+ if (m_radius != deviceRadius) {
1511+ m_radius = deviceRadius;
1512+ m_flags |= DirtyRadius;
1513+ }
1514+ if (m_shape != static_cast<quint8>(type)) {
1515+ m_shape = static_cast<quint8>(type);
1516+ m_flags |= DirtyShape;
1517+ }
1518+}
1519
1520=== added file 'src/UbuntuToolkit/privates/ucshapedropshadownodes_p.h'
1521--- src/UbuntuToolkit/privates/ucshapedropshadownodes_p.h 1970-01-01 00:00:00 +0000
1522+++ src/UbuntuToolkit/privates/ucshapedropshadownodes_p.h 2016-12-14 07:25:05 +0000
1523@@ -0,0 +1,57 @@
1524+/*
1525+ * Copyright 2016 Canonical Ltd.
1526+ *
1527+ * This program is free software; you can redistribute it and/or modify
1528+ * it under the terms of the GNU Lesser General Public License as published by
1529+ * the Free Software Foundation; version 3.
1530+ *
1531+ * This program is distributed in the hope that it will be useful,
1532+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1533+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1534+ * GNU Lesser General Public License for more details.
1535+ *
1536+ * You should have received a copy of the GNU Lesser General Public License
1537+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1538+ *
1539+ * Author: Loïc Molinari <loic.molinari@canonical.com>
1540+ */
1541+
1542+#ifndef UCSHAPEDROPSHADOWNODES_P_H
1543+#define UCSHAPEDROPSHADOWNODES_P_H
1544+
1545+#include <QtQuick/QSGNode>
1546+
1547+#include <UbuntuToolkit/private/ucshaperesources_p.h>
1548+
1549+class UCShapeDropShadowNode : public QSGGeometryNode
1550+{
1551+public:
1552+ UCShapeDropShadowNode();
1553+ ~UCShapeDropShadowNode();
1554+
1555+ void preprocess() Q_DECL_OVERRIDE;
1556+ bool isSubtreeBlocked() const Q_DECL_OVERRIDE { return !(m_flags & Visible); }
1557+
1558+ void setVisible(bool visible);
1559+ void update(
1560+ const QSizeF& itemSize, UCShapeType type, float radius, float shadowSize, float shadowAngle,
1561+ float shadowDistance, QRgb shadowColor);
1562+
1563+private:
1564+ enum {
1565+ DirtyRadius = (1 << 0),
1566+ DirtyShadow = (1 << 1),
1567+ DirtyShape = (1 << 2),
1568+ DirtyMask = (DirtyRadius | DirtyShadow | DirtyShape),
1569+ Visible = (1 << 3),
1570+ Blending = (1 << 4)
1571+ };
1572+
1573+ UCShapeColorMaskResources m_resources;
1574+ quint16 m_radius;
1575+ quint16 m_shadow;
1576+ quint8 m_shape;
1577+ quint8 m_flags;
1578+};
1579+
1580+#endif // UCSHAPEDROPSHADOWNODES_P_H
1581
1582=== added file 'src/UbuntuToolkit/privates/ucshapefillnodes.cpp'
1583--- src/UbuntuToolkit/privates/ucshapefillnodes.cpp 1970-01-01 00:00:00 +0000
1584+++ src/UbuntuToolkit/privates/ucshapefillnodes.cpp 2016-12-14 07:25:05 +0000
1585@@ -0,0 +1,1431 @@
1586+/*
1587+ * Copyright 2016 Canonical Ltd.
1588+ *
1589+ * This program is free software; you can redistribute it and/or modify
1590+ * it under the terms of the GNU Lesser General Public License as published by
1591+ * the Free Software Foundation; version 3.
1592+ *
1593+ * This program is distributed in the hope that it will be useful,
1594+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1595+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1596+ * GNU Lesser General Public License for more details.
1597+ *
1598+ * You should have received a copy of the GNU Lesser General Public License
1599+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1600+ *
1601+ * Author: Loïc Molinari <loic.molinari@canonical.com>
1602+ */
1603+
1604+// FIXME(loicm) The midShadow coords force a dependent texture read which is
1605+// quite slow on some platforms. We should maybe add geometry to deal with
1606+// the coords inversion. That would add complexity but improve perf.
1607+
1608+#include "ucshapefillnodes_p.h"
1609+
1610+#include <QtGui/QOpenGLFunctions>
1611+#include <QtGui/QGuiApplication>
1612+
1613+UCShapeFillCenterNode::UCShapeFillCenterNode()
1614+ : QSGGeometryNode()
1615+ , m_resources(Q_NULLPTR)
1616+ , m_radius(0)
1617+ , m_shadow(0)
1618+ , m_borderRadius(0)
1619+ , m_flags(0)
1620+ , m_shape(UCShapeType::Squircle)
1621+{
1622+ DLOG("creating UCShapeFillCenterNode");
1623+ qsgnode_set_description(this, QLatin1String("shapefillcenter"));
1624+}
1625+
1626+UCShapeFillCenterNode::~UCShapeFillCenterNode()
1627+{
1628+ DLOG("detroying UCShapeFillCenterNode");
1629+ delete m_resources;
1630+}
1631+
1632+void UCShapeFillCenterNode::preprocess()
1633+{
1634+ DASSERT(m_flags & Textured);
1635+
1636+ // FIXME(loicm) Could be made more consise (texture update methods in the resources?).
1637+
1638+ switch (m_flags & StyleMask) {
1639+ case (HasColor | HasShadow):
1640+ if (m_flags & (DirtyRadius | DirtyShadow | DirtyShape)) {
1641+ static_cast<UCShapeFillCenterShadowMaterial<false>*>(
1642+ m_resources->material())->updateShadowTexture(
1643+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
1644+ static_cast<UCShapeFillCenterShadowMaterial<true>*>(
1645+ m_resources->opaqueMaterial())->updateShadowTexture(
1646+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
1647+ }
1648+ break;
1649+
1650+ case (HasColor | HasBorder):
1651+ if (m_flags & (DirtyBorderRadius | DirtyShape)) {
1652+ static_cast<UCShapeFillCenterBorderMaterial<false>*>(
1653+ m_resources->material())->updateBorderTexture(
1654+ static_cast<UCShapeType>(m_shape), m_borderRadius);
1655+ static_cast<UCShapeFillCenterBorderMaterial<true>*>(
1656+ m_resources->opaqueMaterial())->updateBorderTexture(
1657+ static_cast<UCShapeType>(m_shape), m_borderRadius);
1658+ }
1659+ break;
1660+
1661+ case (HasColor | HasShadow | HasBorder):
1662+ if (m_flags & (DirtyRadius | DirtyShadow | DirtyShape)) {
1663+ static_cast<UCShapeFillCenterShadowBorderMaterial<false>*>(
1664+ m_resources->material())->updateShadowTexture(
1665+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
1666+ static_cast<UCShapeFillCenterShadowBorderMaterial<true>*>(
1667+ m_resources->opaqueMaterial())->updateShadowTexture(
1668+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
1669+ }
1670+ if (m_flags & (DirtyBorderRadius | DirtyShape)) {
1671+ static_cast<UCShapeFillCenterShadowBorderMaterial<false>*>(
1672+ m_resources->material())->updateBorderTexture(
1673+ static_cast<UCShapeType>(m_shape), m_borderRadius);
1674+ static_cast<UCShapeFillCenterShadowBorderMaterial<true>*>(
1675+ m_resources->opaqueMaterial())->updateBorderTexture(
1676+ static_cast<UCShapeType>(m_shape), m_borderRadius);
1677+ }
1678+ break;
1679+
1680+ default:
1681+ NOT_REACHED();
1682+ }
1683+
1684+ m_flags &= ~DirtyMask;
1685+}
1686+
1687+void UCShapeFillCenterNode::setVisible(bool visible)
1688+{
1689+ DLOG("UCShapeFillCenterNode::setVisible %d", visible);
1690+ if (static_cast<bool>(m_flags & Visible) != visible) {
1691+ m_flags = (m_flags & ~Visible) | (visible ? Visible : 0);
1692+ markDirty(DirtySubtreeBlocked);
1693+ }
1694+}
1695+
1696+void UCShapeFillCenterNode::update(
1697+ const QSizeF& itemSize, UCShapeType type, float radius, QRgb color, float shadowSize,
1698+ float shadowAngle, float shadowDistance, QRgb shadowColor, float borderSize, QRgb borderColor)
1699+{
1700+ // Without border, the geometry is made of 8 vertices indexed with a
1701+ // triangle strip mode. With border, the geometry is made of 13 vertices
1702+ // indexed with a triangle strip mode.
1703+ //
1704+ // Without border: With border:
1705+ // 0 ----- 1 0 - 1 - 2
1706+ // / \ / | \ ("-Werror=comment" GCC guard)
1707+ // 2 3 3 | 4
1708+ // | | | | |
1709+ // | | 5 ----- 6 ----- 7
1710+ // | | | | |
1711+ // 4 5 8 | 9
1712+ // \ / \ | /
1713+ // 6 ----- 7 10 -11-12
1714+ const quint16 noBorderIndices[] = {
1715+ 2, 4, 0, 6, 1, 7, 3, 5
1716+ };
1717+ const quint16 borderIndices[] = {
1718+ 3, 5, 0, 6, 1, 7, 2, 4,
1719+ 4, 8, // Degenerate triangle.
1720+ 8, 10, 5, 11, 6, 12, 7, 9
1721+ };
1722+ const int noBorderIndexCount = ARRAY_SIZE(noBorderIndices);
1723+ const int borderIndexCount = ARRAY_SIZE(borderIndices);
1724+ const int noBorderVertexCount = 8;
1725+ const int borderVertexCount = 13;
1726+
1727+ quint16 style = ((shadowSize <= 0.0f && shadowDistance <= 0.0f) || (qAlpha(shadowColor) == 0)) ?
1728+ HasColor : (HasColor | HasShadow);
1729+ if (borderSize >= 1.0f) {
1730+ style |= HasBorder;
1731+ }
1732+
1733+ // Create new material/geometry set if needed.
1734+ if (style != (m_flags & StyleMask)) {
1735+ delete m_resources;
1736+ switch (style) {
1737+ case HasColor:
1738+ m_resources = new UCShapeColorResources(noBorderVertexCount, noBorderIndexCount);
1739+ memcpy(m_resources->geometry()->indexData(), noBorderIndices,
1740+ noBorderIndexCount * sizeof(quint16));
1741+ setFlag(QSGNode::UsePreprocess, false);
1742+ break;
1743+ case (HasColor | HasShadow):
1744+ m_resources = new UCShapeFillCenterShadowResources(
1745+ noBorderVertexCount, noBorderIndexCount);
1746+ memcpy(m_resources->geometry()->indexData(), noBorderIndices,
1747+ noBorderIndexCount * sizeof(quint16));
1748+ setFlag(QSGNode::UsePreprocess, true);
1749+ break;
1750+ case (HasColor | HasBorder):
1751+ m_resources = new UCShapeFillCenterBorderResources(borderVertexCount, borderIndexCount);
1752+ memcpy(m_resources->geometry()->indexData(), borderIndices,
1753+ borderIndexCount * sizeof(quint16));
1754+ setFlag(QSGNode::UsePreprocess, true);
1755+ break;
1756+ case (HasColor | HasShadow | HasBorder):
1757+ m_resources = new UCShapeFillCenterShadowBorderResources(
1758+ borderVertexCount, borderIndexCount);
1759+ memcpy(m_resources->geometry()->indexData(), borderIndices,
1760+ borderIndexCount * sizeof(quint16));
1761+ setFlag(QSGNode::UsePreprocess, true);
1762+ break;
1763+ default:
1764+ NOT_REACHED();
1765+ }
1766+ setMaterial(m_resources->material());
1767+ setOpaqueMaterial(m_resources->opaqueMaterial());
1768+ setGeometry(m_resources->geometry());
1769+ m_flags = (m_flags & ~StyleMask) | style | DirtyMask;
1770+ }
1771+
1772+ const float dpr = qGuiApp->devicePixelRatio();
1773+ const float w = floorf(static_cast<float>(itemSize.width()));
1774+ const float h = floorf(static_cast<float>(itemSize.height()));
1775+ // Rounded down since Shadow doesn't support sub-pixel rendering.
1776+ const float maxSize = floorf(qMin(w, h) * 0.5f);
1777+ const float clampedRadius = qMin(floorf(radius), maxSize);
1778+ const quint32 packedColor = packColor(color);
1779+
1780+ // Update geometry depending on the style.
1781+ switch (style) {
1782+ case HasColor: {
1783+ UCShapeColorResources::Vertex* v =
1784+ reinterpret_cast<UCShapeColorResources::Vertex*>(m_resources->geometry()->vertexData());
1785+ v[0].x = clampedRadius;
1786+ v[0].y = 0.0f;
1787+ v[0].color = packedColor;
1788+ v[1].x = w - clampedRadius;
1789+ v[1].y = 0.0f;
1790+ v[1].color = packedColor;
1791+ v[2].x = 0.0f;
1792+ v[2].y = clampedRadius;
1793+ v[2].color = packedColor;
1794+ v[3].x = w;
1795+ v[3].y = clampedRadius;
1796+ v[3].color = packedColor;
1797+ v[4].x = 0.0f;
1798+ v[4].y = h - clampedRadius;
1799+ v[4].color = packedColor;
1800+ v[5].x = w;
1801+ v[5].y = h - clampedRadius;
1802+ v[5].color = packedColor;
1803+ v[6].x = clampedRadius;
1804+ v[6].y = h;
1805+ v[6].color = packedColor;
1806+ v[7].x = w - clampedRadius;
1807+ v[7].y = h;
1808+ v[7].color = packedColor;
1809+ markDirty(QSGNode::DirtyGeometry);
1810+ break;
1811+ }
1812+
1813+ case (HasColor | HasShadow): {
1814+ UCShapeFillCenterShadowResources::Vertex* v =
1815+ reinterpret_cast<UCShapeFillCenterShadowResources::Vertex*>(
1816+ m_resources->geometry()->vertexData());
1817+ float s, c;
1818+ sincosf(shadowAngle * -(M_PI / 180.0f), &s, &c);
1819+ const float offsetX = roundf(c * shadowDistance);
1820+ const float offsetY = roundf(s * shadowDistance);
1821+ const float clampedShadow = qMin(floorf(shadowSize), maxSize);
1822+ const float border = 1.0f;
1823+ const float textureSize = (2.0f * clampedShadow + 2.0f * border + clampedRadius) * dpr;
1824+ const float textureSizeRounded = roundUp(static_cast<int>(textureSize), textureRounding);
1825+ const float textureOffset = (textureSizeRounded - textureSize) / textureSizeRounded;
1826+ const float textureFactor = ((1.0f - textureOffset) * dpr) / textureSize;
1827+ const float midShadowS =
1828+ (border + clampedShadow + (w * 0.5f)) * textureFactor + textureOffset;
1829+ const float midShadowT =
1830+ (border + clampedShadow + (h * 0.5f)) * textureFactor + textureOffset;
1831+ const quint32 packedShadowColor = packColor(shadowColor);
1832+ v[0].x = clampedRadius;
1833+ v[0].y = 0.0f;
1834+ v[0].shadowS = (offsetX + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
1835+ v[0].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
1836+ v[0].midShadowS = midShadowS;
1837+ v[0].midShadowT = midShadowT;
1838+ v[0].color = packedColor;
1839+ v[0].shadowColor = packedShadowColor;
1840+ v[1].x = w - clampedRadius;
1841+ v[1].y = 0.0f;
1842+ v[1].shadowS =
1843+ (offsetX + border + clampedShadow + (w - clampedRadius)) * textureFactor + textureOffset;
1844+ v[1].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
1845+ v[1].midShadowS = midShadowS;
1846+ v[1].midShadowT = midShadowT;
1847+ v[1].color = packedColor;
1848+ v[1].shadowColor = packedShadowColor;
1849+ v[2].x = 0.0f;
1850+ v[2].y = clampedRadius;
1851+ v[2].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
1852+ v[2].shadowT = (offsetY + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
1853+ v[2].midShadowS = midShadowS;
1854+ v[2].midShadowT = midShadowT;
1855+ v[2].color = packedColor;
1856+ v[2].shadowColor = packedShadowColor;
1857+ v[3].x = w;
1858+ v[3].y = clampedRadius;
1859+ v[3].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
1860+ v[3].shadowT = (offsetY + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
1861+ v[3].midShadowS = midShadowS;
1862+ v[3].midShadowT = midShadowT;
1863+ v[3].color = packedColor;
1864+ v[3].shadowColor = packedShadowColor;
1865+ v[4].x = 0.0f;
1866+ v[4].y = h - clampedRadius;
1867+ v[4].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
1868+ v[4].shadowT =
1869+ (offsetY + border + clampedShadow + (h - clampedRadius)) * textureFactor + textureOffset;
1870+ v[4].midShadowS = midShadowS;
1871+ v[4].midShadowT = midShadowT;
1872+ v[4].color = packedColor;
1873+ v[4].shadowColor = packedShadowColor;
1874+ v[5].x = w;
1875+ v[5].y = h - clampedRadius;
1876+ v[5].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
1877+ v[5].shadowT =
1878+ (offsetY + border + clampedShadow + (h - clampedRadius)) * textureFactor + textureOffset;
1879+ v[5].midShadowS = midShadowS;
1880+ v[5].midShadowT = midShadowT;
1881+ v[5].color = packedColor;
1882+ v[5].shadowColor = packedShadowColor;
1883+ v[6].x = clampedRadius;
1884+ v[6].y = h;
1885+ v[6].shadowS = (offsetX + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
1886+ v[6].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
1887+ v[6].midShadowS = midShadowS;
1888+ v[6].midShadowT = midShadowT;
1889+ v[6].color = packedColor;
1890+ v[6].shadowColor = packedShadowColor;
1891+ v[7].x = w - clampedRadius;
1892+ v[7].y = h;
1893+ v[7].shadowS =
1894+ (offsetX + border + clampedShadow + (w - clampedRadius)) * textureFactor + textureOffset;
1895+ v[7].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
1896+ v[7].midShadowS = midShadowS;
1897+ v[7].midShadowT = midShadowT;
1898+ v[7].color = packedColor;
1899+ v[7].shadowColor = packedShadowColor;
1900+ markDirty(QSGNode::DirtyGeometry);
1901+
1902+ // Update data for the preprocess() call.
1903+ const quint16 deviceShadow = static_cast<quint16>(clampedShadow * dpr);
1904+ if (m_shadow != deviceShadow) {
1905+ m_shadow = deviceShadow;
1906+ m_flags |= DirtyShadow;
1907+ }
1908+ const quint16 deviceRadius = static_cast<quint16>(clampedRadius * dpr);
1909+ if (m_radius != deviceRadius) {
1910+ m_radius = deviceRadius;
1911+ m_flags |= DirtyRadius;
1912+ }
1913+ if (m_shape != static_cast<quint8>(type)) {
1914+ m_shape = static_cast<quint8>(type);
1915+ m_flags |= DirtyShape;
1916+ }
1917+ break;
1918+ }
1919+
1920+ case (HasColor | HasBorder): {
1921+ UCShapeFillCenterBorderResources::Vertex* v =
1922+ reinterpret_cast<UCShapeFillCenterBorderResources::Vertex*>(
1923+ m_resources->geometry()->vertexData());
1924+ const float midW = w * 0.5f;
1925+ const float midH = h * 0.5f;
1926+ const float clampedBorder = qMin(floorf(borderSize), maxSize);
1927+ const float clampedBorderRadius =
1928+ floorf(((maxSize - clampedBorder) / maxSize) * clampedRadius);
1929+ const float textureBorder = 1.0f;
1930+ const float borderTextureSize = (2.0f * textureBorder + clampedBorderRadius) * dpr;
1931+ const float borderTextureSizeRounded =
1932+ roundUp(static_cast<int>(borderTextureSize), textureRounding);
1933+ const float borderTextureOffset =
1934+ (borderTextureSizeRounded - borderTextureSize) / borderTextureSizeRounded;
1935+ const float borderTextureFactor = ((1.0f - borderTextureOffset) * dpr) / borderTextureSize;
1936+ const float borderOffset = -(clampedBorder - textureBorder);
1937+ const quint32 packedBorderColor = packColor(borderColor);
1938+ v[0].x = clampedRadius;
1939+ v[0].y = 0.0f;
1940+ v[0].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
1941+ v[0].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
1942+ v[0].color = packedColor;
1943+ v[0].borderColor = packedBorderColor;
1944+ v[1].x = midW;
1945+ v[1].y = 0.0f;
1946+ v[1].borderS = (midW + borderOffset) * borderTextureFactor + borderTextureOffset;
1947+ v[1].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
1948+ v[1].color = packedColor;
1949+ v[1].borderColor = packedBorderColor;
1950+ v[2].x = w - clampedRadius;
1951+ v[2].y = 0.0f;
1952+ v[2].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
1953+ v[2].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
1954+ v[2].color = packedColor;
1955+ v[2].borderColor = packedBorderColor;
1956+ v[3].x = 0.0f;
1957+ v[3].y = clampedRadius;
1958+ v[3].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
1959+ v[3].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
1960+ v[3].color = packedColor;
1961+ v[3].borderColor = packedBorderColor;
1962+ v[4].x = w;
1963+ v[4].y = clampedRadius;
1964+ v[4].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
1965+ v[4].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
1966+ v[4].color = packedColor;
1967+ v[4].borderColor = packedBorderColor;
1968+ v[5].x = 0.0f;
1969+ v[5].y = midH;
1970+ v[5].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
1971+ v[5].borderT = (midH + borderOffset) * borderTextureFactor + borderTextureOffset;
1972+ v[5].color = packedColor;
1973+ v[5].borderColor = packedBorderColor;
1974+ v[6].x = midW;
1975+ v[6].y = midH;
1976+ v[6].borderS = (midW + borderOffset) * borderTextureFactor + borderTextureOffset;
1977+ v[6].borderT = (midH + borderOffset) * borderTextureFactor + borderTextureOffset;
1978+ v[6].color = packedColor;
1979+ v[6].borderColor = packedBorderColor;
1980+ v[7].x = w;
1981+ v[7].y = midH;
1982+ v[7].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
1983+ v[7].borderT = (midH + borderOffset) * borderTextureFactor + borderTextureOffset;
1984+ v[7].color = packedColor;
1985+ v[7].borderColor = packedBorderColor;
1986+ v[8].x = 0.0f;
1987+ v[8].y = h - clampedRadius;
1988+ v[8].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
1989+ v[8].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
1990+ v[8].color = packedColor;
1991+ v[8].borderColor = packedBorderColor;
1992+ v[9].x = w;
1993+ v[9].y = h - clampedRadius;
1994+ v[9].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
1995+ v[9].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
1996+ v[9].color = packedColor;
1997+ v[9].borderColor = packedBorderColor;
1998+ v[10].x = clampedRadius;
1999+ v[10].y = h;
2000+ v[10].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2001+ v[10].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2002+ v[10].color = packedColor;
2003+ v[10].borderColor = packedBorderColor;
2004+ v[11].x = midW;
2005+ v[11].y = h;
2006+ v[11].borderS = (midW + borderOffset) * borderTextureFactor + borderTextureOffset;
2007+ v[11].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2008+ v[11].color = packedColor;
2009+ v[11].borderColor = packedBorderColor;
2010+ v[12].x = w - clampedRadius;
2011+ v[12].y = h;
2012+ v[12].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2013+ v[12].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2014+ v[12].color = packedColor;
2015+ v[12].borderColor = packedBorderColor;
2016+ markDirty(QSGNode::DirtyGeometry);
2017+
2018+ // Update data for the preprocess() call.
2019+ const quint16 deviceRadius = static_cast<quint16>(clampedRadius * dpr);
2020+ if (m_radius != deviceRadius) {
2021+ m_radius = deviceRadius;
2022+ m_flags |= DirtyRadius;
2023+ }
2024+ const quint16 deviceBorderRadius = static_cast<quint16>(clampedBorderRadius * dpr);
2025+ if (m_borderRadius != deviceBorderRadius) {
2026+ m_borderRadius = deviceBorderRadius;
2027+ m_flags |= DirtyBorderRadius;
2028+ }
2029+ if (m_shape != static_cast<quint8>(type)) {
2030+ m_shape = static_cast<quint8>(type);
2031+ m_flags |= DirtyShape;
2032+ }
2033+ break;
2034+ }
2035+
2036+ case (HasColor | HasShadow | HasBorder): {
2037+ UCShapeFillCenterShadowBorderResources::Vertex* v =
2038+ reinterpret_cast<UCShapeFillCenterShadowBorderResources::Vertex*>(
2039+ m_resources->geometry()->vertexData());
2040+ float s, c;
2041+ sincosf(shadowAngle * -(M_PI / 180.0f), &s, &c);
2042+ const float offsetX = roundf(c * shadowDistance);
2043+ const float offsetY = roundf(s * shadowDistance);
2044+ const float clampedShadow = qMin(floorf(shadowSize), maxSize);
2045+ const float border = 1.0f;
2046+ const float textureSize = (2.0f * clampedShadow + 2.0f * border + clampedRadius) * dpr;
2047+ const float textureSizeRounded = roundUp(static_cast<int>(textureSize), textureRounding);
2048+ const float textureOffset = (textureSizeRounded - textureSize) / textureSizeRounded;
2049+ const float textureFactor = ((1.0f - textureOffset) * dpr) / textureSize;
2050+ const float midW = w * 0.5f;
2051+ const float midH = h * 0.5f;
2052+ const float midShadowS = (border + clampedShadow + midW) * textureFactor + textureOffset;
2053+ const float midShadowT = (border + clampedShadow + midH) * textureFactor + textureOffset;
2054+ const float clampedBorder = qMin(floorf(borderSize), maxSize);
2055+ const float clampedBorderRadius =
2056+ floorf(((maxSize - clampedBorder) / maxSize) * clampedRadius);
2057+ const float textureBorder = 1.0f;
2058+ const float borderTextureSize = (2.0f * textureBorder + clampedBorderRadius) * dpr;
2059+ const float borderTextureSizeRounded =
2060+ roundUp(static_cast<int>(borderTextureSize), textureRounding);
2061+ const float borderTextureOffset =
2062+ (borderTextureSizeRounded - borderTextureSize) / borderTextureSizeRounded;
2063+ const float borderTextureFactor = ((1.0f - borderTextureOffset) * dpr) / borderTextureSize;
2064+ const float borderOffset = -(clampedBorder - textureBorder);
2065+ const quint32 packedShadowColor = packColor(shadowColor);
2066+ const quint32 packedBorderColor = packColor(borderColor);
2067+ v[0].x = clampedRadius;
2068+ v[0].y = 0.0f;
2069+ v[0].shadowS = (offsetX + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2070+ v[0].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2071+ v[0].midShadowS = midShadowS;
2072+ v[0].midShadowT = midShadowT;
2073+ v[0].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2074+ v[0].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2075+ v[0].color = packedColor;
2076+ v[0].shadowColor = packedShadowColor;
2077+ v[0].borderColor = packedBorderColor;
2078+ v[1].x = midW;
2079+ v[1].y = 0.0f;
2080+ v[1].shadowS = (offsetX + border + clampedShadow + midW) * textureFactor + textureOffset;
2081+ v[1].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2082+ v[1].midShadowS = midShadowS;
2083+ v[1].midShadowT = midShadowT;
2084+ v[1].borderS = (midW + borderOffset) * borderTextureFactor + borderTextureOffset;
2085+ v[1].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2086+ v[1].color = packedColor;
2087+ v[1].shadowColor = packedShadowColor;
2088+ v[1].borderColor = packedBorderColor;
2089+ v[2].x = w - clampedRadius;
2090+ v[2].y = 0.0f;
2091+ v[2].shadowS =
2092+ (offsetX + border + clampedShadow + (w - clampedRadius)) * textureFactor + textureOffset;
2093+ v[2].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2094+ v[2].midShadowS = midShadowS;
2095+ v[2].midShadowT = midShadowT;
2096+ v[2].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2097+ v[2].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2098+ v[2].color = packedColor;
2099+ v[2].shadowColor = packedShadowColor;
2100+ v[2].borderColor = packedBorderColor;
2101+ v[3].x = 0.0f;
2102+ v[3].y = clampedRadius;
2103+ v[3].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2104+ v[3].shadowT = (offsetY + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2105+ v[3].midShadowS = midShadowS;
2106+ v[3].midShadowT = midShadowT;
2107+ v[3].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2108+ v[3].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2109+ v[3].color = packedColor;
2110+ v[3].shadowColor = packedShadowColor;
2111+ v[3].borderColor = packedBorderColor;
2112+ v[4].x = w;
2113+ v[4].y = clampedRadius;
2114+ v[4].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2115+ v[4].shadowT = (offsetY + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2116+ v[4].midShadowS = midShadowS;
2117+ v[4].midShadowT = midShadowT;
2118+ v[4].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2119+ v[4].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2120+ v[4].color = packedColor;
2121+ v[4].shadowColor = packedShadowColor;
2122+ v[4].borderColor = packedBorderColor;
2123+ v[5].x = 0.0f;
2124+ v[5].y = midH;
2125+ v[5].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2126+ v[5].shadowT = (offsetY + border + clampedShadow + midH) * textureFactor + textureOffset;
2127+ v[5].midShadowS = midShadowS;
2128+ v[5].midShadowT = midShadowT;
2129+ v[5].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2130+ v[5].borderT = (midH + borderOffset) * borderTextureFactor + borderTextureOffset;
2131+ v[5].color = packedColor;
2132+ v[5].shadowColor = packedShadowColor;
2133+ v[5].borderColor = packedBorderColor;
2134+ v[6].x = midW;
2135+ v[6].y = midH;
2136+ v[6].shadowS = (offsetX + border + clampedShadow + midW) * textureFactor + textureOffset;
2137+ v[6].shadowT = (offsetY + border + clampedShadow + midH) * textureFactor + textureOffset;
2138+ v[6].midShadowS = midShadowS;
2139+ v[6].midShadowT = midShadowT;
2140+ v[6].borderS = (midW + borderOffset) * borderTextureFactor + borderTextureOffset;
2141+ v[6].borderT = (midH + borderOffset) * borderTextureFactor + borderTextureOffset;
2142+ v[6].color = packedColor;
2143+ v[6].shadowColor = packedShadowColor;
2144+ v[6].borderColor = packedBorderColor;
2145+ v[7].x = w;
2146+ v[7].y = midH;
2147+ v[7].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2148+ v[7].shadowT = (offsetY + border + clampedShadow + midH) * textureFactor + textureOffset;
2149+ v[7].midShadowS = midShadowS;
2150+ v[7].midShadowT = midShadowT;
2151+ v[7].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2152+ v[7].borderT = (midH + borderOffset) * borderTextureFactor + borderTextureOffset;
2153+ v[7].color = packedColor;
2154+ v[7].shadowColor = packedShadowColor;
2155+ v[7].borderColor = packedBorderColor;
2156+ v[8].x = 0.0f;
2157+ v[8].y = h - clampedRadius;
2158+ v[8].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2159+ v[8].shadowT =
2160+ (offsetY + border + clampedShadow + (h - clampedRadius)) * textureFactor + textureOffset;
2161+ v[8].midShadowS = midShadowS;
2162+ v[8].midShadowT = midShadowT;
2163+ v[8].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2164+ v[8].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2165+ v[8].color = packedColor;
2166+ v[8].shadowColor = packedShadowColor;
2167+ v[8].borderColor = packedBorderColor;
2168+ v[9].x = w;
2169+ v[9].y = h - clampedRadius;
2170+ v[9].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2171+ v[9].shadowT =
2172+ (offsetY + border + clampedShadow + (h - clampedRadius)) * textureFactor + textureOffset;
2173+ v[9].midShadowS = midShadowS;
2174+ v[9].midShadowT = midShadowT;
2175+ v[9].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2176+ v[9].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2177+ v[9].color = packedColor;
2178+ v[9].shadowColor = packedShadowColor;
2179+ v[9].borderColor = packedBorderColor;
2180+ v[10].x = clampedRadius;
2181+ v[10].y = h;
2182+ v[10].shadowS = (offsetX + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2183+ v[10].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2184+ v[10].midShadowS = midShadowS;
2185+ v[10].midShadowT = midShadowT;
2186+ v[10].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2187+ v[10].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2188+ v[10].color = packedColor;
2189+ v[10].shadowColor = packedShadowColor;
2190+ v[10].borderColor = packedBorderColor;
2191+ v[11].x = midW;
2192+ v[11].y = h;
2193+ v[11].shadowS = (offsetX + border + clampedShadow + midW) * textureFactor + textureOffset;
2194+ v[11].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2195+ v[11].midShadowS = midShadowS;
2196+ v[11].midShadowT = midShadowT;
2197+ v[11].borderS = (midW + borderOffset) * borderTextureFactor + borderTextureOffset;
2198+ v[11].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2199+ v[11].color = packedColor;
2200+ v[11].shadowColor = packedShadowColor;
2201+ v[11].borderColor = packedBorderColor;
2202+ v[12].x = w - clampedRadius;
2203+ v[12].y = h;
2204+ v[12].shadowS =
2205+ (offsetX + border + clampedShadow + (w - clampedRadius)) * textureFactor + textureOffset;
2206+ v[12].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2207+ v[12].midShadowS = midShadowS;
2208+ v[12].midShadowT = midShadowT;
2209+ v[12].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2210+ v[12].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2211+ v[12].color = packedColor;
2212+ v[12].shadowColor = packedShadowColor;
2213+ v[12].borderColor = packedBorderColor;
2214+ markDirty(QSGNode::DirtyGeometry);
2215+
2216+ // Update data for the preprocess() call.
2217+ const quint16 deviceRadius = static_cast<quint16>(clampedRadius * dpr);
2218+ if (m_radius != deviceRadius) {
2219+ m_radius = deviceRadius;
2220+ m_flags |= DirtyRadius;
2221+ }
2222+ const quint16 deviceShadow = static_cast<quint16>(clampedShadow * dpr);
2223+ if (m_shadow != deviceShadow) {
2224+ m_shadow = deviceShadow;
2225+ m_flags |= DirtyShadow;
2226+ }
2227+ const quint16 deviceBorderRadius = static_cast<quint16>(clampedBorderRadius * dpr);
2228+ if (m_borderRadius != deviceBorderRadius) {
2229+ m_borderRadius = deviceBorderRadius;
2230+ m_flags |= DirtyBorderRadius;
2231+ }
2232+ if (m_shape != static_cast<quint8>(type)) {
2233+ m_shape = static_cast<quint8>(type);
2234+ m_flags |= DirtyShape;
2235+ }
2236+ break;
2237+ }
2238+
2239+ default:
2240+ DNOT_REACHED();
2241+ }
2242+
2243+ // Update the blending state of the opaque material (in QSG terms, an opaque
2244+ // material is the material automatically used when the opacity is 1, but
2245+ // even if the opacity is 1 we have to handle the case where the alpha of
2246+ // the specified color is less than 1).
2247+ const bool blending = qAlpha(color) < 255;
2248+ if (blending != static_cast<bool>(m_flags & Blending)) {
2249+ m_resources->opaqueMaterial()->setFlag(QSGMaterial::Blending, blending);
2250+ markDirty(QSGNode::DirtyMaterial);
2251+ m_flags = (m_flags & ~Blending) | (blending ? Blending : 0);
2252+ }
2253+}
2254+
2255+UCShapeFillCornersNode::UCShapeFillCornersNode()
2256+ : QSGGeometryNode()
2257+ , m_resources(Q_NULLPTR)
2258+ , m_radius(0)
2259+ , m_shadow(0)
2260+ , m_borderRadius(0)
2261+ , m_flags(0)
2262+ , m_shape(UCShapeType::Squircle)
2263+{
2264+ DLOG("creating UCShapeFillCornersNode");
2265+ setFlag(QSGNode::UsePreprocess, true);
2266+ qsgnode_set_description(this, QLatin1String("shapefillcorners"));
2267+}
2268+
2269+UCShapeFillCornersNode::~UCShapeFillCornersNode()
2270+{
2271+ DLOG("detroying UCShapeFillCornersNode");
2272+ delete m_resources;
2273+}
2274+
2275+void UCShapeFillCornersNode::preprocess()
2276+{
2277+ // FIXME(loicm) Could be made more consise (texture update methods in the resources?).
2278+
2279+ switch (m_flags & StyleMask) {
2280+ case (HasColor):
2281+ if (m_flags & (DirtyRadius | DirtyShape)) {
2282+ static_cast<UCShapeColorMaskMaterial<false>*>(
2283+ m_resources->material())->updateMaskTexture(
2284+ static_cast<UCShapeType>(m_shape), m_radius);
2285+ static_cast<UCShapeColorMaskMaterial<true>*>(
2286+ m_resources->opaqueMaterial())->updateMaskTexture(
2287+ static_cast<UCShapeType>(m_shape), m_radius);
2288+ }
2289+ break;
2290+
2291+ case (HasColor | HasShadow):
2292+ if (m_flags & (DirtyRadius | DirtyShadow | DirtyShape)) {
2293+ static_cast<UCShapeFillCornersShadowMaterial<false>*>(
2294+ m_resources->material())->updateShadowTexture(
2295+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
2296+ static_cast<UCShapeFillCornersShadowMaterial<true>*>(
2297+ m_resources->opaqueMaterial())->updateShadowTexture(
2298+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
2299+ }
2300+ break;
2301+
2302+ case (HasColor | HasBorder):
2303+ if (m_flags & (DirtyRadius | DirtyShape)) {
2304+ static_cast<UCShapeFillCornersBorderMaterial<false>*>(
2305+ m_resources->material())->updateMaskTexture(
2306+ static_cast<UCShapeType>(m_shape), m_radius);
2307+ static_cast<UCShapeFillCornersBorderMaterial<true>*>(
2308+ m_resources->opaqueMaterial())->updateMaskTexture(
2309+ static_cast<UCShapeType>(m_shape), m_radius);
2310+ }
2311+ if (m_flags & (DirtyBorderRadius | DirtyShape)) {
2312+ static_cast<UCShapeFillCornersBorderMaterial<false>*>(
2313+ m_resources->material())->updateBorderTexture(
2314+ static_cast<UCShapeType>(m_shape), m_borderRadius);
2315+ static_cast<UCShapeFillCornersBorderMaterial<true>*>(
2316+ m_resources->opaqueMaterial())->updateBorderTexture(
2317+ static_cast<UCShapeType>(m_shape), m_borderRadius);
2318+ }
2319+ break;
2320+
2321+ case (HasColor | HasShadow | HasBorder):
2322+ if (m_flags & (DirtyRadius | DirtyShadow | DirtyShape)) {
2323+ static_cast<UCShapeFillCornersShadowBorderMaterial<false>*>(
2324+ m_resources->material())->updateShadowTexture(
2325+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
2326+ static_cast<UCShapeFillCornersShadowBorderMaterial<true>*>(
2327+ m_resources->opaqueMaterial())->updateShadowTexture(
2328+ static_cast<UCShapeType>(m_shape), m_radius, m_shadow);
2329+ }
2330+ if (m_flags & (DirtyBorderRadius | DirtyShape)) {
2331+ static_cast<UCShapeFillCornersShadowBorderMaterial<false>*>(
2332+ m_resources->material())->updateBorderTexture(
2333+ static_cast<UCShapeType>(m_shape), m_borderRadius);
2334+ static_cast<UCShapeFillCornersShadowBorderMaterial<true>*>(
2335+ m_resources->opaqueMaterial())->updateBorderTexture(
2336+ static_cast<UCShapeType>(m_shape), m_borderRadius);
2337+ }
2338+ break;
2339+
2340+ default:
2341+ NOT_REACHED();
2342+ }
2343+
2344+ m_flags &= ~DirtyMask;
2345+}
2346+
2347+void UCShapeFillCornersNode::setVisible(bool visible)
2348+{
2349+ DLOG("UCShapeFillCornersNode::setVisible %d", visible);
2350+ if (static_cast<bool>(m_flags & Visible) != visible) {
2351+ m_flags = (m_flags & ~Visible) | (visible ? Visible : 0);
2352+ markDirty(DirtySubtreeBlocked);
2353+ }
2354+}
2355+
2356+void UCShapeFillCornersNode::update(
2357+ const QSizeF& itemSize, UCShapeType type, float radius, QRgb color, float shadowSize,
2358+ float shadowAngle, float shadowDistance, QRgb shadowColor, float borderSize, QRgb borderColor)
2359+{
2360+ // The geometry is made of 12 vertices indexed with a triangles mode.
2361+ // 0 - 1 2 - 3
2362+ // | / \ |
2363+ // 4 5
2364+ //
2365+ // 6 7
2366+ // | \ / |
2367+ // 8 - 9 10 - 11
2368+ const quint16 indices[] = { 1, 0, 4, 6, 8, 9, 10, 11, 7, 5, 3, 2 };
2369+ const int indexCount = ARRAY_SIZE(indices);
2370+ const int vertexCount = 12;
2371+
2372+ quint16 style = ((shadowSize <= 0.0f && shadowDistance <= 0.0f) || (qAlpha(shadowColor) == 0)) ?
2373+ HasColor : (HasColor | HasShadow);
2374+ if (borderSize >= 1.0f) {
2375+ style |= HasBorder;
2376+ }
2377+
2378+ // Create new material/geometry set if needed.
2379+ if (style != (m_flags & StyleMask)) {
2380+ delete m_resources;
2381+ switch (style) {
2382+ case HasColor:
2383+ m_resources = new UCShapeColorMaskResources(vertexCount, indexCount);
2384+ break;
2385+ case (HasColor | HasShadow):
2386+ m_resources = new UCShapeFillCornersShadowResources(vertexCount, indexCount);
2387+ break;
2388+ case (HasColor | HasBorder):
2389+ m_resources = new UCShapeFillCornersBorderResources(vertexCount, indexCount);
2390+ break;
2391+ case (HasColor | HasShadow | HasBorder):
2392+ m_resources = new UCShapeFillCornersShadowBorderResources(vertexCount, indexCount);
2393+ break;
2394+ default:
2395+ NOT_REACHED();
2396+ }
2397+ setMaterial(m_resources->material());
2398+ m_resources->opaqueMaterial()->setFlag(QSGMaterial::Blending);
2399+ setOpaqueMaterial(m_resources->opaqueMaterial());
2400+ memcpy(m_resources->geometry()->indexData(), indices, indexCount * sizeof(quint16));
2401+ setGeometry(m_resources->geometry());
2402+ m_flags = (m_flags & ~StyleMask) | style | DirtyMask;
2403+ }
2404+
2405+ const float dpr = qGuiApp->devicePixelRatio();
2406+ const float w = floorf(static_cast<float>(itemSize.width()));
2407+ const float h = floorf(static_cast<float>(itemSize.height()));
2408+ // Rounded down since Shadow doesn't support sub-pixel rendering.
2409+ const float maxSize = floorf(qMin(w, h) * 0.5f);
2410+ const float clampedRadius = qMin(floorf(radius), maxSize);
2411+ const quint32 packedColor = packColor(color);
2412+
2413+ // Update geometry depending on the style.
2414+ switch (style) {
2415+ case HasColor: {
2416+ UCShapeColorMaskResources::Vertex* v =
2417+ reinterpret_cast<UCShapeColorMaskResources::Vertex*>(
2418+ m_resources->geometry()->vertexData());
2419+ const float deviceRadius = clampedRadius * dpr;
2420+ const float border = 1.0f;
2421+ const float textureSize = deviceRadius + 2 * border;
2422+ const float textureSizeRounded = roundUp(static_cast<int>(textureSize), textureRounding);
2423+ const float textureStart = (textureSizeRounded - textureSize + border) / textureSizeRounded;
2424+ const float textureEnd = (textureSizeRounded - border) / textureSizeRounded;
2425+ v[0].x = 0.0f;
2426+ v[0].y = 0.0f;
2427+ v[0].maskS = textureStart;
2428+ v[0].maskT = textureStart;
2429+ v[0].color = packedColor;
2430+ v[1].x = clampedRadius;
2431+ v[1].y = 0.0f;
2432+ v[1].maskS = textureEnd;
2433+ v[1].maskT = textureStart;
2434+ v[1].color = packedColor;
2435+ v[2].x = w - clampedRadius;
2436+ v[2].y = 0.0f;
2437+ v[2].maskS = textureEnd;
2438+ v[2].maskT = textureStart;
2439+ v[2].color = packedColor;
2440+ v[3].x = w;
2441+ v[3].y = 0.0f;
2442+ v[3].maskS = textureStart;
2443+ v[3].maskT = textureStart;
2444+ v[3].color = packedColor;
2445+ v[4].x = 0.0f;
2446+ v[4].y = clampedRadius;
2447+ v[4].maskS = textureStart;
2448+ v[4].maskT = textureEnd;
2449+ v[4].color = packedColor;
2450+ v[5].x = w;
2451+ v[5].y = clampedRadius;
2452+ v[5].maskS = textureStart;
2453+ v[5].maskT = textureEnd;
2454+ v[5].color = packedColor;
2455+ v[6].x = 0.0f;
2456+ v[6].y = h - clampedRadius;
2457+ v[6].maskS = textureStart;
2458+ v[6].maskT = textureEnd;
2459+ v[6].color = packedColor;
2460+ v[7].x = w;
2461+ v[7].y = h - clampedRadius;
2462+ v[7].maskS = textureStart;
2463+ v[7].maskT = textureEnd;
2464+ v[7].color = packedColor;
2465+ v[8].x = 0.0f;
2466+ v[8].y = h;
2467+ v[8].maskS = textureStart;
2468+ v[8].maskT = textureStart;
2469+ v[8].color = packedColor;
2470+ v[9].x = clampedRadius;
2471+ v[9].y = h;
2472+ v[9].maskS = textureEnd;
2473+ v[9].maskT = textureStart;
2474+ v[9].color = packedColor;
2475+ v[10].x = w - clampedRadius;
2476+ v[10].y = h;
2477+ v[10].maskS = textureEnd;
2478+ v[10].maskT = textureStart;
2479+ v[10].color = packedColor;
2480+ v[11].x = w;
2481+ v[11].y = h;
2482+ v[11].maskS = textureStart;
2483+ v[11].maskT = textureStart;
2484+ v[11].color = packedColor;
2485+ markDirty(QSGNode::DirtyGeometry);
2486+
2487+ // Update data for the preprocess() call.
2488+ if (m_radius != static_cast<quint16>(deviceRadius)) {
2489+ m_radius = static_cast<quint16>(deviceRadius);
2490+ m_flags |= DirtyRadius;
2491+ }
2492+ if (m_shape != static_cast<quint8>(type)) {
2493+ m_shape = static_cast<quint8>(type);
2494+ m_flags |= DirtyShape;
2495+ }
2496+ break;
2497+ }
2498+
2499+ case (HasColor | HasShadow): {
2500+ UCShapeFillCornersShadowResources::Vertex* v =
2501+ reinterpret_cast<UCShapeFillCornersShadowResources::Vertex*>(
2502+ m_resources->geometry()->vertexData());
2503+ float s, c;
2504+ sincosf(shadowAngle * -(M_PI / 180.0f), &s, &c);
2505+ const float offsetX = roundf(c * shadowDistance);
2506+ const float offsetY = roundf(s * shadowDistance);
2507+ const float clampedShadow = qMin(floorf(shadowSize), maxSize);
2508+ const float border = 1.0f;
2509+ const float textureSize = (2.0f * clampedShadow + 2.0f * border + clampedRadius) * dpr;
2510+ const float textureSizeRounded = roundUp(static_cast<int>(textureSize), textureRounding);
2511+ const float textureOffset = (textureSizeRounded - textureSize) / textureSizeRounded;
2512+ const float textureFactor = ((1.0f - textureOffset) * dpr) / textureSize;
2513+ const float midShadowS = (border + clampedShadow + (w * 0.5f)) * textureFactor + textureOffset;
2514+ const float midShadowT = (border + clampedShadow + (h * 0.5f)) * textureFactor + textureOffset;
2515+ const quint32 packedShadowColor = packColor(shadowColor);
2516+ v[0].x = 0.0f;
2517+ v[0].y = 0.0f;
2518+ v[0].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2519+ v[0].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2520+ v[0].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2521+ v[0].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2522+ v[0].midShadowS = midShadowS;
2523+ v[0].midShadowT = midShadowT;
2524+ v[0].color = packedColor;
2525+ v[0].shadowColor = packedShadowColor;
2526+ v[1].x = clampedRadius;
2527+ v[1].y = 0.0f;
2528+ v[1].maskS = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2529+ v[1].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2530+ v[1].shadowS = (offsetX + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2531+ v[1].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2532+ v[1].midShadowS = midShadowS;
2533+ v[1].midShadowT = midShadowT;
2534+ v[1].color = packedColor;
2535+ v[1].shadowColor = packedShadowColor;
2536+ v[2].x = w - clampedRadius;
2537+ v[2].y = 0.0f;
2538+ v[2].maskS = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2539+ v[2].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2540+ v[2].shadowS =
2541+ (offsetX + border + clampedShadow + (w - clampedRadius)) * textureFactor + textureOffset;
2542+ v[2].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2543+ v[2].midShadowS = midShadowS;
2544+ v[2].midShadowT = midShadowT;
2545+ v[2].color = packedColor;
2546+ v[2].shadowColor = packedShadowColor;
2547+ v[3].x = w;
2548+ v[3].y = 0.0f;
2549+ v[3].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2550+ v[3].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2551+ v[3].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2552+ v[3].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2553+ v[3].midShadowS = midShadowS;
2554+ v[3].midShadowT = midShadowT;
2555+ v[3].color = packedColor;
2556+ v[3].shadowColor = packedShadowColor;
2557+ v[4].x = 0.0f;
2558+ v[4].y = clampedRadius;
2559+ v[4].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2560+ v[4].maskT = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2561+ v[4].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2562+ v[4].shadowT = (offsetY + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2563+ v[4].midShadowS = midShadowS;
2564+ v[4].midShadowT = midShadowT;
2565+ v[4].color = packedColor;
2566+ v[4].shadowColor = packedShadowColor;
2567+ v[5].x = w;
2568+ v[5].y = clampedRadius;
2569+ v[5].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2570+ v[5].maskT = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2571+ v[5].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2572+ v[5].shadowT = (offsetY + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2573+ v[5].midShadowS = midShadowS;
2574+ v[5].midShadowT = midShadowT;
2575+ v[5].color = packedColor;
2576+ v[5].shadowColor = packedShadowColor;
2577+ v[6].x = 0.0f;
2578+ v[6].y = h - clampedRadius;
2579+ v[6].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2580+ v[6].maskT = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2581+ v[6].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2582+ v[6].shadowT =
2583+ (offsetY + border + clampedShadow + (h - clampedRadius)) * textureFactor + textureOffset;
2584+ v[6].midShadowS = midShadowS;
2585+ v[6].midShadowT = midShadowT;
2586+ v[6].color = packedColor;
2587+ v[6].shadowColor = packedShadowColor;
2588+ v[7].x = w;
2589+ v[7].y = h - clampedRadius;
2590+ v[7].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2591+ v[7].maskT = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2592+ v[7].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2593+ v[7].shadowT =
2594+ (offsetY + border + clampedShadow + (h - clampedRadius)) * textureFactor + textureOffset;
2595+ v[7].midShadowS = midShadowS;
2596+ v[7].midShadowT = midShadowT;
2597+ v[7].color = packedColor;
2598+ v[7].shadowColor = packedShadowColor;
2599+ v[8].x = 0.0f;
2600+ v[8].y = h;
2601+ v[8].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2602+ v[8].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2603+ v[8].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2604+ v[8].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2605+ v[8].midShadowS = midShadowS;
2606+ v[8].midShadowT = midShadowT;
2607+ v[8].color = packedColor;
2608+ v[8].shadowColor = packedShadowColor;
2609+ v[9].x = clampedRadius;
2610+ v[9].y = h;
2611+ v[9].maskS = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2612+ v[9].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2613+ v[9].shadowS = (offsetX + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2614+ v[9].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2615+ v[9].midShadowS = midShadowS;
2616+ v[9].midShadowT = midShadowT;
2617+ v[9].color = packedColor;
2618+ v[9].shadowColor = packedShadowColor;
2619+ v[10].x = w - clampedRadius;
2620+ v[10].y = h;
2621+ v[10].maskS = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2622+ v[10].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2623+ v[10].shadowS =
2624+ (offsetX + border + clampedShadow + (w - clampedRadius)) * textureFactor + textureOffset;
2625+ v[10].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2626+ v[10].midShadowS = midShadowS;
2627+ v[10].midShadowT = midShadowT;
2628+ v[10].color = packedColor;
2629+ v[10].shadowColor = packedShadowColor;
2630+ v[11].x = w;
2631+ v[11].y = h;
2632+ v[11].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2633+ v[11].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2634+ v[11].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2635+ v[11].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2636+ v[11].midShadowS = midShadowS;
2637+ v[11].midShadowT = midShadowT;
2638+ v[11].color = packedColor;
2639+ v[11].shadowColor = packedShadowColor;
2640+ markDirty(QSGNode::DirtyGeometry);
2641+
2642+ // Update data for the preprocess() call.
2643+ const quint16 deviceShadow = static_cast<quint16>(clampedShadow * dpr);
2644+ if (m_shadow != deviceShadow) {
2645+ m_shadow = deviceShadow;
2646+ m_flags |= DirtyShadow;
2647+ }
2648+ const quint16 deviceRadius = static_cast<quint16>(clampedRadius * dpr);
2649+ if (m_radius != deviceRadius) {
2650+ m_radius = deviceRadius;
2651+ m_flags |= DirtyRadius;
2652+ }
2653+ if (m_shape != static_cast<quint8>(type)) {
2654+ m_shape = static_cast<quint8>(type);
2655+ m_flags |= DirtyShape;
2656+ }
2657+ break;
2658+ }
2659+
2660+ case (HasColor | HasBorder): {
2661+ UCShapeFillCornersBorderResources::Vertex* v =
2662+ reinterpret_cast<UCShapeFillCornersBorderResources::Vertex*>(
2663+ m_resources->geometry()->vertexData());
2664+ const float deviceRadius = clampedRadius * dpr;
2665+ const float maskBorder = 1.0f;
2666+ const float maskTextureSize = deviceRadius + 2.0f * maskBorder;
2667+ const float maskTextureSizeRounded =
2668+ roundUp(static_cast<int>(maskTextureSize), textureRounding);
2669+ const float maskTextureStart =
2670+ (maskTextureSizeRounded - maskTextureSize + maskBorder) / maskTextureSizeRounded;
2671+ const float maskTextureEnd = (maskTextureSizeRounded - maskBorder) / maskTextureSizeRounded;
2672+ const float clampedBorder = qMin(floorf(borderSize), maxSize);
2673+ const float clampedBorderRadius =
2674+ floorf(((maxSize - clampedBorder) / maxSize) * clampedRadius);
2675+ const float textureBorder = 1.0f;
2676+ const float borderTextureSize = (2.0f * textureBorder + clampedBorderRadius) * dpr;
2677+ const float borderTextureSizeRounded =
2678+ roundUp(static_cast<int>(borderTextureSize), textureRounding);
2679+ const float borderTextureOffset =
2680+ (borderTextureSizeRounded - borderTextureSize) / borderTextureSizeRounded;
2681+ const float borderTextureFactor = ((1.0f - borderTextureOffset) * dpr) / borderTextureSize;
2682+ const float borderOffset = -(clampedBorder - textureBorder);
2683+ const quint32 packedBorderColor = packColor(borderColor);
2684+ v[0].x = 0.0f;
2685+ v[0].y = 0.0f;
2686+ v[0].maskS = maskTextureStart;
2687+ v[0].maskT = maskTextureStart;
2688+ v[0].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2689+ v[0].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2690+ v[0].color = packedColor;
2691+ v[0].borderColor = packedBorderColor;
2692+ v[1].x = clampedRadius;
2693+ v[1].y = 0.0f;
2694+ v[1].maskS = maskTextureEnd;
2695+ v[1].maskT = maskTextureStart;
2696+ v[1].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2697+ v[1].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2698+ v[1].color = packedColor;
2699+ v[1].borderColor = packedBorderColor;
2700+ v[2].x = w - clampedRadius;
2701+ v[2].y = 0.0f;
2702+ v[2].maskS = maskTextureEnd;
2703+ v[2].maskT = maskTextureStart;
2704+ v[2].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2705+ v[2].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2706+ v[2].color = packedColor;
2707+ v[2].borderColor = packedBorderColor;
2708+ v[3].x = w;
2709+ v[3].y = 0.0f;
2710+ v[3].maskS = maskTextureStart;
2711+ v[3].maskT = maskTextureStart;
2712+ v[3].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2713+ v[3].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2714+ v[3].color = packedColor;
2715+ v[3].borderColor = packedBorderColor;
2716+ v[4].x = 0.0f;
2717+ v[4].y = clampedRadius;
2718+ v[4].maskS = maskTextureStart;
2719+ v[4].maskT = maskTextureEnd;
2720+ v[4].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2721+ v[4].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2722+ v[4].color = packedColor;
2723+ v[4].borderColor = packedBorderColor;
2724+ v[5].x = w;
2725+ v[5].y = clampedRadius;
2726+ v[5].maskS = maskTextureStart;
2727+ v[5].maskT = maskTextureEnd;
2728+ v[5].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2729+ v[5].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2730+ v[5].color = packedColor;
2731+ v[5].borderColor = packedBorderColor;
2732+ v[6].x = 0.0f;
2733+ v[6].y = h - clampedRadius;
2734+ v[6].maskS = maskTextureStart;
2735+ v[6].maskT = maskTextureEnd;
2736+ v[6].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2737+ v[6].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2738+ v[6].color = packedColor;
2739+ v[6].borderColor = packedBorderColor;
2740+ v[7].x = w;
2741+ v[7].y = h - clampedRadius;
2742+ v[7].maskS = maskTextureStart;
2743+ v[7].maskT = maskTextureEnd;
2744+ v[7].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2745+ v[7].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2746+ v[7].color = packedColor;
2747+ v[7].borderColor = packedBorderColor;
2748+ v[8].x = 0.0f;
2749+ v[8].y = h;
2750+ v[8].maskS = maskTextureStart;
2751+ v[8].maskT = maskTextureStart;
2752+ v[8].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2753+ v[8].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2754+ v[8].color = packedColor;
2755+ v[8].borderColor = packedBorderColor;
2756+ v[9].x = clampedRadius;
2757+ v[9].y = h;
2758+ v[9].maskS = maskTextureEnd;
2759+ v[9].maskT = maskTextureStart;
2760+ v[9].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2761+ v[9].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2762+ v[9].color = packedColor;
2763+ v[9].borderColor = packedBorderColor;
2764+ v[10].x = w - clampedRadius;
2765+ v[10].y = h;
2766+ v[10].maskS = maskTextureEnd;
2767+ v[10].maskT = maskTextureStart;
2768+ v[10].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2769+ v[10].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2770+ v[10].color = packedColor;
2771+ v[10].borderColor = packedBorderColor;
2772+ v[11].x = w;
2773+ v[11].y = h;
2774+ v[11].maskS = maskTextureStart;
2775+ v[11].maskT = maskTextureStart;
2776+ v[11].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2777+ v[11].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2778+ v[11].color = packedColor;
2779+ v[11].borderColor = packedBorderColor;
2780+ markDirty(QSGNode::DirtyGeometry);
2781+
2782+ // Update data for the preprocess() call.
2783+ if (m_radius != static_cast<quint16>(deviceRadius)) {
2784+ m_radius = static_cast<quint16>(deviceRadius);
2785+ m_flags |= DirtyRadius;
2786+ }
2787+ const quint16 deviceBorderRadius = static_cast<quint16>(clampedBorderRadius * dpr);
2788+ if (m_borderRadius != deviceBorderRadius) {
2789+ m_borderRadius = deviceBorderRadius;
2790+ m_flags |= DirtyBorderRadius;
2791+ }
2792+ if (m_shape != static_cast<quint8>(type)) {
2793+ m_shape = static_cast<quint8>(type);
2794+ m_flags |= DirtyShape;
2795+ }
2796+ break;
2797+ }
2798+
2799+ case (HasColor | HasShadow | HasBorder): {
2800+ UCShapeFillCornersShadowBorderResources::Vertex* v =
2801+ reinterpret_cast<UCShapeFillCornersShadowBorderResources::Vertex*>(
2802+ m_resources->geometry()->vertexData());
2803+ float s, c;
2804+ sincosf(shadowAngle * -(M_PI / 180.0f), &s, &c);
2805+ const float offsetX = roundf(c * shadowDistance);
2806+ const float offsetY = roundf(s * shadowDistance);
2807+ const float clampedShadow = qMin(floorf(shadowSize), maxSize);
2808+ const float border = 1.0f;
2809+ const float textureSize = (2.0f * clampedShadow + 2.0f * border + clampedRadius) * dpr;
2810+ const float textureSizeRounded = roundUp(static_cast<int>(textureSize), textureRounding);
2811+ const float textureOffset = (textureSizeRounded - textureSize) / textureSizeRounded;
2812+ const float textureFactor = ((1.0f - textureOffset) * dpr) / textureSize;
2813+ const float midShadowS = (border + clampedShadow + (w * 0.5f)) * textureFactor + textureOffset;
2814+ const float midShadowT = (border + clampedShadow + (h * 0.5f)) * textureFactor + textureOffset;
2815+ const float clampedBorder = qMin(floorf(borderSize), maxSize);
2816+ const float clampedBorderRadius =
2817+ floorf(((maxSize - clampedBorder) / maxSize) * clampedRadius);
2818+ const float textureBorder = 1.0f;
2819+ const float borderTextureSize = (2.0f * textureBorder + clampedBorderRadius) * dpr;
2820+ const float borderTextureSizeRounded =
2821+ roundUp(static_cast<int>(borderTextureSize), textureRounding);
2822+ const float borderTextureOffset =
2823+ (borderTextureSizeRounded - borderTextureSize) / borderTextureSizeRounded;
2824+ const float borderTextureFactor = ((1.0f - borderTextureOffset) * dpr) / borderTextureSize;
2825+ const float borderOffset = -(clampedBorder - textureBorder);
2826+ const quint32 packedShadowColor = packColor(shadowColor);
2827+ const quint32 packedBorderColor = packColor(borderColor);
2828+ v[0].x = 0.0f;
2829+ v[0].y = 0.0f;
2830+ v[0].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2831+ v[0].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2832+ v[0].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2833+ v[0].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2834+ v[0].midShadowS = midShadowS;
2835+ v[0].midShadowT = midShadowT;
2836+ v[0].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2837+ v[0].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2838+ v[0].color = packedColor;
2839+ v[0].shadowColor = packedShadowColor;
2840+ v[0].borderColor = packedBorderColor;
2841+ v[1].x = clampedRadius;
2842+ v[1].y = 0.0f;
2843+ v[1].maskS = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2844+ v[1].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2845+ v[1].shadowS = (offsetX + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2846+ v[1].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2847+ v[1].midShadowS = midShadowS;
2848+ v[1].midShadowT = midShadowT;
2849+ v[1].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2850+ v[1].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2851+ v[1].color = packedColor;
2852+ v[1].shadowColor = packedShadowColor;
2853+ v[1].borderColor = packedBorderColor;
2854+ v[2].x = w - clampedRadius;
2855+ v[2].y = 0.0f;
2856+ v[2].maskS = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2857+ v[2].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2858+ v[2].shadowS =
2859+ (offsetX + border + clampedShadow + (w - clampedRadius)) * textureFactor + textureOffset;
2860+ v[2].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2861+ v[2].midShadowS = midShadowS;
2862+ v[2].midShadowT = midShadowT;
2863+ v[2].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2864+ v[2].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2865+ v[2].color = packedColor;
2866+ v[2].shadowColor = packedShadowColor;
2867+ v[2].borderColor = packedBorderColor;
2868+ v[3].x = w;
2869+ v[3].y = 0.0f;
2870+ v[3].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2871+ v[3].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2872+ v[3].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2873+ v[3].shadowT = (offsetY + border + clampedShadow) * textureFactor + textureOffset;
2874+ v[3].midShadowS = midShadowS;
2875+ v[3].midShadowT = midShadowT;
2876+ v[3].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2877+ v[3].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2878+ v[3].color = packedColor;
2879+ v[3].shadowColor = packedShadowColor;
2880+ v[3].borderColor = packedBorderColor;
2881+ v[4].x = 0.0f;
2882+ v[4].y = clampedRadius;
2883+ v[4].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2884+ v[4].maskT = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2885+ v[4].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2886+ v[4].shadowT = (offsetY + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2887+ v[4].midShadowS = midShadowS;
2888+ v[4].midShadowT = midShadowT;
2889+ v[4].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2890+ v[4].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2891+ v[4].color = packedColor;
2892+ v[4].shadowColor = packedShadowColor;
2893+ v[4].borderColor = packedBorderColor;
2894+ v[5].x = w;
2895+ v[5].y = clampedRadius;
2896+ v[5].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2897+ v[5].maskT = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2898+ v[5].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2899+ v[5].shadowT = (offsetY + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2900+ v[5].midShadowS = midShadowS;
2901+ v[5].midShadowT = midShadowT;
2902+ v[5].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2903+ v[5].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2904+ v[5].color = packedColor;
2905+ v[5].shadowColor = packedShadowColor;
2906+ v[5].borderColor = packedBorderColor;
2907+ v[6].x = 0.0f;
2908+ v[6].y = h - clampedRadius;
2909+ v[6].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2910+ v[6].maskT = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2911+ v[6].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2912+ v[6].shadowT =
2913+ (offsetY + border + clampedShadow + (h - clampedRadius)) * textureFactor + textureOffset;
2914+ v[6].midShadowS = midShadowS;
2915+ v[6].midShadowT = midShadowT;
2916+ v[6].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2917+ v[6].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2918+ v[6].color = packedColor;
2919+ v[6].shadowColor = packedShadowColor;
2920+ v[6].borderColor = packedBorderColor;
2921+ v[7].x = w;
2922+ v[7].y = h - clampedRadius;
2923+ v[7].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2924+ v[7].maskT = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2925+ v[7].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2926+ v[7].shadowT =
2927+ (offsetY + border + clampedShadow + (h - clampedRadius)) * textureFactor + textureOffset;
2928+ v[7].midShadowS = midShadowS;
2929+ v[7].midShadowT = midShadowT;
2930+ v[7].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2931+ v[7].borderT = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2932+ v[7].color = packedColor;
2933+ v[7].shadowColor = packedShadowColor;
2934+ v[7].borderColor = packedBorderColor;
2935+ v[8].x = 0.0f;
2936+ v[8].y = h;
2937+ v[8].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2938+ v[8].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2939+ v[8].shadowS = (offsetX + border + clampedShadow) * textureFactor + textureOffset;
2940+ v[8].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2941+ v[8].midShadowS = midShadowS;
2942+ v[8].midShadowT = midShadowT;
2943+ v[8].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2944+ v[8].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2945+ v[8].color = packedColor;
2946+ v[8].shadowColor = packedShadowColor;
2947+ v[8].borderColor = packedBorderColor;
2948+ v[9].x = clampedRadius;
2949+ v[9].y = h;
2950+ v[9].maskS = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2951+ v[9].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2952+ v[9].shadowS = (offsetX + border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2953+ v[9].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2954+ v[9].midShadowS = midShadowS;
2955+ v[9].midShadowT = midShadowT;
2956+ v[9].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2957+ v[9].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2958+ v[9].color = packedColor;
2959+ v[9].shadowColor = packedShadowColor;
2960+ v[9].borderColor = packedBorderColor;
2961+ v[10].x = w - clampedRadius;
2962+ v[10].y = h;
2963+ v[10].maskS = (border + clampedShadow + clampedRadius) * textureFactor + textureOffset;
2964+ v[10].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2965+ v[10].shadowS =
2966+ (offsetX + border + clampedShadow + (w - clampedRadius)) * textureFactor + textureOffset;
2967+ v[10].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2968+ v[10].midShadowS = midShadowS;
2969+ v[10].midShadowT = midShadowT;
2970+ v[10].borderS = (clampedRadius + borderOffset) * borderTextureFactor + borderTextureOffset;
2971+ v[10].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2972+ v[10].color = packedColor;
2973+ v[10].shadowColor = packedShadowColor;
2974+ v[10].borderColor = packedBorderColor;
2975+ v[11].x = w;
2976+ v[11].y = h;
2977+ v[11].maskS = (border + clampedShadow) * textureFactor + textureOffset;
2978+ v[11].maskT = (border + clampedShadow) * textureFactor + textureOffset;
2979+ v[11].shadowS = (offsetX + border + clampedShadow + w) * textureFactor + textureOffset;
2980+ v[11].shadowT = (offsetY + border + clampedShadow + h) * textureFactor + textureOffset;
2981+ v[11].midShadowS = midShadowS;
2982+ v[11].midShadowT = midShadowT;
2983+ v[11].borderS = borderOffset * borderTextureFactor + borderTextureOffset;
2984+ v[11].borderT = borderOffset * borderTextureFactor + borderTextureOffset;
2985+ v[11].color = packedColor;
2986+ v[11].shadowColor = packedShadowColor;
2987+ v[11].borderColor = packedBorderColor;
2988+ markDirty(QSGNode::DirtyGeometry);
2989+
2990+ // Update data for the preprocess() call.
2991+ const quint16 deviceRadius = static_cast<quint16>(clampedRadius * dpr);
2992+ if (m_radius != deviceRadius) {
2993+ m_radius = deviceRadius;
2994+ m_flags |= DirtyRadius;
2995+ }
2996+ const quint16 deviceShadow = static_cast<quint16>(clampedShadow * dpr);
2997+ if (m_shadow != deviceShadow) {
2998+ m_shadow = deviceShadow;
2999+ m_flags |= DirtyShadow;
3000+ }
3001+ const quint16 deviceBorderRadius = static_cast<quint16>(clampedBorderRadius * dpr);
3002+ if (m_borderRadius != deviceBorderRadius) {
3003+ m_borderRadius = deviceBorderRadius;
3004+ m_flags |= DirtyBorderRadius;
3005+ }
3006+ if (m_shape != static_cast<quint8>(type)) {
3007+ m_shape = static_cast<quint8>(type);
3008+ m_flags |= DirtyShape;
3009+ }
3010+ break;
3011+ }
3012+
3013+ default:
3014+ DNOT_REACHED();
3015+ }
3016+}
3017
3018=== added file 'src/UbuntuToolkit/privates/ucshapefillnodes_p.h'
3019--- src/UbuntuToolkit/privates/ucshapefillnodes_p.h 1970-01-01 00:00:00 +0000
3020+++ src/UbuntuToolkit/privates/ucshapefillnodes_p.h 2016-12-14 07:25:05 +0000
3021@@ -0,0 +1,999 @@
3022+/*
3023+ * Copyright 2016 Canonical Ltd.
3024+ *
3025+ * This program is free software; you can redistribute it and/or modify
3026+ * it under the terms of the GNU Lesser General Public License as published by
3027+ * the Free Software Foundation; version 3.
3028+ *
3029+ * This program is distributed in the hope that it will be useful,
3030+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3031+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3032+ * GNU Lesser General Public License for more details.
3033+ *
3034+ * You should have received a copy of the GNU Lesser General Public License
3035+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3036+ *
3037+ * Author: Loïc Molinari <loic.molinari@canonical.com>
3038+ */
3039+
3040+#ifndef UCSHAPEFILLNODES_P_H
3041+#define UCSHAPEFILLNODES_P_H
3042+
3043+#include <QtQuick/QSGNode>
3044+
3045+#include <UbuntuToolkit/private/ucshapetexturefactory_p.h>
3046+#include <UbuntuToolkit/private/ucshaperesources_p.h>
3047+
3048+// ################################
3049+// # Fill center shadow materials #
3050+// ################################
3051+
3052+class UCShapeFillCenterShadowOpaqueShader : public QSGMaterialShader
3053+{
3054+public:
3055+ UCShapeFillCenterShadowOpaqueShader() {
3056+ setShaderSourceFile(QOpenGLShader::Vertex,
3057+ QStringLiteral(":/uc/privates/shaders/fillcentershadow.vert"));
3058+ setShaderSourceFile(QOpenGLShader::Fragment,
3059+ QStringLiteral(":/uc/privates/shaders/fillcentershadow_opaque.frag"));
3060+ }
3061+ char const* const* attributeNames() const Q_DECL_OVERRIDE {
3062+ static char const* const attributes[] = {
3063+ "positionAttrib", "shadowCoordAttrib", "midShadowCoordAttrib", "colorAttrib",
3064+ "shadowColorAttrib", 0
3065+ };
3066+ return attributes;
3067+ }
3068+ void initialize() Q_DECL_OVERRIDE {
3069+ QSGMaterialShader::initialize();
3070+ program()->bind();
3071+ program()->setUniformValue("shadowTexture", 0);
3072+ m_matrixId = program()->uniformLocation("matrix");
3073+ }
3074+ void updateState(
3075+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial*) Q_DECL_OVERRIDE {
3076+ QOpenGLFunctions* funcs = QOpenGLContext::currentContext()->functions();
3077+ UCShapeTextureProvider* provider = dynamic_cast<UCShapeTextureProvider*>(newEffect);
3078+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId());
3079+ if (state.isMatrixDirty()) {
3080+ program()->setUniformValue(m_matrixId, state.combinedMatrix());
3081+ }
3082+ }
3083+
3084+private:
3085+ int m_matrixId;
3086+};
3087+
3088+class UCShapeFillCenterShadowShader : public UCShapeFillCenterShadowOpaqueShader
3089+{
3090+public:
3091+ UCShapeFillCenterShadowShader() : UCShapeFillCenterShadowOpaqueShader() {
3092+ setShaderSourceFile(QOpenGLShader::Fragment,
3093+ QStringLiteral(":/uc/privates/shaders/fillcentershadow.frag"));
3094+ }
3095+ void initialize() Q_DECL_OVERRIDE {
3096+ UCShapeFillCenterShadowOpaqueShader::initialize();
3097+ m_opacityId = program()->uniformLocation("opacity");
3098+ }
3099+ void updateState(
3100+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) Q_DECL_OVERRIDE {
3101+ UCShapeFillCenterShadowOpaqueShader::updateState(state, newEffect, oldEffect);
3102+ if (state.isOpacityDirty()) {
3103+ program()->setUniformValue(m_opacityId, state.opacity());
3104+ }
3105+ }
3106+
3107+private:
3108+ int m_opacityId;
3109+};
3110+
3111+template <bool opaque>
3112+class UCShapeFillCenterShadowMaterial : public QSGMaterial, public UCShapeTextureProvider
3113+{
3114+public:
3115+ UCShapeFillCenterShadowMaterial() : m_textureId(0) {
3116+ setFlag(Blending, !opaque);
3117+ }
3118+
3119+ QSGMaterialType* type() const Q_DECL_OVERRIDE {
3120+ static QSGMaterialType type[2];
3121+ return opaque ? &type[0] : &type[1];
3122+ }
3123+ QSGMaterialShader* createShader() const Q_DECL_OVERRIDE {
3124+ return opaque ? new UCShapeFillCenterShadowOpaqueShader : new UCShapeFillCenterShadowShader;
3125+ }
3126+ int compare(const QSGMaterial* other) const Q_DECL_OVERRIDE {
3127+ return reinterpret_cast<const UCShapeTextureProvider*>(other)->textureId() - m_textureId;
3128+ }
3129+
3130+ quint32 textureId(int) const Q_DECL_OVERRIDE {
3131+ return m_textureId;
3132+ }
3133+ void updateShadowTexture(UCShapeType type, quint16 radius, quint16 shadow) {
3134+ m_textureId = m_textureFactory.shadowTexture(0, type, radius, shadow);
3135+ }
3136+
3137+private:
3138+ UCShapeTextureFactory<1> m_textureFactory;
3139+ quint32 m_textureId;
3140+};
3141+
3142+class UCShapeFillCenterShadowResources : public UCShapeResources
3143+{
3144+public:
3145+ UCShapeFillCenterShadowResources(
3146+ int vertexCount, int indexCount, int indexType = GL_UNSIGNED_SHORT)
3147+ : m_geometry(attributeSet(), vertexCount, indexCount, indexType) {
3148+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
3149+ m_geometry.setIndexDataPattern(QSGGeometry::StaticPattern);
3150+ m_geometry.setVertexDataPattern(QSGGeometry::AlwaysUploadPattern);
3151+ }
3152+
3153+ QSGMaterial* material() Q_DECL_OVERRIDE { return &m_material; }
3154+ QSGMaterial* opaqueMaterial() Q_DECL_OVERRIDE { return &m_opaqueMaterial; }
3155+ QSGGeometry* geometry() Q_DECL_OVERRIDE { return &m_geometry; }
3156+
3157+ struct Vertex {
3158+ float x, y;
3159+ float shadowS, shadowT;
3160+ float midShadowS, midShadowT;
3161+ quint32 color;
3162+ quint32 shadowColor;
3163+ };
3164+
3165+private:
3166+ static const QSGGeometry::AttributeSet& attributeSet() {
3167+ static const QSGGeometry::Attribute attributes[] = {
3168+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // x, y
3169+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // shadowS, shadowT
3170+ QSGGeometry::Attribute::create(2, 2, GL_FLOAT), // midShadowS, midShadowT
3171+ QSGGeometry::Attribute::create(3, 4, GL_UNSIGNED_BYTE), // color
3172+ QSGGeometry::Attribute::create(4, 4, GL_UNSIGNED_BYTE) // shadowColor
3173+ };
3174+ static const QSGGeometry::AttributeSet attributeSet = {
3175+ 5, sizeof(Vertex), attributes
3176+ };
3177+ return attributeSet;
3178+ }
3179+
3180+ UCShapeFillCenterShadowMaterial<false> m_material;
3181+ UCShapeFillCenterShadowMaterial<true> m_opaqueMaterial;
3182+ QSGGeometry m_geometry;
3183+};
3184+
3185+// ################################
3186+// # Fill center border materials #
3187+// ################################
3188+
3189+class UCShapeFillCenterBorderOpaqueShader : public QSGMaterialShader
3190+{
3191+public:
3192+ UCShapeFillCenterBorderOpaqueShader() {
3193+ setShaderSourceFile(
3194+ QOpenGLShader::Vertex, QStringLiteral(":/uc/privates/shaders/fillcenterborder.vert"));
3195+ setShaderSourceFile(
3196+ QOpenGLShader::Fragment, QStringLiteral(
3197+ ":/uc/privates/shaders/fillcenterborder_opaque.frag"));
3198+ }
3199+ char const* const* attributeNames() const Q_DECL_OVERRIDE {
3200+ static char const* const attributes[] = {
3201+ "positionAttrib", "borderCoordAttrib", "colorAttrib", "borderColorAttrib", 0
3202+ };
3203+ return attributes;
3204+ }
3205+ void initialize() Q_DECL_OVERRIDE {
3206+ QSGMaterialShader::initialize();
3207+ program()->bind();
3208+ program()->setUniformValue("borderTexture", 0);
3209+ m_matrixId = program()->uniformLocation("matrix");
3210+ }
3211+ void updateState(
3212+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial*) Q_DECL_OVERRIDE {
3213+ QOpenGLFunctions* funcs = QOpenGLContext::currentContext()->functions();
3214+ UCShapeTextureProvider* provider = dynamic_cast<UCShapeTextureProvider*>(newEffect);
3215+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId());
3216+ if (state.isMatrixDirty()) {
3217+ program()->setUniformValue(m_matrixId, state.combinedMatrix());
3218+ }
3219+ }
3220+
3221+private:
3222+ int m_matrixId;
3223+};
3224+
3225+class UCShapeFillCenterBorderShader : public UCShapeFillCenterBorderOpaqueShader
3226+{
3227+public:
3228+ UCShapeFillCenterBorderShader() : UCShapeFillCenterBorderOpaqueShader() {
3229+ setShaderSourceFile(
3230+ QOpenGLShader::Fragment, QStringLiteral(":/uc/privates/shaders/fillcenterborder.frag"));
3231+ }
3232+ void initialize() Q_DECL_OVERRIDE {
3233+ UCShapeFillCenterBorderOpaqueShader::initialize();
3234+ m_opacityId = program()->uniformLocation("opacity");
3235+ }
3236+ void updateState(
3237+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) Q_DECL_OVERRIDE {
3238+ UCShapeFillCenterBorderOpaqueShader::updateState(state, newEffect, oldEffect);
3239+ if (state.isOpacityDirty()) {
3240+ program()->setUniformValue(m_opacityId, state.opacity());
3241+ }
3242+ }
3243+
3244+private:
3245+ int m_opacityId;
3246+};
3247+
3248+template <bool opaque>
3249+class UCShapeFillCenterBorderMaterial : public QSGMaterial, public UCShapeTextureProvider
3250+{
3251+public:
3252+ UCShapeFillCenterBorderMaterial() : m_textureId(0) {
3253+ setFlag(Blending, !opaque);
3254+ }
3255+
3256+ QSGMaterialType* type() const Q_DECL_OVERRIDE {
3257+ static QSGMaterialType type[2];
3258+ return opaque ? &type[0] : &type[1];
3259+ }
3260+ QSGMaterialShader* createShader() const Q_DECL_OVERRIDE {
3261+ return opaque ?
3262+ new UCShapeFillCenterBorderOpaqueShader : new UCShapeFillCenterBorderShader;
3263+ }
3264+ int compare(const QSGMaterial* other) const Q_DECL_OVERRIDE {
3265+ return reinterpret_cast<const UCShapeTextureProvider*>(other)->textureId() - m_textureId;
3266+ }
3267+
3268+ quint32 textureId(int) const Q_DECL_OVERRIDE {
3269+ return m_textureId;
3270+ }
3271+ void updateBorderTexture(UCShapeType type, quint16 radius) {
3272+ m_textureId = m_textureFactory.maskTexture(0, type, radius);
3273+ }
3274+
3275+private:
3276+ UCShapeTextureFactory<1> m_textureFactory;
3277+ quint32 m_textureId;
3278+};
3279+
3280+class UCShapeFillCenterBorderResources : public UCShapeResources
3281+{
3282+public:
3283+ UCShapeFillCenterBorderResources(
3284+ int vertexCount, int indexCount, int indexType = GL_UNSIGNED_SHORT)
3285+ : m_geometry(attributeSet(), vertexCount, indexCount, indexType) {
3286+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
3287+ m_geometry.setIndexDataPattern(QSGGeometry::StaticPattern);
3288+ m_geometry.setVertexDataPattern(QSGGeometry::AlwaysUploadPattern);
3289+ }
3290+
3291+ QSGMaterial* material() Q_DECL_OVERRIDE { return &m_material; }
3292+ QSGMaterial* opaqueMaterial() Q_DECL_OVERRIDE { return &m_opaqueMaterial; }
3293+ QSGGeometry* geometry() Q_DECL_OVERRIDE { return &m_geometry; }
3294+
3295+ struct Vertex {
3296+ float x, y;
3297+ float borderS, borderT;
3298+ quint32 color;
3299+ quint32 borderColor;
3300+ };
3301+
3302+private:
3303+ static const QSGGeometry::AttributeSet& attributeSet() {
3304+ static const QSGGeometry::Attribute attributes[] = {
3305+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // x, y
3306+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // borderS, borderT
3307+ QSGGeometry::Attribute::create(2, 4, GL_UNSIGNED_BYTE), // color
3308+ QSGGeometry::Attribute::create(3, 4, GL_UNSIGNED_BYTE) // borderColor
3309+ };
3310+ static const QSGGeometry::AttributeSet attributeSet = {
3311+ 4, sizeof(Vertex), attributes
3312+ };
3313+ return attributeSet;
3314+ }
3315+
3316+ UCShapeFillCenterBorderMaterial<false> m_material;
3317+ UCShapeFillCenterBorderMaterial<true> m_opaqueMaterial;
3318+ QSGGeometry m_geometry;
3319+};
3320+
3321+// #######################################
3322+// # Fill center shadow border materials #
3323+// #######################################
3324+
3325+class UCShapeFillCenterShadowBorderOpaqueShader : public QSGMaterialShader
3326+{
3327+public:
3328+ UCShapeFillCenterShadowBorderOpaqueShader() {
3329+ setShaderSourceFile(
3330+ QOpenGLShader::Vertex, QStringLiteral(
3331+ ":/uc/privates/shaders/fillcentershadowborder.vert"));
3332+ setShaderSourceFile(
3333+ QOpenGLShader::Fragment, QStringLiteral(
3334+ ":/uc/privates/shaders/fillcentershadowborder_opaque.frag"));
3335+ }
3336+ char const* const* attributeNames() const Q_DECL_OVERRIDE {
3337+ static char const* const attributes[] = {
3338+ "positionAttrib", "shadowCoordAttrib", "midShadowCoordAttrib", "borderCoordAttrib",
3339+ "colorAttrib", "shadowColorAttrib", "borderColorAttrib", 0
3340+ };
3341+ return attributes;
3342+ }
3343+ void initialize() Q_DECL_OVERRIDE {
3344+ QSGMaterialShader::initialize();
3345+ program()->bind();
3346+ program()->setUniformValue("shadowTexture", 0);
3347+ program()->setUniformValue("borderTexture", 1);
3348+ m_matrixId = program()->uniformLocation("matrix");
3349+ }
3350+ void updateState(
3351+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial*) Q_DECL_OVERRIDE {
3352+ QOpenGLFunctions* funcs = QOpenGLContext::currentContext()->functions();
3353+ UCShapeTextureProvider* provider = dynamic_cast<UCShapeTextureProvider*>(newEffect);
3354+ funcs->glActiveTexture(GL_TEXTURE1);
3355+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId(1));
3356+ funcs->glActiveTexture(GL_TEXTURE0);
3357+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId(0));
3358+ if (state.isMatrixDirty()) {
3359+ program()->setUniformValue(m_matrixId, state.combinedMatrix());
3360+ }
3361+ }
3362+
3363+private:
3364+ int m_matrixId;
3365+};
3366+
3367+class UCShapeFillCenterShadowBorderShader : public UCShapeFillCenterShadowBorderOpaqueShader
3368+{
3369+public:
3370+ UCShapeFillCenterShadowBorderShader() : UCShapeFillCenterShadowBorderOpaqueShader() {
3371+ setShaderSourceFile(
3372+ QOpenGLShader::Fragment, QStringLiteral(
3373+ ":/uc/privates/shaders/fillcentershadowborder.frag"));
3374+ }
3375+ void initialize() Q_DECL_OVERRIDE {
3376+ UCShapeFillCenterShadowBorderOpaqueShader::initialize();
3377+ m_opacityId = program()->uniformLocation("opacity");
3378+ }
3379+ void updateState(
3380+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) Q_DECL_OVERRIDE {
3381+ UCShapeFillCenterShadowBorderOpaqueShader::updateState(state, newEffect, oldEffect);
3382+ if (state.isOpacityDirty()) {
3383+ program()->setUniformValue(m_opacityId, state.opacity());
3384+ }
3385+ }
3386+
3387+private:
3388+ int m_opacityId;
3389+};
3390+
3391+template <bool opaque>
3392+class UCShapeFillCenterShadowBorderMaterial : public QSGMaterial, public UCShapeTextureProvider
3393+{
3394+public:
3395+ UCShapeFillCenterShadowBorderMaterial() : m_textureId{0, 0} {
3396+ setFlag(Blending, !opaque);
3397+ }
3398+
3399+ QSGMaterialType* type() const Q_DECL_OVERRIDE {
3400+ static QSGMaterialType type[2];
3401+ return opaque ? &type[0] : &type[1];
3402+ }
3403+ QSGMaterialShader* createShader() const Q_DECL_OVERRIDE {
3404+ return opaque ?
3405+ new UCShapeFillCenterShadowBorderOpaqueShader : new UCShapeFillCenterShadowBorderShader;
3406+ }
3407+ int compare(const QSGMaterial* other) const Q_DECL_OVERRIDE {
3408+ const UCShapeTextureProvider* provider =
3409+ reinterpret_cast<const UCShapeTextureProvider*>(other);
3410+ if (provider->textureId(0) == m_textureId[0]) {
3411+ return provider->textureId(1) - m_textureId[1];
3412+ } else {
3413+ return -1;
3414+ }
3415+ }
3416+
3417+ quint32 textureId(int index) const Q_DECL_OVERRIDE {
3418+ DASSERT(index <= 1);
3419+ return m_textureId[index];
3420+ }
3421+ void updateShadowTexture(UCShapeType type, quint16 radius, quint16 shadow) {
3422+ m_textureId[0] = m_textureFactory.shadowTexture(0, type, radius, shadow);
3423+ }
3424+ void updateBorderTexture(UCShapeType type, quint16 radius) {
3425+ m_textureId[1] = m_textureFactory.maskTexture(1, type, radius);
3426+ }
3427+
3428+private:
3429+ UCShapeTextureFactory<2> m_textureFactory;
3430+ quint32 m_textureId[2];
3431+};
3432+
3433+class UCShapeFillCenterShadowBorderResources : public UCShapeResources
3434+{
3435+public:
3436+ UCShapeFillCenterShadowBorderResources(
3437+ int vertexCount, int indexCount, int indexType = GL_UNSIGNED_SHORT)
3438+ : m_geometry(attributeSet(), vertexCount, indexCount, indexType) {
3439+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
3440+ m_geometry.setIndexDataPattern(QSGGeometry::StaticPattern);
3441+ m_geometry.setVertexDataPattern(QSGGeometry::AlwaysUploadPattern);
3442+ }
3443+
3444+ QSGMaterial* material() Q_DECL_OVERRIDE { return &m_material; }
3445+ QSGMaterial* opaqueMaterial() Q_DECL_OVERRIDE { return &m_opaqueMaterial; }
3446+ QSGGeometry* geometry() Q_DECL_OVERRIDE { return &m_geometry; }
3447+
3448+ struct Vertex {
3449+ float x, y;
3450+ float shadowS, shadowT;
3451+ float midShadowS, midShadowT;
3452+ float borderS, borderT;
3453+ quint32 color;
3454+ quint32 shadowColor;
3455+ quint32 borderColor;
3456+ };
3457+
3458+private:
3459+ static const QSGGeometry::AttributeSet& attributeSet() {
3460+ static const QSGGeometry::Attribute attributes[] = {
3461+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // x, y
3462+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // shadowS, shadowT
3463+ QSGGeometry::Attribute::create(2, 2, GL_FLOAT), // midShadowS, midShadowT
3464+ QSGGeometry::Attribute::create(3, 2, GL_FLOAT), // borderS, borderT
3465+ QSGGeometry::Attribute::create(4, 4, GL_UNSIGNED_BYTE), // color
3466+ QSGGeometry::Attribute::create(5, 4, GL_UNSIGNED_BYTE), // shadowColor
3467+ QSGGeometry::Attribute::create(6, 4, GL_UNSIGNED_BYTE) // borderColor
3468+ };
3469+ static const QSGGeometry::AttributeSet attributeSet = {
3470+ 7, sizeof(Vertex), attributes
3471+ };
3472+ return attributeSet;
3473+ }
3474+
3475+ UCShapeFillCenterShadowBorderMaterial<false> m_material;
3476+ UCShapeFillCenterShadowBorderMaterial<true> m_opaqueMaterial;
3477+ QSGGeometry m_geometry;
3478+};
3479+
3480+// ####################
3481+// # Fill center node #
3482+// ####################
3483+
3484+class UCShapeFillCenterNode : public QSGGeometryNode
3485+{
3486+public:
3487+ UCShapeFillCenterNode();
3488+ ~UCShapeFillCenterNode();
3489+
3490+ void preprocess() Q_DECL_OVERRIDE;
3491+ bool isSubtreeBlocked() const Q_DECL_OVERRIDE { return !(m_flags & Visible); }
3492+
3493+ void setVisible(bool visible);
3494+ void update(
3495+ const QSizeF& itemSize, UCShapeType type, float radius, QRgb color, float shadowSize,
3496+ float shadowAngle, float shadowDistance, QRgb shadowColor, float borderSize,
3497+ QRgb borderColor);
3498+
3499+private:
3500+ enum {
3501+ HasColor = (1 << 0),
3502+ HasShadow = (1 << 1),
3503+ HasBorder = (1 << 2),
3504+ StyleMask = (HasColor | HasShadow | HasBorder),
3505+ Textured = (HasShadow | HasBorder),
3506+ DirtyRadius = (1 << 3),
3507+ DirtyShadow = (1 << 4),
3508+ DirtyShape = (1 << 5),
3509+ DirtyBorderRadius = (1 << 6),
3510+ DirtyMask = (DirtyRadius | DirtyShadow | DirtyShape | DirtyBorderRadius),
3511+ Visible = (1 << 7),
3512+ Blending = (1 << 8)
3513+ };
3514+
3515+ UCShapeResources* m_resources;
3516+ quint16 m_radius;
3517+ quint16 m_shadow;
3518+ quint16 m_borderRadius;
3519+ quint16 m_flags;
3520+ quint8 m_shape;
3521+};
3522+
3523+// #################################
3524+// # Fill corners shadow materials #
3525+// #################################
3526+
3527+class UCShapeFillCornersShadowOpaqueShader : public QSGMaterialShader
3528+{
3529+public:
3530+ UCShapeFillCornersShadowOpaqueShader() {
3531+ setShaderSourceFile(QOpenGLShader::Vertex,
3532+ QStringLiteral(":/uc/privates/shaders/fillcornersshadow.vert"));
3533+ setShaderSourceFile(QOpenGLShader::Fragment,
3534+ QStringLiteral(":/uc/privates/shaders/fillcornersshadow_opaque.frag"));
3535+ }
3536+ char const* const* attributeNames() const Q_DECL_OVERRIDE {
3537+ static char const* const attributes[] = {
3538+ "positionAttrib", "maskCoordAttrib", "shadowCoordAttrib", "midShadowCoordAttrib",
3539+ "colorAttrib", "shadowColorAttrib", 0
3540+ };
3541+ return attributes;
3542+ }
3543+ void initialize() Q_DECL_OVERRIDE {
3544+ QSGMaterialShader::initialize();
3545+ program()->bind();
3546+ program()->setUniformValue("shadowTexture", 0);
3547+ m_matrixId = program()->uniformLocation("matrix");
3548+ }
3549+ void updateState(
3550+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial*) Q_DECL_OVERRIDE {
3551+ QOpenGLFunctions* funcs = QOpenGLContext::currentContext()->functions();
3552+ UCShapeTextureProvider* provider = dynamic_cast<UCShapeTextureProvider*>(newEffect);
3553+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId());
3554+ if (state.isMatrixDirty()) {
3555+ program()->setUniformValue(m_matrixId, state.combinedMatrix());
3556+ }
3557+ }
3558+
3559+private:
3560+ int m_matrixId;
3561+};
3562+
3563+class UCShapeFillCornersShadowShader : public UCShapeFillCornersShadowOpaqueShader
3564+{
3565+public:
3566+ UCShapeFillCornersShadowShader() : UCShapeFillCornersShadowOpaqueShader() {
3567+ setShaderSourceFile(QOpenGLShader::Fragment,
3568+ QStringLiteral(":/uc/privates/shaders/fillcornersshadow.frag"));
3569+ }
3570+ void initialize() Q_DECL_OVERRIDE {
3571+ UCShapeFillCornersShadowOpaqueShader::initialize();
3572+ m_opacityId = program()->uniformLocation("opacity");
3573+ }
3574+ void updateState(
3575+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) Q_DECL_OVERRIDE {
3576+ UCShapeFillCornersShadowOpaqueShader::updateState(state, newEffect, oldEffect);
3577+ if (state.isOpacityDirty()) {
3578+ program()->setUniformValue(m_opacityId, state.opacity());
3579+ }
3580+ }
3581+
3582+private:
3583+ int m_opacityId;
3584+};
3585+
3586+template <bool opaque>
3587+class UCShapeFillCornersShadowMaterial : public QSGMaterial, public UCShapeTextureProvider
3588+{
3589+public:
3590+ UCShapeFillCornersShadowMaterial() : m_textureId(0) {
3591+ setFlag(Blending, !opaque);
3592+ }
3593+
3594+ QSGMaterialType* type() const Q_DECL_OVERRIDE {
3595+ static QSGMaterialType type[2];
3596+ return opaque ? &type[0] : &type[1];
3597+ }
3598+ QSGMaterialShader* createShader() const Q_DECL_OVERRIDE {
3599+ return opaque ?
3600+ new UCShapeFillCornersShadowOpaqueShader : new UCShapeFillCornersShadowShader;
3601+ }
3602+ int compare(const QSGMaterial* other) const Q_DECL_OVERRIDE {
3603+ return reinterpret_cast<const UCShapeTextureProvider*>(other)->textureId() - m_textureId;
3604+ }
3605+
3606+ quint32 textureId(int) const Q_DECL_OVERRIDE {
3607+ return m_textureId;
3608+ }
3609+ void updateShadowTexture(UCShapeType type, quint16 radius, quint16 shadow) {
3610+ m_textureId = m_textureFactory.shadowTexture(0, type, radius, shadow);
3611+ }
3612+
3613+private:
3614+ UCShapeTextureFactory<1> m_textureFactory;
3615+ quint32 m_textureId;
3616+};
3617+
3618+class UCShapeFillCornersShadowResources : public UCShapeResources
3619+{
3620+public:
3621+ UCShapeFillCornersShadowResources(
3622+ int vertexCount, int indexCount, int indexType = GL_UNSIGNED_SHORT)
3623+ : m_geometry(attributeSet(), vertexCount, indexCount, indexType) {
3624+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
3625+ m_geometry.setIndexDataPattern(QSGGeometry::StaticPattern);
3626+ m_geometry.setVertexDataPattern(QSGGeometry::AlwaysUploadPattern);
3627+ }
3628+
3629+ QSGMaterial* material() Q_DECL_OVERRIDE { return &m_material; }
3630+ QSGMaterial* opaqueMaterial() Q_DECL_OVERRIDE { return &m_opaqueMaterial; }
3631+ QSGGeometry* geometry() Q_DECL_OVERRIDE { return &m_geometry; }
3632+
3633+ struct Vertex {
3634+ float x, y;
3635+ float maskS, maskT;
3636+ float shadowS, shadowT;
3637+ float midShadowS, midShadowT;
3638+ quint32 color;
3639+ quint32 shadowColor;
3640+ };
3641+
3642+private:
3643+ static const QSGGeometry::AttributeSet& attributeSet() {
3644+ static const QSGGeometry::Attribute attributes[] = {
3645+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // x, y
3646+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // maskS, maskT
3647+ QSGGeometry::Attribute::create(2, 2, GL_FLOAT), // shadowS, shadowT
3648+ QSGGeometry::Attribute::create(3, 2, GL_FLOAT), // midShadowS, midShadowT
3649+ QSGGeometry::Attribute::create(4, 4, GL_UNSIGNED_BYTE), // color
3650+ QSGGeometry::Attribute::create(5, 4, GL_UNSIGNED_BYTE) // shadowColor
3651+ };
3652+ static const QSGGeometry::AttributeSet attributeSet = {
3653+ 6, sizeof(Vertex), attributes
3654+ };
3655+ return attributeSet;
3656+ }
3657+
3658+ UCShapeFillCornersShadowMaterial<false> m_material;
3659+ UCShapeFillCornersShadowMaterial<true> m_opaqueMaterial;
3660+ QSGGeometry m_geometry;
3661+};
3662+
3663+// #################################
3664+// # Fill corners border materials #
3665+// #################################
3666+
3667+class UCShapeFillCornersBorderOpaqueShader : public QSGMaterialShader
3668+{
3669+public:
3670+ UCShapeFillCornersBorderOpaqueShader() {
3671+ setShaderSourceFile(
3672+ QOpenGLShader::Vertex, QStringLiteral(":/uc/privates/shaders/fillcornersborder.vert"));
3673+ setShaderSourceFile(
3674+ QOpenGLShader::Fragment, QStringLiteral(
3675+ ":/uc/privates/shaders/fillcornersborder_opaque.frag"));
3676+ }
3677+ char const* const* attributeNames() const Q_DECL_OVERRIDE {
3678+ static char const* const attributes[] = {
3679+ "positionAttrib", "maskCoordAttrib", "borderCoordAttrib", "colorAttrib",
3680+ "borderColorAttrib", 0
3681+ };
3682+ return attributes;
3683+ }
3684+ void initialize() Q_DECL_OVERRIDE {
3685+ QSGMaterialShader::initialize();
3686+ program()->bind();
3687+ program()->setUniformValue("maskTexture", 0);
3688+ program()->setUniformValue("borderTexture", 1);
3689+ m_matrixId = program()->uniformLocation("matrix");
3690+ }
3691+ void updateState(
3692+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial*) Q_DECL_OVERRIDE {
3693+ QOpenGLFunctions* funcs = QOpenGLContext::currentContext()->functions();
3694+ UCShapeTextureProvider* provider = dynamic_cast<UCShapeTextureProvider*>(newEffect);
3695+ funcs->glActiveTexture(GL_TEXTURE1);
3696+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId(1));
3697+ funcs->glActiveTexture(GL_TEXTURE0);
3698+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId(0));
3699+ if (state.isMatrixDirty()) {
3700+ program()->setUniformValue(m_matrixId, state.combinedMatrix());
3701+ }
3702+ }
3703+
3704+private:
3705+ int m_matrixId;
3706+};
3707+
3708+class UCShapeFillCornersBorderShader : public UCShapeFillCornersBorderOpaqueShader
3709+{
3710+public:
3711+ UCShapeFillCornersBorderShader() : UCShapeFillCornersBorderOpaqueShader() {
3712+ setShaderSourceFile(
3713+ QOpenGLShader::Fragment, QStringLiteral(
3714+ ":/uc/privates/shaders/fillcornersborder.frag"));
3715+ }
3716+ void initialize() Q_DECL_OVERRIDE {
3717+ UCShapeFillCornersBorderOpaqueShader::initialize();
3718+ m_opacityId = program()->uniformLocation("opacity");
3719+ }
3720+ void updateState(
3721+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) Q_DECL_OVERRIDE {
3722+ UCShapeFillCornersBorderOpaqueShader::updateState(state, newEffect, oldEffect);
3723+ if (state.isOpacityDirty()) {
3724+ program()->setUniformValue(m_opacityId, state.opacity());
3725+ }
3726+ }
3727+
3728+private:
3729+ int m_opacityId;
3730+};
3731+
3732+template <bool opaque>
3733+class UCShapeFillCornersBorderMaterial : public QSGMaterial, public UCShapeTextureProvider
3734+{
3735+public:
3736+ UCShapeFillCornersBorderMaterial() : m_textureId{0, 0} {
3737+ setFlag(Blending, !opaque);
3738+ }
3739+
3740+ QSGMaterialType* type() const Q_DECL_OVERRIDE {
3741+ static QSGMaterialType type[2];
3742+ return opaque ? &type[0] : &type[1];
3743+ }
3744+ QSGMaterialShader* createShader() const Q_DECL_OVERRIDE {
3745+ return opaque ?
3746+ new UCShapeFillCornersBorderOpaqueShader : new UCShapeFillCornersBorderShader;
3747+ }
3748+ int compare(const QSGMaterial* other) const Q_DECL_OVERRIDE {
3749+ const UCShapeTextureProvider* provider =
3750+ reinterpret_cast<const UCShapeTextureProvider*>(other);
3751+ if (provider->textureId(0) == m_textureId[0]) {
3752+ return provider->textureId(1) - m_textureId[1];
3753+ } else {
3754+ return -1;
3755+ }
3756+ }
3757+
3758+ quint32 textureId(int index) const Q_DECL_OVERRIDE {
3759+ DASSERT(index <= 1);
3760+ return m_textureId[index];
3761+ }
3762+ void updateMaskTexture(UCShapeType type, quint16 radius) {
3763+ m_textureId[0] = m_textureFactory.maskTexture(0, type, radius);
3764+ }
3765+ void updateBorderTexture(UCShapeType type, quint16 radius) {
3766+ m_textureId[1] = m_textureFactory.maskTexture(1, type, radius);
3767+ }
3768+
3769+private:
3770+ UCShapeTextureFactory<2> m_textureFactory;
3771+ quint32 m_textureId[2];
3772+};
3773+
3774+class UCShapeFillCornersBorderResources : public UCShapeResources
3775+{
3776+public:
3777+ UCShapeFillCornersBorderResources(
3778+ int vertexCount, int indexCount, int indexType = GL_UNSIGNED_SHORT)
3779+ : m_geometry(attributeSet(), vertexCount, indexCount, indexType) {
3780+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
3781+ m_geometry.setIndexDataPattern(QSGGeometry::StaticPattern);
3782+ m_geometry.setVertexDataPattern(QSGGeometry::AlwaysUploadPattern);
3783+ }
3784+
3785+ QSGMaterial* material() Q_DECL_OVERRIDE { return &m_material; }
3786+ QSGMaterial* opaqueMaterial() Q_DECL_OVERRIDE { return &m_opaqueMaterial; }
3787+ QSGGeometry* geometry() Q_DECL_OVERRIDE { return &m_geometry; }
3788+
3789+ struct Vertex {
3790+ float x, y;
3791+ float maskS, maskT;
3792+ float borderS, borderT;
3793+ quint32 color;
3794+ quint32 borderColor;
3795+ };
3796+
3797+private:
3798+ static const QSGGeometry::AttributeSet& attributeSet() {
3799+ static const QSGGeometry::Attribute attributes[] = {
3800+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // x, y
3801+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // maskS, maskT
3802+ QSGGeometry::Attribute::create(2, 2, GL_FLOAT), // borderS, borderT
3803+ QSGGeometry::Attribute::create(3, 4, GL_UNSIGNED_BYTE), // color
3804+ QSGGeometry::Attribute::create(4, 4, GL_UNSIGNED_BYTE) // borderColor
3805+ };
3806+ static const QSGGeometry::AttributeSet attributeSet = {
3807+ 5, sizeof(Vertex), attributes
3808+ };
3809+ return attributeSet;
3810+ }
3811+
3812+ UCShapeFillCornersBorderMaterial<false> m_material;
3813+ UCShapeFillCornersBorderMaterial<true> m_opaqueMaterial;
3814+ QSGGeometry m_geometry;
3815+};
3816+
3817+// ########################################
3818+// # Fill corners shadow border materials #
3819+// ########################################
3820+
3821+class UCShapeFillCornersShadowBorderOpaqueShader : public QSGMaterialShader
3822+{
3823+public:
3824+ UCShapeFillCornersShadowBorderOpaqueShader() {
3825+ setShaderSourceFile(
3826+ QOpenGLShader::Vertex, QStringLiteral(
3827+ ":/uc/privates/shaders/fillcornersshadowborder.vert"));
3828+ setShaderSourceFile(
3829+ QOpenGLShader::Fragment, QStringLiteral(
3830+ ":/uc/privates/shaders/fillcornersshadowborder_opaque.frag"));
3831+ }
3832+ char const* const* attributeNames() const Q_DECL_OVERRIDE {
3833+ static char const* const attributes[] = {
3834+ "positionAttrib", "maskCoordAttrib", "shadowCoordAttrib", "midShadowCoordAttrib",
3835+ "borderCoordAttrib", "colorAttrib", "shadowColorAttrib", "borderColorAttrib", 0
3836+ };
3837+ return attributes;
3838+ }
3839+ void initialize() Q_DECL_OVERRIDE {
3840+ QSGMaterialShader::initialize();
3841+ program()->bind();
3842+ program()->setUniformValue("shadowtexture", 0);
3843+ program()->setUniformValue("borderTexture", 1);
3844+ m_matrixId = program()->uniformLocation("matrix");
3845+ }
3846+ void updateState(
3847+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial*) Q_DECL_OVERRIDE {
3848+ QOpenGLFunctions* funcs = QOpenGLContext::currentContext()->functions();
3849+ UCShapeTextureProvider* provider = dynamic_cast<UCShapeTextureProvider*>(newEffect);
3850+ funcs->glActiveTexture(GL_TEXTURE1);
3851+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId(1));
3852+ funcs->glActiveTexture(GL_TEXTURE0);
3853+ funcs->glBindTexture(GL_TEXTURE_2D, provider->textureId(0));
3854+ if (state.isMatrixDirty()) {
3855+ program()->setUniformValue(m_matrixId, state.combinedMatrix());
3856+ }
3857+ }
3858+
3859+private:
3860+ int m_matrixId;
3861+};
3862+
3863+class UCShapeFillCornersShadowBorderShader : public UCShapeFillCornersShadowBorderOpaqueShader
3864+{
3865+public:
3866+ UCShapeFillCornersShadowBorderShader() : UCShapeFillCornersShadowBorderOpaqueShader() {
3867+ setShaderSourceFile(QOpenGLShader::Fragment,
3868+ QStringLiteral(":/uc/privates/shaders/fillcornersshadowborder.frag"));
3869+ }
3870+ void initialize() Q_DECL_OVERRIDE {
3871+ UCShapeFillCornersShadowBorderOpaqueShader::initialize();
3872+ m_opacityId = program()->uniformLocation("opacity");
3873+ }
3874+ void updateState(
3875+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) Q_DECL_OVERRIDE {
3876+ UCShapeFillCornersShadowBorderOpaqueShader::updateState(state, newEffect, oldEffect);
3877+ if (state.isOpacityDirty()) {
3878+ program()->setUniformValue(m_opacityId, state.opacity());
3879+ }
3880+ }
3881+
3882+private:
3883+ int m_opacityId;
3884+};
3885+
3886+template <bool opaque>
3887+class UCShapeFillCornersShadowBorderMaterial : public QSGMaterial, public UCShapeTextureProvider
3888+{
3889+public:
3890+ UCShapeFillCornersShadowBorderMaterial() : m_textureId{0, 0} {
3891+ setFlag(Blending, !opaque);
3892+ }
3893+
3894+ QSGMaterialType* type() const Q_DECL_OVERRIDE {
3895+ static QSGMaterialType type[2];
3896+ return opaque ? &type[0] : &type[1];
3897+ }
3898+ QSGMaterialShader* createShader() const Q_DECL_OVERRIDE {
3899+ return opaque ?
3900+ new UCShapeFillCornersShadowBorderOpaqueShader :
3901+ new UCShapeFillCornersShadowBorderShader;
3902+ }
3903+ int compare(const QSGMaterial* other) const Q_DECL_OVERRIDE {
3904+ const UCShapeTextureProvider* provider =
3905+ reinterpret_cast<const UCShapeTextureProvider*>(other);
3906+ if (provider->textureId(0) == m_textureId[0]) {
3907+ return provider->textureId(1) - m_textureId[1];
3908+ } else {
3909+ return -1;
3910+ }
3911+ }
3912+
3913+ quint32 textureId(int index) const Q_DECL_OVERRIDE {
3914+ DASSERT(index <= 1);
3915+ return m_textureId[index];
3916+ }
3917+ void updateShadowTexture(UCShapeType type, quint16 radius, quint16 shadow) {
3918+ m_textureId[0] = m_textureFactory.shadowTexture(0, type, radius, shadow);
3919+ }
3920+ void updateBorderTexture(UCShapeType type, quint16 radius) {
3921+ m_textureId[1] = m_textureFactory.maskTexture(1, type, radius);
3922+ }
3923+
3924+private:
3925+ UCShapeTextureFactory<2> m_textureFactory;
3926+ quint32 m_textureId[2];
3927+};
3928+
3929+class UCShapeFillCornersShadowBorderResources : public UCShapeResources
3930+{
3931+public:
3932+ UCShapeFillCornersShadowBorderResources(
3933+ int vertexCount, int indexCount, int indexType = GL_UNSIGNED_SHORT)
3934+ : m_geometry(attributeSet(), vertexCount, indexCount, indexType) {
3935+ m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
3936+ m_geometry.setIndexDataPattern(QSGGeometry::StaticPattern);
3937+ m_geometry.setVertexDataPattern(QSGGeometry::AlwaysUploadPattern);
3938+ }
3939+
3940+ QSGMaterial* material() Q_DECL_OVERRIDE { return &m_material; }
3941+ QSGMaterial* opaqueMaterial() Q_DECL_OVERRIDE { return &m_opaqueMaterial; }
3942+ QSGGeometry* geometry() Q_DECL_OVERRIDE { return &m_geometry; }
3943+
3944+ struct Vertex {
3945+ float x, y;
3946+ float maskS, maskT;
3947+ float shadowS, shadowT;
3948+ float midShadowS, midShadowT;
3949+ float borderS, borderT;
3950+ quint32 color;
3951+ quint32 shadowColor;
3952+ quint32 borderColor;
3953+ };
3954+
3955+private:
3956+ static const QSGGeometry::AttributeSet& attributeSet() {
3957+ static const QSGGeometry::Attribute attributes[] = {
3958+ QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // x, y
3959+ QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // maskS, maskT
3960+ QSGGeometry::Attribute::create(2, 2, GL_FLOAT), // shadowS, shadowT
3961+ QSGGeometry::Attribute::create(3, 2, GL_FLOAT), // midShadowS, midShadowT
3962+ QSGGeometry::Attribute::create(4, 2, GL_FLOAT), // borderS, borderT
3963+ QSGGeometry::Attribute::create(5, 4, GL_UNSIGNED_BYTE), // color
3964+ QSGGeometry::Attribute::create(6, 4, GL_UNSIGNED_BYTE), // shadowColor
3965+ QSGGeometry::Attribute::create(7, 4, GL_UNSIGNED_BYTE) // borderColor
3966+ };
3967+ static const QSGGeometry::AttributeSet attributeSet = {
3968+ 8, sizeof(Vertex), attributes
3969+ };
3970+ return attributeSet;
3971+ }
3972+
3973+ UCShapeFillCornersShadowBorderMaterial<false> m_material;
3974+ UCShapeFillCornersShadowBorderMaterial<true> m_opaqueMaterial;
3975+ QSGGeometry m_geometry;
3976+};
3977+
3978+// #####################
3979+// # Fill corners node #
3980+// #####################
3981+
3982+class UCShapeFillCornersNode : public QSGGeometryNode
3983+{
3984+public:
3985+ UCShapeFillCornersNode();
3986+ ~UCShapeFillCornersNode();
3987+
3988+ void preprocess() Q_DECL_OVERRIDE;
3989+ bool isSubtreeBlocked() const Q_DECL_OVERRIDE { return !(m_flags & Visible); }
3990+
3991+ void setVisible(bool visible);
3992+ void update(
3993+ const QSizeF& itemSize, UCShapeType type, float radius, QRgb color, float shadowSize,
3994+ float shadowAngle, float shadowDistance, QRgb shadowColor, float borderSize,
3995+ QRgb borderColor);
3996+
3997+private:
3998+ enum {
3999+ HasColor = (1 << 0),
4000+ HasShadow = (1 << 1),
4001+ HasBorder = (1 << 2),
4002+ StyleMask = (HasColor | HasShadow | HasBorder),
4003+ DirtyRadius = (1 << 3),
4004+ DirtyShadow = (1 << 4),
4005+ DirtyShape = (1 << 5),
4006+ DirtyBorderRadius = (1 << 6),
4007+ DirtyMask = (DirtyRadius | DirtyShadow | DirtyShape | DirtyBorderRadius),
4008+ Visible = (1 << 7),
4009+ Blending = (1 << 8)
4010+ };
4011+
4012+ UCShapeResources* m_resources;
4013+ quint16 m_radius;
4014+ quint16 m_shadow;
4015+ quint16 m_borderRadius;
4016+ quint16 m_flags;
4017+ quint8 m_shape;
4018+};
4019+
4020+#endif // UCSHAPEFILLNODES_P_H
4021
4022=== renamed file 'src/UbuntuToolkit/privates/frame.cpp' => 'src/UbuntuToolkit/privates/ucshapeframenodes.cpp'
4023--- src/UbuntuToolkit/privates/frame.cpp 2016-09-09 17:49:07 +0000
4024+++ src/UbuntuToolkit/privates/ucshapeframenodes.cpp 2016-12-14 07:25:05 +0000
4025@@ -16,68 +16,191 @@
4026 * Author: Loïc Molinari <loic.molinari@canonical.com>
4027 */
4028
4029-#include "privates/frame_p.h"
4030+#include "ucshapeframenodes_p.h"
4031
4032-#include <QtGui/QOpenGLContext>
4033+#include <QtGui/QGuiApplication>
4034 #include <QtGui/QOpenGLFunctions>
4035
4036-#include "privates/textures_p.h"
4037-
4038-UT_NAMESPACE_BEGIN
4039-
4040-const QRgb defaultColor = qRgba(255, 255, 255, 255);
4041-const float defaultThickness = 20.0f;
4042-const float defaultRadius = 50.0f;
4043-
4044-// --- Shader ---
4045-
4046-class FrameShader : public QSGMaterialShader
4047+UCShapeFrameEdgesNode::UCShapeFrameEdgesNode()
4048+ : QSGGeometryNode()
4049+ , m_resources(16, 22, GL_UNSIGNED_SHORT)
4050+ , m_visible(0)
4051+ , m_blending(0)
4052+{
4053+ DLOG("creating UCShapeFrameEdgesNode");
4054+
4055+ setMaterial(m_resources.material());
4056+ setOpaqueMaterial(m_resources.opaqueMaterial());
4057+
4058+ // The geometry is made of 16 vertices indexed with a triangle strip mode.
4059+ // 0 ----- 1
4060+ // 2 --- 3
4061+ // 4 5
4062+ // | 6 7 |
4063+ // | | | |
4064+ // | 8 9 |
4065+ // 10 11
4066+ // 12 --- 13
4067+ // 14 ----- 15
4068+ const quint16 indices[] = {
4069+ 0, 2, 1, 3,
4070+ 3, 4, // Degenerate triangle.
4071+ 4, 10, 6, 8,
4072+ 8, 7, // Degenerate triangle.
4073+ 7, 9, 5, 11,
4074+ 11, 12, // Degenerate triangle.
4075+ 12, 14, 13, 15
4076+ };
4077+ memcpy(m_resources.geometry()->indexData(), indices, 22 * sizeof(quint16));
4078+ setGeometry(m_resources.geometry());
4079+
4080+ qsgnode_set_description(this, QLatin1String("shapeframeedges"));
4081+}
4082+
4083+UCShapeFrameEdgesNode::~UCShapeFrameEdgesNode()
4084+{
4085+ DLOG("detroying UCShapeFrameEdgesNode");
4086+}
4087+
4088+void UCShapeFrameEdgesNode::setVisible(bool visible)
4089+{
4090+ DLOG("UCShapeFrameEdgesNode::setVisible %d", visible);
4091+ if (m_visible != visible) {
4092+ m_visible = visible;
4093+ markDirty(DirtySubtreeBlocked);
4094+ }
4095+}
4096+
4097+void UCShapeFrameEdgesNode::update(
4098+ const QSizeF& itemSize, float radius, float thickness, float space, QRgb color)
4099+{
4100+ Q_UNUSED(space);
4101+ // FIXME(loicm) Add space support.
4102+
4103+ UCShapeColorResources::Vertex* v =
4104+ reinterpret_cast<UCShapeColorResources::Vertex*>(m_resources.geometry()->vertexData());
4105+ const float w = static_cast<float>(itemSize.width());
4106+ const float h = static_cast<float>(itemSize.height());
4107+ // FIXME(loicm) Rounded down since renderShape() doesn't support sub-pixel rendering.
4108+ const float maxSize = floorf(qMin(w, h) * 0.5f);
4109+ const float clampedThickness = qMin(floorf(thickness), maxSize);
4110+ const float outerRadius = qMin(floorf(radius), maxSize);
4111+ // FIXME(loicm) Rounded down since renderShape() doesn't support sub-pixel rendering.
4112+ const float innerRadius = floorf(outerRadius * ((maxSize - clampedThickness) / maxSize));
4113+ const quint32 packedColor = packColor(color);
4114+
4115+ v[0].x = outerRadius;
4116+ v[0].y = 0.0f;
4117+ v[0].color = packedColor;
4118+ v[1].x = w - outerRadius;
4119+ v[1].y = 0.0f;
4120+ v[1].color = packedColor;
4121+ v[2].x = clampedThickness + innerRadius;
4122+ v[2].y = clampedThickness;
4123+ v[2].color = packedColor;
4124+ v[3].x = w - clampedThickness - innerRadius;
4125+ v[3].y = clampedThickness;
4126+ v[3].color = packedColor;
4127+ v[4].x = 0.0f;
4128+ v[4].y = outerRadius;
4129+ v[4].color = packedColor;
4130+ v[5].x = w;
4131+ v[5].y = outerRadius;
4132+ v[5].color = packedColor;
4133+ v[6].x = clampedThickness;
4134+ v[6].y = clampedThickness + innerRadius;
4135+ v[6].color = packedColor;
4136+ v[7].x = w - clampedThickness;
4137+ v[7].y = clampedThickness + innerRadius;
4138+ v[7].color = packedColor;
4139+ v[8].x = clampedThickness;
4140+ v[8].y = h - clampedThickness - innerRadius;
4141+ v[8].color = packedColor;
4142+ v[9].x = w - clampedThickness;
4143+ v[9].y = h - clampedThickness - innerRadius;
4144+ v[9].color = packedColor;
4145+ v[10].x = 0.0f;
4146+ v[10].y = h - outerRadius;
4147+ v[10].color = packedColor;
4148+ v[11].x = w;
4149+ v[11].y = h - outerRadius;
4150+ v[11].color = packedColor;
4151+ v[12].x = clampedThickness + innerRadius;
4152+ v[12].y = h - clampedThickness;
4153+ v[12].color = packedColor;
4154+ v[13].x = w - clampedThickness - innerRadius;
4155+ v[13].y = h - clampedThickness;
4156+ v[13].color = packedColor;
4157+ v[14].x = outerRadius;
4158+ v[14].y = h;
4159+ v[14].color = packedColor;
4160+ v[15].x = w - outerRadius;
4161+ v[15].y = h;
4162+ v[15].color = packedColor;
4163+ markDirty(QSGNode::DirtyGeometry);
4164+
4165+ // Update the blending state of the opaque material (in QSG terms, an opaque
4166+ // material is the material automatically used when the opacity is 1, but
4167+ // even if the opacity is 1 we have to handle the case where the alpha of
4168+ // the specified color is less than 1).
4169+ const bool blending = qAlpha(color) < 255;
4170+ if (blending != static_cast<bool>(m_blending)) {
4171+ m_resources.opaqueMaterial()->setFlag(QSGMaterial::Blending, blending);
4172+ markDirty(QSGNode::DirtyMaterial);
4173+ }
4174+}
4175+
4176+class UCShapeFrameCornersShader : public QSGMaterialShader
4177 {
4178 public:
4179- FrameShader();
4180- char const* const* attributeNames() const override;
4181- void initialize() override;
4182+ UCShapeFrameCornersShader();
4183+ char const* const* attributeNames() const Q_DECL_OVERRIDE;
4184+ void initialize() Q_DECL_OVERRIDE;
4185 void updateState(
4186- const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) override;
4187+ const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect) Q_DECL_OVERRIDE;
4188
4189 private:
4190 int m_matrixId;
4191 int m_opacityId;
4192 };
4193
4194-FrameShader::FrameShader()
4195+UCShapeFrameCornersShader::UCShapeFrameCornersShader()
4196 {
4197- setShaderSourceFile(
4198- QOpenGLShader::Vertex, QStringLiteral(":/uc/privates/shaders/frame.vert"));
4199- setShaderSourceFile(
4200- QOpenGLShader::Fragment, QStringLiteral(":/uc/privates/shaders/frame.frag"));
4201+ setShaderSourceFile(QOpenGLShader::Vertex,
4202+ QStringLiteral(":/uc/privates/shaders/texture2.vert"));
4203+ setShaderSourceFile(QOpenGLShader::Fragment,
4204+ QStringLiteral(":/uc/privates/shaders/frame.frag"));
4205 }
4206
4207-char const* const* FrameShader::attributeNames() const
4208+char const* const* UCShapeFrameCornersShader::attributeNames() const
4209 {
4210 static char const* const attributes[] = {
4211- "positionAttrib", "outerCoordAttrib", "innerCoordAttrib", "colorAttrib", 0
4212+ "positionAttrib", "texCoord1Attrib", "texCoord2Attrib", "colorAttrib", 0
4213 };
4214 return attributes;
4215 }
4216
4217-void FrameShader::initialize()
4218+void UCShapeFrameCornersShader::initialize()
4219 {
4220 QSGMaterialShader::initialize();
4221 program()->bind();
4222- program()->setUniformValue("texture", 0);
4223+ const GLint values[2] = { 0, 1 };
4224+ program()->setUniformValueArray("texture", values, 2);
4225 m_matrixId = program()->uniformLocation("matrix");
4226 m_opacityId = program()->uniformLocation("opacity");
4227 }
4228
4229-void FrameShader::updateState(
4230+void UCShapeFrameCornersShader::updateState(
4231 const RenderState& state, QSGMaterial* newEffect, QSGMaterial* oldEffect)
4232 {
4233 Q_UNUSED(oldEffect);
4234
4235 QOpenGLFunctions* funcs = QOpenGLContext::currentContext()->functions();
4236- funcs->glBindTexture(
4237- GL_TEXTURE_2D, static_cast<UCFrameMaterial*>(newEffect)->textureId());
4238+ UCShapeFrameCornersMaterial* material = static_cast<UCShapeFrameCornersMaterial*>(newEffect);
4239+ funcs->glActiveTexture(GL_TEXTURE1);
4240+ funcs->glBindTexture(GL_TEXTURE_2D, material->innerTextureId());
4241+ funcs->glActiveTexture(GL_TEXTURE0);
4242+ funcs->glBindTexture(GL_TEXTURE_2D, material->outerTextureId());
4243
4244 if (state.isMatrixDirty()) {
4245 program()->setUniformValue(m_matrixId, state.combinedMatrix());
4246@@ -87,136 +210,87 @@
4247 }
4248 }
4249
4250-// --- Material ---
4251-
4252-const int maxTextures = 16;
4253-static struct { QOpenGLContext* openglContext; quint32 textureId; } textures[maxTextures];
4254-
4255-// Gets the textures' slot used by the given context, or -1 if not stored.
4256-static int getTexturesIndex(const QOpenGLContext* openglContext)
4257-{
4258- int index = 0;
4259- while (textures[index].openglContext != openglContext) {
4260- index++;
4261- if (index == maxTextures) {
4262- return -1;
4263- }
4264- }
4265- return index;
4266-}
4267-
4268-// Gets an empty textures' slot.
4269-static int getEmptyTexturesIndex()
4270-{
4271- int index = 0;
4272- while (textures[index].openglContext) {
4273- index++;
4274- if (index == maxTextures) {
4275- // Don't bother with a dynamic array, let's just set a high enough
4276- // maxTextures and increase the static array size if ever needed.
4277- qFatal("reached maximum number of OpenGL contexts supported per item.");
4278- }
4279- }
4280- return index;
4281-}
4282-
4283-UCFrameMaterial::UCFrameMaterial()
4284+UCShapeFrameCornersMaterial::UCShapeFrameCornersMaterial()
4285 {
4286 setFlag(Blending, true);
4287-
4288- // Get the texture stored per context and shared by all materials of the same type.
4289- QOpenGLContext* openglContext = QOpenGLContext::currentContext();
4290- int index = getTexturesIndex(openglContext);
4291- if (index < 0) {
4292- QOpenGLFunctions* funcs = openglContext->functions();
4293- index = getEmptyTexturesIndex();
4294- textures[index].openglContext = openglContext;
4295- funcs->glGenTextures(1, &textures[index].textureId);
4296- funcs->glBindTexture(GL_TEXTURE_2D, textures[index].textureId);
4297- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
4298- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4299- // FIXME(loicm) GL_LINEAR_MIPMAP_[NEAREST,LINEAR] perf/quality tradeoff.
4300- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4301- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
4302- // Set the highest mipmap level in order to avoid clamp to edge issues
4303- // with inner corners starting from mipmap level 5 (OpenGL ES 2 doesn't
4304- // support GL_TEXTURE_MAX_LOD).
4305- funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4.0f);
4306- for (int i = 0; i < shapeMipmapCount; i++) {
4307- funcs->glTexImage2D(GL_TEXTURE_2D, i, GL_LUMINANCE, shapeMipmapBaseSize >> i,
4308- shapeMipmapBaseSize >> i, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
4309- &shapeMipmapData[shapeMipmapOffsets[i]]);
4310- }
4311- QObject::connect(
4312- openglContext, &QOpenGLContext::aboutToBeDestroyed, [index] {
4313- QOpenGLFunctions* funcs = textures[index].openglContext->functions();
4314- funcs->glDeleteTextures(1, &textures[index].textureId);
4315- textures[index].openglContext = NULL;
4316- });
4317- }
4318- m_textureId = textures[index].textureId;
4319 }
4320
4321-QSGMaterialType* UCFrameMaterial::type() const
4322+QSGMaterialType* UCShapeFrameCornersMaterial::type() const
4323 {
4324 static QSGMaterialType type;
4325 return &type;
4326 }
4327
4328-QSGMaterialShader* UCFrameMaterial::createShader() const
4329-{
4330- return new FrameShader;
4331-}
4332-
4333-int UCFrameMaterial::compare(const QSGMaterial* other) const
4334-{
4335- Q_UNUSED(other);
4336- return 0;
4337-}
4338-
4339-// --- Node ---
4340-
4341-UCFrameNode::UCFrameNode()
4342+QSGMaterialShader* UCShapeFrameCornersMaterial::createShader() const
4343+{
4344+ return new UCShapeFrameCornersShader;
4345+}
4346+
4347+int UCShapeFrameCornersMaterial::compare(const QSGMaterial* other) const
4348+{
4349+ const UCShapeFrameCornersMaterial* otherFrameCornersMaterial =
4350+ static_cast<const UCShapeFrameCornersMaterial*>(other);
4351+ if (otherFrameCornersMaterial->outerTextureId() != m_textureId[0]) {
4352+ return -1;
4353+ }
4354+ return otherFrameCornersMaterial->innerTextureId() - m_textureId[1];
4355+}
4356+
4357+void UCShapeFrameCornersMaterial::updateTexture(int index, UCShapeType type, quint16 radius)
4358+{
4359+ DASSERT(index >= 0 && index < 2);
4360+ //DASSERT(radius >= 0);
4361+ m_textureId[index] = m_textureFactory.maskTexture(index, type, radius);
4362+}
4363+
4364+UCShapeFrameCornersNode::UCShapeFrameCornersNode()
4365 : QSGGeometryNode()
4366 , m_material()
4367- , m_geometry(attributeSet(), 20, 34, GL_UNSIGNED_SHORT)
4368+ , m_geometry(attributeSet(), 20, 26, GL_UNSIGNED_SHORT)
4369+ , m_radius{0, 0}
4370+ , m_newRadius{0, 0}
4371+ , m_type(0)
4372+ , m_newType(0)
4373+ , m_visible(0)
4374 {
4375- memcpy(m_geometry.indexData(), indices(), 34 * sizeof(unsigned short));
4376+ DLOG("creating UCShapeFrameCornersNode");
4377+ setFlag(QSGNode::UsePreprocess);
4378+ memcpy(m_geometry.indexData(), indices(), 26 * sizeof(quint16));
4379 m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
4380 m_geometry.setIndexDataPattern(QSGGeometry::StaticPattern);
4381 m_geometry.setVertexDataPattern(QSGGeometry::AlwaysUploadPattern);
4382 setMaterial(&m_material);
4383 setGeometry(&m_geometry);
4384- qsgnode_set_description(this, QLatin1String("frame"));
4385+ qsgnode_set_description(this, QLatin1String("shapeframecorners"));
4386 }
4387
4388 // static
4389-const unsigned short* UCFrameNode::indices()
4390+const quint16* UCShapeFrameCornersNode::indices()
4391 {
4392 // The geometry is made of 20 vertices indexed with a triangle strip mode.
4393- // 0 -1 ----- 2- 3
4394- // | 4 --- 5 |
4395- // 6 / \ 9
4396- // | 7 8 |
4397- // | | | |
4398- // | 11 12 |
4399- // 10 \ / 13
4400- // | 14---15 |
4401- // 16 -17 --- 18- 19
4402- static const unsigned short indices[] = {
4403- 6, 7, 0, 4, 1, 5, 2,
4404- 2, 2, // Degenerate triangle.
4405- 2, 5, 3, 8, 9, 12, 13,
4406- 13, 13, // Degenerate triangle.
4407- 13, 12, 19, 15, 18, 14, 17,
4408- 17, 17, // Degenerate triangle.
4409- 17, 14, 16, 11, 10, 7, 6
4410+ // 0 -1 2- 3
4411+ // | 4 5 |
4412+ // 6 / \ 7
4413+ // 8 9
4414+ //
4415+ // 10 11
4416+ // 12 \ / 13
4417+ // | 14 15 |
4418+ // 16 -17 18- 19
4419+ static const quint16 indices[] = {
4420+ 0, 6, 1, 8, 4,
4421+ 4, 5, // Degenerate triangle.
4422+ 5, 9, 2, 7, 3,
4423+ 3, 16, // Degenerate triangle.
4424+ 16, 12, 17, 10, 14,
4425+ 14, 15, // Degenerate triangle.
4426+ 15, 11, 18, 13, 19
4427 };
4428 return indices;
4429 }
4430
4431 // static
4432-const QSGGeometry::AttributeSet& UCFrameNode::attributeSet()
4433+const QSGGeometry::AttributeSet& UCShapeFrameCornersNode::attributeSet()
4434 {
4435 static const QSGGeometry::Attribute attributes[] = {
4436 QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),
4437@@ -230,246 +304,238 @@
4438 return attributeSet;
4439 }
4440
4441-// Pack a color in a premultiplied 32-bit ABGR value.
4442-static quint32 packColor(QRgb color)
4443-{
4444- const quint32 a = qAlpha(color);
4445- const quint32 b = ((qBlue(color) * a) + 0xff) >> 8;
4446- const quint32 g = ((qGreen(color) * a) + 0xff) >> 8;
4447- const quint32 r = ((qRed(color) * a) + 0xff) >> 8;
4448- return (a << 24) | ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff);
4449-}
4450-
4451-void UCFrameNode::updateGeometry(
4452- const QSizeF& itemSize, float thickness, float radius, QRgb color)
4453-{
4454- UCFrameNode::Vertex* v = reinterpret_cast<UCFrameNode::Vertex*>(m_geometry.vertexData());
4455+void UCShapeFrameCornersNode::preprocess()
4456+{
4457+ const bool hasNewType = m_newType != m_type;
4458+ for (int i = 0; i < 2; i++) {
4459+ if (hasNewType || m_newRadius[i] != m_radius[i]) {
4460+ m_material.updateTexture(i, static_cast<UCShapeType>(m_newType), m_newRadius[i]);
4461+ m_radius[i] = m_newRadius[i];
4462+ }
4463+ }
4464+ if (hasNewType) {
4465+ m_type = m_newType;
4466+ }
4467+}
4468+
4469+void UCShapeFrameCornersNode::setVisible(bool visible)
4470+{
4471+ DLOG("UCShapeFrameCornersNode::setVisible %d", visible);
4472+ if (m_visible != visible) {
4473+ m_visible = visible;
4474+ markDirty(DirtySubtreeBlocked);
4475+ }
4476+}
4477+
4478+void UCShapeFrameCornersNode::update(
4479+ const QSizeF& itemSize, UCShapeType type, float radius, float thickness, float space,
4480+ QRgb color)
4481+{
4482+ Q_UNUSED(space);
4483+ // FIXME(loicm) Add space support.
4484+
4485+ // FIXME(loicm) Temp hack to hide the broken rendering of corners which
4486+ // slightly appears when the thickness is less than 1.
4487+ if (thickness < 1.0f) {
4488+ radius = 0.0f;
4489+ }
4490+
4491+ UCShapeFrameCornersNode::Vertex* v =
4492+ reinterpret_cast<UCShapeFrameCornersNode::Vertex*>(m_geometry.vertexData());
4493+ const float devicePixelRatio = qGuiApp->devicePixelRatio();
4494 const float w = static_cast<float>(itemSize.width());
4495 const float h = static_cast<float>(itemSize.height());
4496- const float maxSize = qMin(w, h) * 0.5f;
4497- const float clampedThickness = qMin(thickness, maxSize);
4498- const float radiusOut = qBound(0.01f, radius, maxSize);
4499- const float radiusIn = radiusOut * ((maxSize - clampedThickness) / maxSize);
4500- const float outerCoord1 =
4501- (((1.0f - shapeOffset) / radiusOut) * (clampedThickness + radiusIn)) + shapeOffset;
4502- const float outerCoord2 =
4503- (((1.0f - shapeOffset) / radiusOut) * clampedThickness) + shapeOffset;
4504- const float innerCoord1 =
4505- (((1.0f - shapeOffset) / radiusIn) * -clampedThickness) + shapeOffset;
4506- const float innerCoord2 =
4507- (((1.0f - shapeOffset) / radiusIn) * (radiusOut - clampedThickness)) + shapeOffset;
4508+ // FIXME(loicm) Rounded down since renderShape() doesn't support sub-pixel rendering.
4509+ const float maxSize = floorf(qMin(w, h) * 0.5f);
4510+ const float clampedThickness = qMin(floorf(thickness), maxSize);
4511+ const float deviceThickness = clampedThickness * devicePixelRatio;
4512+ const float border = 1.0f;
4513+ const float outerRadius = qMin(floorf(radius), maxSize);
4514+ const float deviceOuterRadius = outerRadius * devicePixelRatio;
4515+ // FIXME(loicm) Rounded down since renderShape() doesn't support sub-pixel rendering.
4516+ const float outerRadiusRounded =
4517+ roundUp(static_cast<int>(deviceOuterRadius + 2 * border), textureRounding);
4518+ const float innerRadius = floorf(outerRadius * ((maxSize - clampedThickness) / maxSize));
4519+ const float deviceInnerRadius = innerRadius * devicePixelRatio;
4520+ const float innerRadiusRounded =
4521+ roundUp(static_cast<int>(deviceInnerRadius + 2 * border), textureRounding);
4522+
4523+ const float outerRadiusOffset = outerRadiusRounded - deviceOuterRadius - border;
4524+ const float outerTextureFactor = 1.0f / outerRadiusRounded;
4525+ const float outerS0 = outerTextureFactor * outerRadiusOffset;
4526+ const float outerS1 = outerTextureFactor * (outerRadiusOffset + deviceOuterRadius);
4527+ const float outerS2 = outerTextureFactor * (outerRadiusOffset + deviceThickness);
4528+ const float outerS3 =
4529+ outerTextureFactor * (outerRadiusOffset + deviceThickness + deviceInnerRadius);
4530+
4531+ const float innerRadiusOffset = innerRadiusRounded - deviceInnerRadius - border;
4532+ const float innerTextureFactor = 1.0f / innerRadiusRounded;
4533+ const float innerS0 = innerTextureFactor * innerRadiusOffset;
4534+ const float innerS1 = innerTextureFactor * (innerRadiusOffset + deviceInnerRadius);
4535+ const float innerS2 = innerTextureFactor * (innerRadiusOffset - deviceThickness);
4536+ const float innerS3 =
4537+ innerTextureFactor * (innerRadiusOffset - deviceThickness + deviceOuterRadius);
4538+
4539 const quint32 packedColor = packColor(color);
4540
4541- // 1st row.
4542 v[0].x = 0.0f;
4543 v[0].y = 0.0f;
4544- v[0].s1 = shapeOffset;
4545- v[0].t1 = shapeOffset;
4546- v[0].s2 = innerCoord1;
4547- v[0].t2 = innerCoord1;
4548+ v[0].outerS = outerS0;
4549+ v[0].outerT = outerS0;
4550+ v[0].innerS = innerS2;
4551+ v[0].innerT = innerS2;
4552 v[0].color = packedColor;
4553- v[1].x = radiusOut;
4554+ v[1].x = outerRadius;
4555 v[1].y = 0.0f;
4556- v[1].s1 = 1.0f;
4557- v[1].t1 = shapeOffset;
4558- v[1].s2 = innerCoord2;
4559- v[1].t2 = innerCoord1;
4560+ v[1].outerS = outerS1;
4561+ v[1].outerT = outerS0;
4562+ v[1].innerS = innerS3;
4563+ v[1].innerT = innerS2;
4564 v[1].color = packedColor;
4565- v[2].x = w - radiusOut;
4566+ v[2].x = w - outerRadius;
4567 v[2].y = 0.0f;
4568- v[2].s1 = 1.0f;
4569- v[2].t1 = shapeOffset;
4570- v[2].s2 = innerCoord2;
4571- v[2].t2 = innerCoord1;
4572+ v[2].outerS = outerS1;
4573+ v[2].outerT = outerS0;
4574+ v[2].innerS = innerS3;
4575+ v[2].innerT = innerS2;
4576 v[2].color = packedColor;
4577 v[3].x = w;
4578 v[3].y = 0.0f;
4579- v[3].s1 = shapeOffset;
4580- v[3].t1 = shapeOffset;
4581- v[3].s2 = innerCoord1;
4582- v[3].t2 = innerCoord1;
4583+ v[3].outerS = outerS0;
4584+ v[3].outerT = outerS0;
4585+ v[3].innerS = innerS2;
4586+ v[3].innerT = innerS2;
4587 v[3].color = packedColor;
4588
4589- // 2nd row.
4590- v[4].x = clampedThickness + radiusIn;
4591+ v[4].x = clampedThickness + innerRadius;
4592 v[4].y = clampedThickness;
4593- v[4].s1 = outerCoord1;
4594- v[4].t1 = outerCoord2;
4595- v[4].s2 = 1.0f;
4596- v[4].t2 = shapeOffset;
4597+ v[4].outerS = outerS3;
4598+ v[4].outerT = outerS2;
4599+ v[4].innerS = innerS1;
4600+ v[4].innerT = innerS0;
4601 v[4].color = packedColor;
4602- v[5].x = w - (clampedThickness + radiusIn);
4603+ v[5].x = w - (clampedThickness + innerRadius);
4604 v[5].y = clampedThickness;
4605- v[5].s1 = outerCoord1;
4606- v[5].t1 = outerCoord2;
4607- v[5].s2 = 1.0f;
4608- v[5].t2 = shapeOffset;
4609+ v[5].outerS = outerS3;
4610+ v[5].outerT = outerS2;
4611+ v[5].innerS = innerS1;
4612+ v[5].innerT = innerS0;
4613 v[5].color = packedColor;
4614
4615- // 3rd row.
4616 v[6].x = 0.0f;
4617- v[6].y = radiusOut;
4618- v[6].s1 = shapeOffset;
4619- v[6].t1 = 1.0f;
4620- v[6].s2 = innerCoord1;
4621- v[6].t2 = innerCoord2;
4622+ v[6].y = outerRadius;
4623+ v[6].outerS = outerS0;
4624+ v[6].outerT = outerS1;
4625+ v[6].innerS = innerS2;
4626+ v[6].innerT = innerS3;
4627 v[6].color = packedColor;
4628- v[7].x = clampedThickness;
4629- v[7].y = clampedThickness + radiusIn;
4630- v[7].s1 = outerCoord2;
4631- v[7].t1 = outerCoord1;
4632- v[7].s2 = shapeOffset;
4633- v[7].t2 = 1.0f;
4634+ v[7].x = w;
4635+ v[7].y = outerRadius;
4636+ v[7].outerS = outerS0;
4637+ v[7].outerT = outerS1;
4638+ v[7].innerS = innerS2;
4639+ v[7].innerT = innerS3;
4640 v[7].color = packedColor;
4641- v[8].x = w - clampedThickness;
4642- v[8].y = clampedThickness + radiusIn;
4643- v[8].s1 = outerCoord2;
4644- v[8].t1 = outerCoord1;
4645- v[8].s2 = shapeOffset;
4646- v[8].t2 = 1.0f;
4647+
4648+ v[8].x = clampedThickness;
4649+ v[8].y = clampedThickness + innerRadius;
4650+ v[8].outerS = outerS2;
4651+ v[8].outerT = outerS3;
4652+ v[8].innerS = innerS0;
4653+ v[8].innerT = innerS1;
4654 v[8].color = packedColor;
4655- v[9].x = w;
4656- v[9].y = radiusOut;
4657- v[9].s1 = shapeOffset;
4658- v[9].t1 = 1.0f;
4659- v[9].s2 = innerCoord1;
4660- v[9].t2 = innerCoord2;
4661+ v[9].x = w - clampedThickness;
4662+ v[9].y = clampedThickness + innerRadius;
4663+ v[9].outerS = outerS2;
4664+ v[9].outerT = outerS3;
4665+ v[9].innerS = innerS0;
4666+ v[9].innerT = innerS1;
4667 v[9].color = packedColor;
4668
4669- // 4th row.
4670- v[10].x = 0.0f;
4671- v[10].y = h - radiusOut;
4672- v[10].s1 = shapeOffset;
4673- v[10].t1 = 1.0f;
4674- v[10].s2 = innerCoord1;
4675- v[10].t2 = innerCoord2;
4676+ v[10].x = clampedThickness;
4677+ v[10].y = h - (clampedThickness + innerRadius);
4678+ v[10].outerS = outerS2;
4679+ v[10].outerT = outerS3;
4680+ v[10].innerS = innerS0;
4681+ v[10].innerT = innerS1;
4682 v[10].color = packedColor;
4683- v[11].x = clampedThickness;
4684- v[11].y = h - (clampedThickness + radiusIn);
4685- v[11].s1 = outerCoord2;
4686- v[11].t1 = outerCoord1;
4687- v[11].s2 = shapeOffset;
4688- v[11].t2 = 1.0f;
4689+ v[11].x = w - clampedThickness;
4690+ v[11].y = h - (clampedThickness + innerRadius);
4691+ v[11].outerS = outerS2;
4692+ v[11].outerT = outerS3;
4693+ v[11].innerS = innerS0;
4694+ v[11].innerT = innerS1;
4695 v[11].color = packedColor;
4696- v[12].x = w - clampedThickness;
4697- v[12].y = h - (clampedThickness + radiusIn);
4698- v[12].s1 = outerCoord2;
4699- v[12].t1 = outerCoord1;
4700- v[12].s2 = shapeOffset;
4701- v[12].t2 = 1.0f;
4702+
4703+ v[12].x = 0.0f;
4704+ v[12].y = h - outerRadius;
4705+ v[12].outerS = outerS0;
4706+ v[12].outerT = outerS1;
4707+ v[12].innerS = innerS2;
4708+ v[12].innerT = innerS3;
4709 v[12].color = packedColor;
4710 v[13].x = w;
4711- v[13].y = h - radiusOut;
4712- v[13].s1 = shapeOffset;
4713- v[13].t1 = 1.0f;
4714- v[13].s2 = innerCoord1;
4715- v[13].t2 = innerCoord2;
4716+ v[13].y = h - outerRadius;
4717+ v[13].outerS = outerS0;
4718+ v[13].outerT = outerS1;
4719+ v[13].innerS = innerS2;
4720+ v[13].innerT = innerS3;
4721 v[13].color = packedColor;
4722
4723- // 5th row.
4724- v[14].x = clampedThickness + radiusIn;
4725+ v[14].x = clampedThickness + innerRadius;
4726 v[14].y = h - clampedThickness;
4727- v[14].s1 = outerCoord1;
4728- v[14].t1 = outerCoord2;
4729- v[14].s2 = 1.0f;
4730- v[14].t2 = shapeOffset;
4731+ v[14].outerS = outerS3;
4732+ v[14].outerT = outerS2;
4733+ v[14].innerS = innerS1;
4734+ v[14].innerT = innerS0;
4735 v[14].color = packedColor;
4736- v[15].x = w - (clampedThickness + radiusIn);
4737+ v[15].x = w - (clampedThickness + innerRadius);
4738 v[15].y = h - clampedThickness;
4739- v[15].s1 = outerCoord1;
4740- v[15].t1 = outerCoord2;
4741- v[15].s2 = 1.0f;
4742- v[15].t2 = shapeOffset;
4743+ v[15].outerS = outerS3;
4744+ v[15].outerT = outerS2;
4745+ v[15].innerS = innerS1;
4746+ v[15].innerT = innerS0;
4747 v[15].color = packedColor;
4748
4749- // 6th row.
4750 v[16].x = 0.0f;
4751 v[16].y = h;
4752- v[16].s1 = shapeOffset;
4753- v[16].t1 = shapeOffset;
4754- v[16].s2 = innerCoord1;
4755- v[16].t2 = innerCoord1;
4756+ v[16].outerS = outerS0;
4757+ v[16].outerT = outerS0;
4758+ v[16].innerS = innerS2;
4759+ v[16].innerT = innerS2;
4760 v[16].color = packedColor;
4761- v[17].x = radiusOut;
4762+ v[17].x = outerRadius;
4763 v[17].y = h;
4764- v[17].s1 = 1.0f;
4765- v[17].t1 = shapeOffset;
4766- v[17].s2 = innerCoord2;
4767- v[17].t2 = innerCoord1;
4768+ v[17].outerS = outerS1;
4769+ v[17].outerT = outerS0;
4770+ v[17].innerS = innerS3;
4771+ v[17].innerT = innerS2;
4772 v[17].color = packedColor;
4773- v[18].x = w - radiusOut;
4774+ v[18].x = w - outerRadius;
4775 v[18].y = h;
4776- v[18].s1 = 1.0f;
4777- v[18].t1 = shapeOffset;
4778- v[18].s2 = innerCoord2;
4779- v[18].t2 = innerCoord1;
4780+ v[18].outerS = outerS1;
4781+ v[18].outerT = outerS0;
4782+ v[18].innerS = innerS3;
4783+ v[18].innerT = innerS2;
4784 v[18].color = packedColor;
4785 v[19].x = w;
4786 v[19].y = h;
4787- v[19].s1 = shapeOffset;
4788- v[19].t1 = shapeOffset;
4789- v[19].s2 = innerCoord1;
4790- v[19].t2 = innerCoord1;
4791+ v[19].outerS = outerS0;
4792+ v[19].outerT = outerS0;
4793+ v[19].innerS = innerS2;
4794+ v[19].innerT = innerS2;
4795 v[19].color = packedColor;
4796
4797 markDirty(QSGNode::DirtyGeometry);
4798-}
4799-
4800-// --- Item ---
4801-
4802-UCFrame::UCFrame(QQuickItem* parent)
4803- : QQuickItem(parent)
4804- , m_color(defaultColor)
4805- , m_thickness(defaultThickness)
4806- , m_radius(defaultRadius)
4807-{
4808- setFlag(ItemHasContents);
4809-}
4810-
4811-void UCFrame::setThickness(qreal thickness)
4812-{
4813- thickness = qMax(0.0f, static_cast<float>(thickness));
4814- if (m_thickness != thickness) {
4815- m_thickness = thickness;
4816- update();
4817- Q_EMIT thicknessChanged();
4818- }
4819-}
4820-
4821-void UCFrame::setRadius(qreal radius)
4822-{
4823- radius = qMax(0.0f, static_cast<float>(radius));
4824- if (m_radius != radius) {
4825- m_radius = radius;
4826- update();
4827- Q_EMIT radiusChanged();
4828- }
4829-}
4830-
4831-void UCFrame::setColor(const QColor& color)
4832-{
4833- const QRgb rgbColor = qRgba(color.red(), color.green(), color.blue(), color.alpha());
4834- if (m_color != rgbColor) {
4835- m_color = rgbColor;
4836- update();
4837- Q_EMIT colorChanged();
4838- }
4839-}
4840-
4841-QSGNode* UCFrame::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data)
4842-{
4843- Q_UNUSED(data);
4844-
4845- const QSizeF itemSize(width(), height());
4846- if (itemSize.isEmpty() || m_thickness <= 0.0f) {
4847- delete oldNode;
4848- return NULL;
4849- }
4850-
4851- UCFrameNode* node = oldNode ? static_cast<UCFrameNode*>(oldNode) : new UCFrameNode();
4852- node->updateGeometry(itemSize, m_thickness, m_radius, m_color);
4853-
4854- return node;
4855-}
4856-
4857-UT_NAMESPACE_END
4858+
4859+ // Update data for the preprocess() call.
4860+ if (m_radius[0] != static_cast<quint16>(deviceOuterRadius)) {
4861+ m_newRadius[0] = static_cast<quint16>(deviceOuterRadius);
4862+ }
4863+ if (m_radius[1] != static_cast<quint16>(deviceInnerRadius)) {
4864+ m_newRadius[1] = static_cast<quint16>(deviceInnerRadius);
4865+ }
4866+ if (m_type != static_cast<quint8>(type)) {
4867+ m_newType = static_cast<quint8>(type);
4868+ }
4869+}
4870
4871=== renamed file 'src/UbuntuToolkit/privates/frame_p.h' => 'src/UbuntuToolkit/privates/ucshapeframenodes_p.h'
4872--- src/UbuntuToolkit/privates/frame_p.h 2016-09-09 17:49:07 +0000
4873+++ src/UbuntuToolkit/privates/ucshapeframenodes_p.h 2016-12-14 07:25:05 +0000
4874@@ -16,90 +16,79 @@
4875 * Author: Loïc Molinari <loic.molinari@canonical.com>
4876 */
4877
4878-#ifndef FRAME_P_H
4879-#define FRAME_P_H
4880+#ifndef UCSHAPEFRAMENODES_P_H
4881+#define UCSHAPEFRAMENODES_P_H
4882
4883 #include <QtQuick/QQuickItem>
4884-#include <QtQuick/QSGMaterial>
4885 #include <QtQuick/QSGNode>
4886
4887-#include <UbuntuToolkit/ubuntutoolkitglobal.h>
4888-
4889-UT_NAMESPACE_BEGIN
4890-
4891-class UCFrameMaterial : public QSGMaterial
4892-{
4893-public:
4894- UCFrameMaterial();
4895- QSGMaterialType* type() const override;
4896- QSGMaterialShader* createShader() const override;
4897- int compare(const QSGMaterial* other) const override;
4898-
4899- quint32 textureId() const { return m_textureId; }
4900-
4901-private:
4902- quint32 m_textureId;
4903-};
4904-
4905-class UCFrameNode : public QSGGeometryNode
4906-{
4907-public:
4908- struct Vertex { float x, y, s1, t1, s2, t2; quint32 color; };
4909-
4910- static const unsigned short* indices();
4911+#include <UbuntuToolkit/private/ucshapetexturefactory_p.h>
4912+#include <UbuntuToolkit/private/ucshaperesources_p.h>
4913+
4914+class UCShapeFrameEdgesNode : public QSGGeometryNode
4915+{
4916+public:
4917+ UCShapeFrameEdgesNode();
4918+ ~UCShapeFrameEdgesNode();
4919+
4920+ bool isSubtreeBlocked() const Q_DECL_OVERRIDE { return m_visible == 0; }
4921+
4922+ void setVisible(bool visible);
4923+ void update(const QSizeF& itemSize, float radius, float thickness, float space, QRgb color);
4924+
4925+private:
4926+ UCShapeColorResources m_resources;
4927+ quint8 m_visible : 1;
4928+ quint8 m_blending : 1;
4929+ quint8 __padding : 6;
4930+};
4931+
4932+class UCShapeFrameCornersMaterial : public QSGMaterial
4933+{
4934+public:
4935+ UCShapeFrameCornersMaterial();
4936+ QSGMaterialType* type() const Q_DECL_OVERRIDE;
4937+ QSGMaterialShader* createShader() const Q_DECL_OVERRIDE;
4938+ int compare(const QSGMaterial* other) const Q_DECL_OVERRIDE;
4939+
4940+ quint32 outerTextureId() const { return m_textureId[0]; }
4941+ quint32 innerTextureId() const { return m_textureId[1]; }
4942+ void updateTexture(int index, UCShapeType type, quint16 radius);
4943+
4944+private:
4945+ UCShapeTextureFactory<2> m_textureFactory;
4946+ quint32 m_textureId[2];
4947+};
4948+
4949+class UCShapeFrameCornersNode : public QSGGeometryNode
4950+{
4951+public:
4952+ struct Vertex { float x, y, outerS, outerT, innerS, innerT; quint32 color; };
4953+
4954+ static const quint16* indices();
4955 static const QSGGeometry::AttributeSet& attributeSet();
4956
4957- UCFrameNode();
4958- void updateGeometry(const QSizeF& itemSize, float thickness, float radius, QRgb color);
4959+ UCShapeFrameCornersNode();
4960+ ~UCShapeFrameCornersNode() { DLOG("detroying UCShapeFrameCornersNode"); }
4961+
4962+ void preprocess() Q_DECL_OVERRIDE;
4963+ bool isSubtreeBlocked() const Q_DECL_OVERRIDE { return m_visible == 0; }
4964+
4965+ void setVisible(bool visible);
4966+ void update(
4967+ const QSizeF& itemSize, UCShapeType type, float radius, float thickness, float space,
4968+ QRgb color);
4969
4970 private:
4971- UCFrameMaterial m_material;
4972+ UCShapeFrameCornersMaterial m_material;
4973 QSGGeometry m_geometry;
4974-};
4975-
4976-// Renders the frame (border) of a shape.
4977-class UBUNTUTOOLKIT_EXPORT UCFrame : public QQuickItem
4978-{
4979- Q_OBJECT
4980-
4981- // Thickness of the frame in pixels.
4982- Q_PROPERTY(qreal thickness READ thickness WRITE setThickness NOTIFY thicknessChanged)
4983-
4984- // Radius of the shape in pixels. A rectangle frame could be obtained using
4985- // a radius of 0 but it's recommended to use a Ractangle with a border for
4986- // that as it is a bit more efficient in term of rendering speed (reason is
4987- // we don't bother to specify a dedicated mesh and shader when radius is 0).
4988- Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged)
4989-
4990- // Color of the frame. Translucent colors are supported too.
4991- Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
4992-
4993-public:
4994- UCFrame(QQuickItem* parent = 0);
4995-
4996- qreal thickness() const { return m_thickness; }
4997- void setThickness(qreal thickness);
4998- qreal radius() const { return m_radius; }
4999- void setRadius(qreal radius);
5000- QColor color() const {
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches