@@ -6,7 +6,17 @@ var MAX_MITER_LIMIT = 100;
66
77/* Flags are passed to the vertex shader in a float. Since a 32-bit float has
88 * 24 bits of mantissa, including the sign bit, a maximum of 23 bits of flags
9- * can be passed in a float without loss or complication. */
9+ * can be passed in a float without loss or complication.
10+ * The flags*Shift values are the bit offsets within the flag value. The
11+ * flags*Mult values are the bit-offset values converted to a multiplier (2
12+ * raised to the offset value). The overall flags value is composed of:
13+ * bits 0-1: vertex (corner, near, far) used by the shader to know where in
14+ * the geometry the vertex is used.
15+ * 2-4: near cap/join style
16+ * 5-7: far cap/join style
17+ * 8-18: stroke offset as a signed value in the range [-1023,1023] which
18+ * maps to a floating-point stroke offset of [-1,1].
19+ */
1020/* vertex flags specify which direction a vertex needs to be offset */
1121var flagsVertex = { // uses 2 bits
1222 corner : 0 ,
@@ -25,8 +35,10 @@ var flagsLineJoin = { // uses 3 bits with flagsLineCap
2535 round : 6 ,
2636 'miter-clip' : 7
2737} ;
28- var flagsNearLineShift = 2 , flagsFarLineShift = 5 ;
29- var flagsNearOffsetShift = 8 ; // uses 11 bits
38+ var flagsNearLineShift = 2 , flagsNearLineMult = 1 << flagsNearLineShift ;
39+ var flagsFarLineShift = 5 , flagsFarLineMult = 1 << flagsFarLineShift ;
40+ var flagsNearOffsetShift = 8 , // uses 11 bits
41+ flagsNearOffsetMult = 1 << flagsNearOffsetShift ;
3042/* Fixed flags */
3143var flagsDebug = { // uses 1 bit
3244 normal : 0 ,
@@ -113,11 +125,17 @@ var webgl_lineFeature = function (arg) {
113125 */
114126 function createGLLines ( onlyStyle ) {
115127 var data = m_this . data ( ) ,
116- d , i , j , k , v , v2 , lidx ,
128+ d , i , j , k , v1 , v2 , lidx , maxj ,
117129 numSegments = 0 , len ,
118130 lineItemList , lineItem , lineItemData ,
119- vert = [ { } , { } ] , v1 = vert [ 1 ] ,
131+ vert = [ {
132+ strokeOffset : 0 , posStrokeOffset : 0 , negStrokeOffset : 0
133+ } , {
134+ strokeOffset : 0 , posStrokeOffset : 0 , negStrokeOffset : 0
135+ } ] ,
136+ v = vert [ 1 ] ,
120137 pos , posIdx3 , firstpos , firstPosIdx3 ,
138+ lineFunc = m_this . line ( ) ,
121139 strokeWidthFunc = m_this . style . get ( 'strokeWidth' ) , strokeWidthVal ,
122140 strokeColorFunc = m_this . style . get ( 'strokeColor' ) , strokeColorVal ,
123141 strokeOpacityFunc = m_this . style . get ( 'strokeOpacity' ) , strokeOpacityVal ,
@@ -126,19 +144,20 @@ var webgl_lineFeature = function (arg) {
126144 strokeOffsetFunc = m_this . style . get ( 'strokeOffset' ) , strokeOffsetVal ,
127145 miterLimit = m_this . style . get ( 'miterLimit' ) ( data ) ,
128146 antialiasing = m_this . style . get ( 'antialiasing' ) ( data ) || 0 ,
129- order = m_this . featureVertices ( ) ,
147+ order = m_this . featureVertices ( ) , orderk0 , prevkey , nextkey , offkey ,
130148 orderLen = order . length ,
131- posBuf , prevBuf , nextBuf , farBuf , flagsBuf , indicesBuf ,
149+ // webgl buffers; see _init for details
150+ posBuf , prevBuf , nextBuf , farBuf , flagsBuf ,
132151 fixedFlags = ( flagsDebug [ m_this . style . get ( 'debug' ) ( data ) ? 'debug' : 'normal' ] || 0 ) ,
133152 strokeWidthBuf , strokeColorBuf , strokeOpacityBuf ,
134153 dest , dest3 ,
135154 geom = m_mapper . geometryData ( ) ,
136- closedFunc = m_this . style . get ( 'closed' ) , closedVal , closed = [ ] ,
155+ closedFunc = m_this . style . get ( 'closed' ) , closedVal , closed ,
137156 updateFlags = true ;
138157
139158 closedVal = util . isFunction ( m_this . style ( 'closed' ) ) ? undefined : ( closedFunc ( ) || false ) ;
140- lineCapVal = util . isFunction ( m_this . style ( 'lineCap' ) ) ? undefined : ( lineCapFunc ( ) || 'butt' ) ;
141- lineJoinVal = util . isFunction ( m_this . style ( 'lineJoin' ) ) ? undefined : ( lineJoinFunc ( ) || 'miter' ) ;
159+ lineCapVal = util . isFunction ( m_this . style ( 'lineCap' ) ) ? undefined : flagsLineCap [ lineCapFunc ( ) || 'butt' ] ;
160+ lineJoinVal = util . isFunction ( m_this . style ( 'lineJoin' ) ) ? undefined : flagsLineJoin [ lineJoinFunc ( ) || 'miter' ] ;
142161 strokeColorVal = util . isFunction ( m_this . style ( 'strokeColor' ) ) ? undefined : strokeColorFunc ( ) ;
143162 strokeOffsetVal = util . isFunction ( m_this . style ( 'strokeOffset' ) ) ? undefined : ( strokeOffsetFunc ( ) || 0 ) ;
144163 strokeOpacityVal = util . isFunction ( m_this . style ( 'strokeOpacity' ) ) ? undefined : strokeOpacityFunc ( ) ;
@@ -157,9 +176,10 @@ var webgl_lineFeature = function (arg) {
157176 var position = [ ] ,
158177 posFunc = m_this . position ( ) ;
159178 lineItemList = new Array ( data . length ) ;
179+ closed = new Array ( data . length ) ;
160180 for ( i = 0 ; i < data . length ; i += 1 ) {
161181 d = data [ i ] ;
162- lineItem = m_this . line ( ) ( d , i ) ;
182+ lineItem = lineFunc ( d , i ) ;
163183 lineItemList [ i ] = lineItem ;
164184 if ( lineItem . length < 2 ) {
165185 continue ;
@@ -183,6 +203,8 @@ var webgl_lineFeature = function (arg) {
183203 } else {
184204 closed [ i ] = 1 ; /* first point is repeated as last point */
185205 }
206+ } else {
207+ closed [ i ] = 0 ;
186208 }
187209 }
188210
@@ -204,10 +226,8 @@ var webgl_lineFeature = function (arg) {
204226 nextBuf = util . getGeomBuffer ( geom , 'next' , len * 3 ) ;
205227 farBuf = util . getGeomBuffer ( geom , 'far' , len * 3 ) ;
206228
207- indicesBuf = geom . primitive ( 0 ) . indices ( ) ;
208- if ( ! ( indicesBuf instanceof Uint16Array ) || indicesBuf . length !== len ) {
209- indicesBuf = new Uint16Array ( len ) ;
210- geom . primitive ( 0 ) . setIndices ( indicesBuf ) ;
229+ if ( geom . primitive ( 0 ) . numberOfIndices ( ) !== len ) {
230+ geom . primitive ( 0 ) . numberOfIndices = function ( ) { return len ; } ;
211231 }
212232 // save some information to be reused when we update only style
213233 m_geometry = {
@@ -241,8 +261,10 @@ var webgl_lineFeature = function (arg) {
241261 continue ;
242262 }
243263 d = data [ i ] ;
264+ closedVal = closed [ i ] ;
244265 firstPosIdx3 = posIdx3 ;
245- for ( j = 0 ; j < lineItem . length + ( closed [ i ] === 2 ? 1 : 0 ) ; j += 1 , posIdx3 += 3 ) {
266+ maxj = lineItem . length + ( closedVal === 2 ? 1 : 0 ) ;
267+ for ( j = 0 ; j < maxj ; j += 1 , posIdx3 += 3 ) {
246268 lidx = j ;
247269 if ( j === lineItem . length ) {
248270 lidx = 0 ;
@@ -252,101 +274,92 @@ var webgl_lineFeature = function (arg) {
252274 /* swap entries in vert so that vert[0] is the first vertex, and
253275 * vert[1] will be reused for the second vertex */
254276 if ( j ) {
255- v1 = vert [ 0 ] ;
277+ v = vert [ 0 ] ;
256278 vert [ 0 ] = vert [ 1 ] ;
257- vert [ 1 ] = v1 ;
279+ vert [ 1 ] = v ;
258280 }
259281 if ( ! onlyStyle ) {
260- v1 . pos = j === lidx ? posIdx3 : firstPosIdx3 ;
261- v1 . prev = lidx ? posIdx3 - 3 : ( closed [ i ] ?
262- firstPosIdx3 + ( lineItem . length - 3 + closed [ i ] ) * 3 : posIdx3 ) ;
263- v1 . next = j + 1 < lineItem . length ? posIdx3 + 3 : ( closed [ i ] ?
264- ( j !== lidx ? firstPosIdx3 + 3 : firstPosIdx3 + 6 - closed [ i ] * 3 ) :
282+ v . pos = j === lidx ? posIdx3 : firstPosIdx3 ;
283+ v . prev = lidx ? posIdx3 - 3 : ( closedVal ?
284+ firstPosIdx3 + ( lineItem . length - 3 + closedVal ) * 3 : posIdx3 ) ;
285+ v . next = j + 1 < lineItem . length ? posIdx3 + 3 : ( closedVal ?
286+ ( j !== lidx ? firstPosIdx3 + 3 : firstPosIdx3 + 6 - closedVal * 3 ) :
265287 posIdx3 ) ;
266288 }
267- v1 . strokeWidth = strokeWidthVal === undefined ? strokeWidthFunc ( lineItemData , lidx , d , i ) : strokeWidthVal ;
268- v1 . strokeColor = strokeColorVal === undefined ? strokeColorFunc ( lineItemData , lidx , d , i ) : strokeColorVal ;
269- v1 . strokeOpacity = strokeOpacityVal === undefined ? strokeOpacityFunc ( lineItemData , lidx , d , i ) : strokeOpacityVal ;
289+ v . strokeWidth = strokeWidthVal === undefined ? strokeWidthFunc ( lineItemData , lidx , d , i ) : strokeWidthVal ;
290+ v . strokeColor = strokeColorVal === undefined ? strokeColorFunc ( lineItemData , lidx , d , i ) : strokeColorVal ;
291+ v . strokeOpacity = strokeOpacityVal === undefined ? strokeOpacityFunc ( lineItemData , lidx , d , i ) : strokeOpacityVal ;
270292 if ( updateFlags ) {
271- v1 . strokeOffset = ( strokeOffsetVal === undefined ? strokeOffsetFunc ( lineItemData , lidx , d , i ) : strokeOffsetVal ) || 0 ;
272- if ( v1 . strokeOffset ) {
273- /* we use 11 bits to store the offset, and we want to store values
274- * from -1 to 1, so multiply our values by 1023, and use some bit
275- * manipulation to ensure that it is packed properly */
276- v1 . posStrokeOffset = Math . round ( 2048 + 1023 * Math . min ( 1 , Math . max ( - 1 , v1 . strokeOffset ) ) ) & 0x7FF ;
277- v1 . negStrokeOffset = Math . round ( 2048 - 1023 * Math . min ( 1 , Math . max ( - 1 , v1 . strokeOffset ) ) ) & 0x7FF ;
278- } else {
279- v1 . posStrokeOffset = v1 . negStrokeOffset = 0 ;
293+ if ( strokeOffsetVal !== 0 ) {
294+ v . strokeOffset = ( strokeOffsetVal === undefined ? strokeOffsetFunc ( lineItemData , lidx , d , i ) : strokeOffsetVal ) || 0 ;
295+ if ( v . strokeOffset ) {
296+ /* we use 11 bits to store the offset, and we want to store values
297+ * from -1 to 1, so multiply our values by 1023, and use some bit
298+ * manipulation to ensure that it is packed properly */
299+ v . posStrokeOffset = Math . round ( 2048 + 1023 * Math . min ( 1 , Math . max ( - 1 , v . strokeOffset ) ) ) & 0x7FF ;
300+ v . negStrokeOffset = Math . round ( 2048 - 1023 * Math . min ( 1 , Math . max ( - 1 , v . strokeOffset ) ) ) & 0x7FF ;
301+ } else {
302+ v . posStrokeOffset = v . negStrokeOffset = 0 ;
303+ }
280304 }
281- if ( ! closed [ i ] && ( ! j || j === lineItem . length - 1 ) ) {
282- v1 . flags = flagsLineCap [ lineCapVal === undefined ? lineCapFunc ( lineItemData , lidx , d , i ) : lineCapVal ] || flagsLineCap . butt ;
305+ if ( ! closedVal && ( ! j || j === lineItem . length - 1 ) ) {
306+ v . flags = lineCapVal === undefined ? flagsLineCap [ lineCapFunc ( lineItemData , lidx , d , i ) ] || flagsLineCap . butt : lineCapVal ;
283307 } else {
284- v1 . flags = flagsLineJoin [ lineJoinVal === undefined ? lineJoinFunc ( lineItemData , lidx , d , i ) : lineJoinVal ] || flagsLineJoin . miter ;
308+ v . flags = lineJoinVal === undefined ? flagsLineJoin [ lineJoinFunc ( lineItemData , lidx , d , i ) ] || flagsLineJoin . miter : lineJoinVal ;
285309 }
286310 }
287311
288312 if ( j ) {
289313 /* zero out the z position. This can be changed if we handle it in
290314 * the shader. */
291315 for ( k = 0 ; k < orderLen ; k += 1 , dest += 1 , dest3 += 3 ) {
292- v = vert [ order [ k ] [ 0 ] ] ;
293- v2 = vert [ 1 - order [ k ] [ 0 ] ] ;
316+ orderk0 = order [ k ] [ 0 ] ;
317+ v1 = vert [ orderk0 ] ;
318+ v2 = vert [ 1 - orderk0 ] ;
294319 if ( ! onlyStyle ) {
295- posBuf [ dest3 ] = position [ v . pos ] ;
296- posBuf [ dest3 + 1 ] = position [ v . pos + 1 ] ;
297- posBuf [ dest3 + 2 ] = 0 ; // position[v.pos + 2];
320+ posBuf [ dest3 ] = position [ v1 . pos ] ;
321+ posBuf [ dest3 + 1 ] = position [ v1 . pos + 1 ] ;
322+ posBuf [ dest3 + 2 ] = 0 ; // position[v1.pos + 2];
323+ prevkey = ! orderk0 ? 'prev' : 'next' ;
324+ nextkey = ! orderk0 ? 'next' : 'prev' ;
325+ prevBuf [ dest3 ] = position [ v1 [ prevkey ] ] ;
326+ prevBuf [ dest3 + 1 ] = position [ v1 [ prevkey ] + 1 ] ;
327+ prevBuf [ dest3 + 2 ] = 0 ; // position[v1[prevkey] + 2];
328+ nextBuf [ dest3 ] = position [ v1 [ nextkey ] ] ;
329+ nextBuf [ dest3 + 1 ] = position [ v1 [ nextkey ] + 1 ] ;
330+ nextBuf [ dest3 + 2 ] = 0 ; // position[v1[nextkey] + 2];
331+ farBuf [ dest3 ] = position [ v2 [ nextkey ] ] ;
332+ farBuf [ dest3 + 1 ] = position [ v2 [ nextkey ] + 1 ] ;
333+ farBuf [ dest3 + 2 ] = 0 ; // position[v2[nextkey] + 2];
298334 }
299- if ( ! order [ k ] [ 0 ] ) {
300- if ( ! onlyStyle ) {
301- prevBuf [ dest3 ] = position [ v . prev ] ;
302- prevBuf [ dest3 + 1 ] = position [ v . prev + 1 ] ;
303- prevBuf [ dest3 + 2 ] = 0 ; // position[v.prev + 2];
304- nextBuf [ dest3 ] = position [ v . next ] ;
305- nextBuf [ dest3 + 1 ] = position [ v . next + 1 ] ;
306- nextBuf [ dest3 + 2 ] = 0 ; // position[v.next + 2];
307- farBuf [ dest3 ] = position [ v2 . next ] ;
308- farBuf [ dest3 + 1 ] = position [ v2 . next + 1 ] ;
309- farBuf [ dest3 + 2 ] = 0 ; // position[v2.next + 2];
310- }
311- if ( updateFlags ) {
312- flagsBuf [ dest ] = ( flagsVertex [ order [ k ] [ 1 ] ] |
313- ( v . flags << flagsNearLineShift ) |
314- ( v2 . flags << flagsFarLineShift ) |
315- ( v . negStrokeOffset << flagsNearOffsetShift ) ) ;
316- }
317- } else {
318- if ( ! onlyStyle ) {
319- prevBuf [ dest3 ] = position [ v . next ] ;
320- prevBuf [ dest3 + 1 ] = position [ v . next + 1 ] ;
321- prevBuf [ dest3 + 2 ] = 0 ; // position[v.next + 2];
322- nextBuf [ dest3 ] = position [ v . prev ] ;
323- nextBuf [ dest3 + 1 ] = position [ v . prev + 1 ] ;
324- nextBuf [ dest3 + 2 ] = 0 ; // position[v.prev + 2];
325- farBuf [ dest3 ] = position [ v2 . prev ] ;
326- farBuf [ dest3 + 1 ] = position [ v2 . prev + 1 ] ;
327- farBuf [ dest3 + 2 ] = 0 ; // position[v2.prev + 2];
328- }
329- if ( updateFlags ) {
330- flagsBuf [ dest ] = ( flagsVertex [ order [ k ] [ 1 ] ] |
331- ( v . flags << flagsNearLineShift ) |
332- ( v2 . flags << flagsFarLineShift ) |
333- ( v . posStrokeOffset << flagsNearOffsetShift ) ) ;
334- }
335+ if ( updateFlags ) {
336+ offkey = ! orderk0 ? 'negStrokeOffset' : 'posStrokeOffset' ;
337+ flagsBuf [ dest ] = ( order [ k ] [ 3 ] +
338+ v1 . flags * flagsNearLineMult +
339+ v2 . flags * flagsFarLineMult +
340+ v1 [ offkey ] * flagsNearOffsetMult ) ;
335341 }
336- strokeWidthBuf [ dest ] = v . strokeWidth ;
337- strokeColorBuf [ dest3 ] = v . strokeColor . r ;
338- strokeColorBuf [ dest3 + 1 ] = v . strokeColor . g ;
339- strokeColorBuf [ dest3 + 2 ] = v . strokeColor . b ;
340- strokeOpacityBuf [ dest ] = v . strokeOpacity ;
342+ strokeWidthBuf [ dest ] = v1 . strokeWidth ;
343+ strokeColorBuf [ dest3 ] = v1 . strokeColor . r ;
344+ strokeColorBuf [ dest3 + 1 ] = v1 . strokeColor . g ;
345+ strokeColorBuf [ dest3 + 2 ] = v1 . strokeColor . b ;
346+ strokeOpacityBuf [ dest ] = v1 . strokeOpacity ;
341347 }
342348 }
343349 }
344350 }
345351
346- m_mapper . modified ( ) ;
347352 if ( ! onlyStyle ) {
353+ m_mapper . modified ( ) ;
348354 geom . boundsDirty ( true ) ;
349355 m_mapper . boundsDirtyTimestamp ( ) . modified ( ) ;
356+ } else {
357+ if ( updateFlags ) {
358+ m_mapper . updateSourceBuffer ( 'flags' ) ;
359+ }
360+ m_mapper . updateSourceBuffer ( 'strokeWidth' ) ;
361+ m_mapper . updateSourceBuffer ( 'strokeOpacity' ) ;
362+ m_mapper . updateSourceBuffer ( 'strokeColor' ) ;
350363 }
351364 }
352365
@@ -360,8 +373,8 @@ var webgl_lineFeature = function (arg) {
360373 */
361374 this . featureVertices = function ( ) {
362375 return [
363- [ 0 , 'corner' , - 1 ] , [ 0 , 'near' , 1 ] , [ 1 , 'far' , - 1 ] ,
364- [ 1 , 'corner' , 1 ] , [ 1 , 'near' , - 1 ] , [ 0 , 'far' , 1 ] ] ;
376+ [ 0 , 'corner' , - 1 , flagsVertex . corner ] , [ 0 , 'near' , 1 , flagsVertex . near ] , [ 1 , 'far' , - 1 , flagsVertex . far ] ,
377+ [ 1 , 'corner' , 1 , flagsVertex . corner ] , [ 1 , 'near' , - 1 , flagsVertex . near ] , [ 0 , 'far' , 1 , flagsVertex . far ] ] ;
365378 } ;
366379
367380 /**
@@ -462,6 +475,9 @@ var webgl_lineFeature = function (arg) {
462475 geom . addSource ( strkColorData ) ;
463476 geom . addSource ( strkOpacityData ) ;
464477 geom . addSource ( flagsData ) ;
478+ /* put a very small array here. We only use the length, and we'll override
479+ * that elsewhere. */
480+ triangles . setIndices ( new Uint16Array ( 1 ) ) ;
465481 geom . addPrimitive ( triangles ) ;
466482 /* We don't need vgl to compute bounds, so make the geo.computeBounds just
467483 * set them to 0. */
@@ -495,7 +511,7 @@ var webgl_lineFeature = function (arg) {
495511 * @returns {this }
496512 */
497513 this . _build = function ( ) {
498- createGLLines ( m_this . dataTime ( ) . timestamp ( ) < m_this . buildTime ( ) . timestamp ( ) && m_geometry ) ;
514+ createGLLines ( ! ! ( m_this . dataTime ( ) . timestamp ( ) < m_this . buildTime ( ) . timestamp ( ) && m_geometry ) ) ;
499515
500516 if ( ! m_this . renderer ( ) . contextRenderer ( ) . hasActor ( m_actor ) ) {
501517 m_this . renderer ( ) . contextRenderer ( ) . addActor ( m_actor ) ;
0 commit comments