@@ -20,6 +20,8 @@ class VectorGraphicsCodec {
2020 static const int _finishPathTag = 36 ;
2121 static const int _saveLayer = 37 ;
2222 static const int _restore = 38 ;
23+ static const int _linearGradientTag = 39 ;
24+ static const int _radialGradientTag = 40 ;
2325
2426 static const int _version = 1 ;
2527 static const int _magicNumber = 0x00882d62 ;
@@ -50,6 +52,12 @@ class VectorGraphicsCodec {
5052 while (buffer.hasRemaining) {
5153 final int type = buffer.getUint8 ();
5254 switch (type) {
55+ case _linearGradientTag:
56+ _readLinearGradient (buffer, listener);
57+ continue ;
58+ case _radialGradientTag:
59+ _readRadialGradient (buffer, listener);
60+ continue ;
5361 case _fillPaintTag:
5462 _readFillPaint (buffer, listener);
5563 continue ;
@@ -149,8 +157,9 @@ class VectorGraphicsCodec {
149157 int writeFill (
150158 VectorGraphicsBuffer buffer,
151159 int color,
152- int blendMode,
153- ) {
160+ int blendMode, [
161+ int ? shaderId,
162+ ]) {
154163 if (buffer._decodePhase.index > _CurrentSection .paints.index) {
155164 throw StateError ('Paints must be encoded together.' );
156165 }
@@ -160,9 +169,90 @@ class VectorGraphicsCodec {
160169 buffer._putUint32 (color);
161170 buffer._putUint8 (blendMode);
162171 buffer._putInt32 (paintId);
172+ buffer._putInt32 (shaderId ?? - 1 );
163173 return paintId;
164174 }
165175
176+ /// Write a linear gradient into the current buffer.
177+ int writeLinearGradient (
178+ VectorGraphicsBuffer buffer, {
179+ required double fromX,
180+ required double fromY,
181+ required double toX,
182+ required double toY,
183+ required Int32List colors,
184+ required Float32List ? offsets,
185+ required int tileMode,
186+ }) {
187+ if (buffer._decodePhase.index > _CurrentSection .shaders.index) {
188+ throw StateError ('Shaders must be encoded together.' );
189+ }
190+ buffer._decodePhase = _CurrentSection .shaders;
191+ final int shaderId = buffer._nextShaderId++ ;
192+ buffer._putUint8 (_linearGradientTag);
193+ buffer._putUint32 (shaderId);
194+ buffer._putFloat64 (fromX);
195+ buffer._putFloat64 (fromY);
196+ buffer._putFloat64 (toX);
197+ buffer._putFloat64 (toY);
198+ buffer._putInt32 (colors.length);
199+ buffer._putInt32List (colors);
200+ if (offsets == null ) {
201+ buffer._putInt32 (0 );
202+ } else {
203+ buffer._putInt32 (offsets.length);
204+ buffer._putFloat32List (offsets);
205+ }
206+ buffer._putUint8 (tileMode);
207+ return shaderId;
208+ }
209+
210+ /// Write a radial gradient into the current buffer.
211+ ///
212+ /// [focalX] and [focalY] must be either both `null` or both `non-null` .
213+ int writeRadialGradient (
214+ VectorGraphicsBuffer buffer, {
215+ required double centerX,
216+ required double centerY,
217+ required double radius,
218+ required double ? focalX,
219+ required double ? focalY,
220+ required Int32List colors,
221+ required Float32List ? offsets,
222+ required int tileMode,
223+ }) {
224+ assert ((focalX == null && focalY == null ) ||
225+ (focalX != null && focalY != null ));
226+ if (buffer._decodePhase.index > _CurrentSection .shaders.index) {
227+ throw StateError ('Shaders must be encoded together.' );
228+ }
229+ buffer._decodePhase = _CurrentSection .shaders;
230+ final int shaderId = buffer._nextShaderId++ ;
231+ buffer._putUint8 (_radialGradientTag);
232+ buffer._putInt32 (shaderId);
233+ buffer._putFloat64 (centerX);
234+ buffer._putFloat64 (centerY);
235+ buffer._putFloat64 (radius);
236+
237+ if (focalX != null ) {
238+ buffer._putUint8 (1 );
239+ buffer._putFloat64 (focalX);
240+ buffer._putFloat64 (focalY! );
241+ } else {
242+ buffer._putUint8 (0 );
243+ }
244+ buffer._putInt32 (colors.length);
245+ buffer._putInt32List (colors);
246+ if (offsets != null ) {
247+ buffer._putInt32 (offsets.length);
248+ buffer._putFloat32List (offsets);
249+ } else {
250+ buffer._putInt32 (0 );
251+ }
252+ buffer._putUint8 (tileMode);
253+ return shaderId;
254+ }
255+
166256 /// Encode a paint object in the current buffer, returning the identifier
167257 /// assigned to it.
168258 ///
@@ -197,11 +287,71 @@ class VectorGraphicsCodec {
197287 return paintId;
198288 }
199289
290+ void _readLinearGradient (
291+ _ReadBuffer buffer,
292+ VectorGraphicsCodecListener ? listener,
293+ ) {
294+ final int id = buffer.getInt32 ();
295+ final double fromX = buffer.getFloat64 ();
296+ final double fromY = buffer.getFloat64 ();
297+ final double toX = buffer.getFloat64 ();
298+ final double toY = buffer.getFloat64 ();
299+ final int colorLength = buffer.getInt32 ();
300+ final Int32List colors = buffer.getInt32List (colorLength);
301+ final int offsetLength = buffer.getInt32 ();
302+ final Float32List offsets = buffer.getFloat32List (offsetLength);
303+ final int tileMode = buffer.getUint8 ();
304+ listener? .onLinearGradient (
305+ fromX,
306+ fromY,
307+ toX,
308+ toY,
309+ colors,
310+ offsets,
311+ tileMode,
312+ id,
313+ );
314+ }
315+
316+ void _readRadialGradient (
317+ _ReadBuffer buffer,
318+ VectorGraphicsCodecListener ? listener,
319+ ) {
320+ final int id = buffer.getInt32 ();
321+ final double centerX = buffer.getFloat64 ();
322+ final double centerY = buffer.getFloat64 ();
323+ final double radius = buffer.getFloat64 ();
324+ final int hasFocal = buffer.getUint8 ();
325+ double ? focalX;
326+ double ? focalY;
327+ if (hasFocal == 1 ) {
328+ focalX = buffer.getFloat64 ();
329+ focalY = buffer.getFloat64 ();
330+ }
331+ final int colorsLength = buffer.getInt32 ();
332+ final Int32List colors = buffer.getInt32List (colorsLength);
333+ final int offsetsLength = buffer.getInt32 ();
334+ final Float32List offsets = buffer.getFloat32List (offsetsLength);
335+ final int tileMode = buffer.getUint8 ();
336+ listener? .onRadialGradient (
337+ centerX,
338+ centerY,
339+ radius,
340+ focalX,
341+ focalY,
342+ colors,
343+ offsets,
344+ tileMode,
345+ id,
346+ );
347+ }
348+
200349 void _readFillPaint (
201350 _ReadBuffer buffer, VectorGraphicsCodecListener ? listener) {
202351 final int color = buffer.getUint32 ();
203352 final int blendMode = buffer.getUint8 ();
204353 final int id = buffer.getInt32 ();
354+ final int shaderId = buffer.getInt32 ();
205355
206356 listener? .onPaintObject (
207357 color: color,
@@ -212,6 +362,7 @@ class VectorGraphicsCodec {
212362 strokeWidth: null ,
213363 paintStyle: 0 , // Fill
214364 id: id,
365+ shaderId: shaderId == - 1 ? null : shaderId,
215366 );
216367 }
217368
@@ -234,6 +385,7 @@ class VectorGraphicsCodec {
234385 strokeWidth: strokeWidth,
235386 paintStyle: 1 , // Stroke
236387 id: id,
388+ shaderId: null ,
237389 );
238390 }
239391
@@ -405,6 +557,7 @@ abstract class VectorGraphicsCodecListener {
405557 required double ? strokeWidth,
406558 required int paintStyle,
407559 required int id,
560+ required int ? shaderId,
408561 });
409562
410563 /// A path object is being created, with the given [id] and [fillType] .
@@ -453,9 +606,37 @@ abstract class VectorGraphicsCodecListener {
453606
454607 /// Restore the save stack.
455608 void onRestoreLayer ();
609+
610+ /// A radial gradient shader has been parsed.
611+ ///
612+ /// [focalX] and [focalY] are either both `null` or `non-null` .
613+ void onRadialGradient (
614+ double centerX,
615+ double centerY,
616+ double radius,
617+ double ? focalX,
618+ double ? focalY,
619+ Int32List colors,
620+ Float32List ? offsets,
621+ int tileMode,
622+ int id,
623+ );
624+
625+ /// A linear gradient shader has been parsed.
626+ void onLinearGradient (
627+ double fromX,
628+ double fromY,
629+ double toX,
630+ double toY,
631+ Int32List colors,
632+ Float32List ? offsets,
633+ int tileMode,
634+ int id,
635+ );
456636}
457637
458638enum _CurrentSection {
639+ shaders,
459640 paints,
460641 paths,
461642 commands,
@@ -492,6 +673,9 @@ class VectorGraphicsBuffer {
492673 /// The next path id to be used.
493674 int _nextPathId = 0 ;
494675
676+ /// The next shader id to be used.
677+ int _nextShaderId = 0 ;
678+
495679 /// The current id of the path being built, or `-1` if there is no
496680 /// active path.
497681 int _currentPathId = - 1 ;
@@ -500,7 +684,7 @@ class VectorGraphicsBuffer {
500684 ///
501685 /// Objects must be written in the correct order, the same as the
502686 /// enum order.
503- _CurrentSection _decodePhase = _CurrentSection .paints ;
687+ _CurrentSection _decodePhase = _CurrentSection .shaders ;
504688
505689 /// Write a Uint8 into the buffer.
506690 void _putUint8 (int byte) {
@@ -522,6 +706,14 @@ class VectorGraphicsBuffer {
522706 _buffer.addAll (_eightBytesAsList.take (4 ));
523707 }
524708
709+ /// Write an Int32List into the buffer.
710+ void _putInt32List (Int32List list) {
711+ assert (! _isDone);
712+ _alignTo (4 );
713+ _buffer
714+ .addAll (list.buffer.asUint8List (list.offsetInBytes, 4 * list.length));
715+ }
716+
525717 /// Write an Float64 into the buffer.
526718 void _putFloat64 (double value, {Endian ? endian}) {
527719 assert (! _isDone);
0 commit comments