• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
4 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
5 import static android.os.Build.VERSION_CODES.KITKAT;
6 import static android.os.Build.VERSION_CODES.KITKAT_WATCH;
7 import static android.os.Build.VERSION_CODES.L;
8 import static android.os.Build.VERSION_CODES.LOLLIPOP;
9 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
10 import static android.os.Build.VERSION_CODES.M;
11 import static android.os.Build.VERSION_CODES.N;
12 import static android.os.Build.VERSION_CODES.N_MR1;
13 import static android.os.Build.VERSION_CODES.O;
14 import static android.os.Build.VERSION_CODES.O_MR1;
15 import static android.os.Build.VERSION_CODES.P;
16 import static android.os.Build.VERSION_CODES.Q;
17 import static org.robolectric.annotation.TextLayoutMode.Mode.REALISTIC;
18 
19 import android.graphics.ColorFilter;
20 import android.graphics.Paint;
21 import android.graphics.Paint.FontMetricsInt;
22 import android.graphics.PathEffect;
23 import android.graphics.Shader;
24 import android.graphics.Typeface;
25 import org.robolectric.annotation.Implementation;
26 import org.robolectric.annotation.Implements;
27 import org.robolectric.annotation.RealObject;
28 import org.robolectric.annotation.TextLayoutMode;
29 import org.robolectric.config.ConfigurationRegistry;
30 import org.robolectric.shadow.api.Shadow;
31 import org.robolectric.util.ReflectionHelpers.ClassParameter;
32 
33 @SuppressWarnings({"UnusedDeclaration"})
34 @Implements(value = Paint.class, looseSignatures = true)
35 public class ShadowPaint {
36 
37   private int color;
38   private Paint.Style style;
39   private Paint.Cap cap;
40   private Paint.Join join;
41   private float width;
42   private float shadowRadius;
43   private float shadowDx;
44   private float shadowDy;
45   private int shadowColor;
46   private Shader shader;
47   private int alpha;
48   private ColorFilter filter;
49   private boolean antiAlias;
50   private boolean dither;
51   private int flags;
52   private PathEffect pathEffect;
53   private float letterSpacing;
54   private float textScaleX = 1f;
55   private float textSkewX;
56   private float wordSpacing;
57 
58   @RealObject Paint paint;
59   private Typeface typeface;
60   private float textSize;
61   private Paint.Align textAlign = Paint.Align.LEFT;
62 
63   @Implementation
__constructor__(Paint otherPaint)64   protected void __constructor__(Paint otherPaint) {
65     ShadowPaint otherShadowPaint = Shadow.extract(otherPaint);
66     this.color = otherShadowPaint.color;
67     this.style = otherShadowPaint.style;
68     this.cap = otherShadowPaint.cap;
69     this.join = otherShadowPaint.join;
70     this.width = otherShadowPaint.width;
71     this.shadowRadius = otherShadowPaint.shadowRadius;
72     this.shadowDx = otherShadowPaint.shadowDx;
73     this.shadowDy = otherShadowPaint.shadowDy;
74     this.shadowColor = otherShadowPaint.shadowColor;
75     this.shader = otherShadowPaint.shader;
76     this.alpha = otherShadowPaint.alpha;
77     this.filter = otherShadowPaint.filter;
78     this.antiAlias = otherShadowPaint.antiAlias;
79     this.dither = otherShadowPaint.dither;
80     this.flags = otherShadowPaint.flags;
81     this.pathEffect = otherShadowPaint.pathEffect;
82     this.letterSpacing = otherShadowPaint.letterSpacing;
83     this.textScaleX = otherShadowPaint.textScaleX;
84     this.textSkewX = otherShadowPaint.textSkewX;
85     this.wordSpacing = otherShadowPaint.wordSpacing;
86 
87     Shadow.invokeConstructor(Paint.class, paint, ClassParameter.from(Paint.class, otherPaint));
88   }
89 
90   @Implementation(minSdk = N)
nInit()91   protected static long nInit() {
92     return 1;
93   }
94 
95   @Implementation
getFlags()96   protected int getFlags() {
97     return flags;
98   }
99 
100   @Implementation
setFlags(int flags)101   protected void setFlags(int flags) {
102     this.flags = flags;
103   }
104 
105   @Implementation
setUnderlineText(boolean underlineText)106   protected void setUnderlineText(boolean underlineText) {
107     if (underlineText) {
108       setFlags(flags | Paint.UNDERLINE_TEXT_FLAG);
109     } else {
110       setFlags(flags & ~Paint.UNDERLINE_TEXT_FLAG);
111     }
112   }
113 
114   @Implementation
setStrikeThruText(boolean strikeThruText)115   protected void setStrikeThruText(boolean strikeThruText) {
116     if (strikeThruText) {
117       setFlags(flags | Paint.STRIKE_THRU_TEXT_FLAG);
118     } else {
119       setFlags(flags & ~Paint.STRIKE_THRU_TEXT_FLAG);
120     }
121   }
122 
123   @Implementation
setShader(Shader shader)124   protected Shader setShader(Shader shader) {
125     this.shader = shader;
126     return shader;
127   }
128 
129   @Implementation
getAlpha()130   protected int getAlpha() {
131     return alpha;
132   }
133 
134   @Implementation
setAlpha(int alpha)135   protected void setAlpha(int alpha) {
136     this.alpha = alpha;
137   }
138 
139   @Implementation
getShader()140   protected Shader getShader() {
141     return shader;
142   }
143 
144   @Implementation
setColor(int color)145   protected void setColor(int color) {
146     this.color = color;
147   }
148 
149   @Implementation
getColor()150   protected int getColor() {
151     return color;
152   }
153 
154   @Implementation
setStyle(Paint.Style style)155   protected void setStyle(Paint.Style style) {
156     this.style = style;
157   }
158 
159   @Implementation
getStyle()160   protected Paint.Style getStyle() {
161     return style;
162   }
163 
164   @Implementation
setStrokeCap(Paint.Cap cap)165   protected void setStrokeCap(Paint.Cap cap) {
166     this.cap = cap;
167   }
168 
169   @Implementation
getStrokeCap()170   protected Paint.Cap getStrokeCap() {
171     return cap;
172   }
173 
174   @Implementation
setStrokeJoin(Paint.Join join)175   protected void setStrokeJoin(Paint.Join join) {
176     this.join = join;
177   }
178 
179   @Implementation
getStrokeJoin()180   protected Paint.Join getStrokeJoin() {
181     return join;
182   }
183 
184   @Implementation
setStrokeWidth(float width)185   protected void setStrokeWidth(float width) {
186     this.width = width;
187   }
188 
189   @Implementation
getStrokeWidth()190   protected float getStrokeWidth() {
191     return width;
192   }
193 
194   @Implementation
setShadowLayer(float radius, float dx, float dy, int color)195   protected void setShadowLayer(float radius, float dx, float dy, int color) {
196     shadowRadius = radius;
197     shadowDx = dx;
198     shadowDy = dy;
199     shadowColor = color;
200   }
201 
202   @Implementation
getTypeface()203   protected Typeface getTypeface() {
204     return typeface;
205   }
206 
207   @Implementation
setTypeface(Typeface typeface)208   protected Typeface setTypeface(Typeface typeface) {
209     this.typeface = typeface;
210     return typeface;
211   }
212 
213   @Implementation
getTextSize()214   protected float getTextSize() {
215     return textSize;
216   }
217 
218   @Implementation
setTextSize(float textSize)219   protected void setTextSize(float textSize) {
220     this.textSize = textSize;
221   }
222 
223   @Implementation
getTextScaleX()224   protected float getTextScaleX() {
225     return textScaleX;
226   }
227 
228   @Implementation
setTextScaleX(float scaleX)229   protected void setTextScaleX(float scaleX) {
230     this.textScaleX = scaleX;
231   }
232 
233   @Implementation
getTextSkewX()234   protected float getTextSkewX() {
235     return textSkewX;
236   }
237 
238   @Implementation
setTextSkewX(float skewX)239   protected void setTextSkewX(float skewX) {
240     this.textSkewX = skewX;
241   }
242 
243   @Implementation(minSdk = L)
getLetterSpacing()244   protected float getLetterSpacing() {
245     return letterSpacing;
246   }
247 
248   @Implementation(minSdk = L)
setLetterSpacing(float letterSpacing)249   protected void setLetterSpacing(float letterSpacing) {
250     this.letterSpacing = letterSpacing;
251   }
252 
253   @Implementation(minSdk = Q)
getWordSpacing()254   protected float getWordSpacing() {
255     return wordSpacing;
256   }
257 
258   @Implementation(minSdk = Q)
setWordSpacing(float wordSpacing)259   protected void setWordSpacing(float wordSpacing) {
260     this.wordSpacing = wordSpacing;
261   }
262 
263   @Implementation
setTextAlign(Paint.Align align)264   protected void setTextAlign(Paint.Align align) {
265     textAlign = align;
266   }
267 
268   @Implementation
getTextAlign()269   protected Paint.Align getTextAlign() {
270     return textAlign;
271   }
272 
273   /**
274    * @return shadow radius (Paint related shadow, not Robolectric Shadow)
275    */
getShadowRadius()276   public float getShadowRadius() {
277     return shadowRadius;
278   }
279 
280   /**
281    * @return shadow Dx (Paint related shadow, not Robolectric Shadow)
282    */
getShadowDx()283   public float getShadowDx() {
284     return shadowDx;
285   }
286 
287   /**
288    * @return shadow Dx (Paint related shadow, not Robolectric Shadow)
289    */
getShadowDy()290   public float getShadowDy() {
291     return shadowDy;
292   }
293 
294   /**
295    * @return shadow color (Paint related shadow, not Robolectric Shadow)
296    */
getShadowColor()297   public int getShadowColor() {
298     return shadowColor;
299   }
300 
getCap()301   public Paint.Cap getCap() {
302     return cap;
303   }
304 
getJoin()305   public Paint.Join getJoin() {
306     return join;
307   }
308 
getWidth()309   public float getWidth() {
310     return width;
311   }
312 
313   @Implementation
getColorFilter()314   protected ColorFilter getColorFilter() {
315     return filter;
316   }
317 
318   @Implementation
setColorFilter(ColorFilter filter)319   protected ColorFilter setColorFilter(ColorFilter filter) {
320     this.filter = filter;
321     return filter;
322   }
323 
324   @Implementation
setAntiAlias(boolean antiAlias)325   protected void setAntiAlias(boolean antiAlias) {
326     this.flags = (flags & ~Paint.ANTI_ALIAS_FLAG) | (antiAlias ? Paint.ANTI_ALIAS_FLAG : 0);
327   }
328 
329   @Implementation
setDither(boolean dither)330   protected void setDither(boolean dither) {
331     this.dither = dither;
332   }
333 
334   @Implementation
isDither()335   protected final boolean isDither() {
336     return dither;
337   }
338 
339   @Implementation
isAntiAlias()340   protected final boolean isAntiAlias() {
341     return (flags & Paint.ANTI_ALIAS_FLAG) == Paint.ANTI_ALIAS_FLAG;
342   }
343 
344   @Implementation
isFilterBitmap()345   protected final boolean isFilterBitmap() {
346     return (flags & Paint.FILTER_BITMAP_FLAG) == Paint.FILTER_BITMAP_FLAG;
347   }
348 
349   @Implementation
setFilterBitmap(boolean filterBitmap)350   protected final void setFilterBitmap(boolean filterBitmap) {
351     this.flags =
352         (flags & ~Paint.FILTER_BITMAP_FLAG) | (filterBitmap ? Paint.FILTER_BITMAP_FLAG : 0);
353   }
354 
355   @Implementation
getPathEffect()356   protected PathEffect getPathEffect() {
357     return pathEffect;
358   }
359 
360   @Implementation
setPathEffect(PathEffect effect)361   protected PathEffect setPathEffect(PathEffect effect) {
362     this.pathEffect = effect;
363     return effect;
364   }
365 
366   @Implementation
measureText(String text)367   protected float measureText(String text) {
368     return applyTextScaleX(text.length());
369   }
370 
371   @Implementation
measureText(CharSequence text, int start, int end)372   protected float measureText(CharSequence text, int start, int end) {
373     return applyTextScaleX(end - start);
374   }
375 
376   @Implementation
measureText(String text, int start, int end)377   protected float measureText(String text, int start, int end) {
378     return applyTextScaleX(end - start);
379   }
380 
381   @Implementation
measureText(char[] text, int index, int count)382   protected float measureText(char[] text, int index, int count) {
383     return applyTextScaleX(count);
384   }
385 
applyTextScaleX(float textWidth)386   private float applyTextScaleX(float textWidth) {
387     return Math.max(0f, textScaleX) * textWidth;
388   }
389 
390   @Implementation(maxSdk = JELLY_BEAN_MR1)
native_breakText( char[] text, int index, int count, float maxWidth, float[] measuredWidth)391   protected int native_breakText(
392       char[] text, int index, int count, float maxWidth, float[] measuredWidth) {
393     return breakText(text, maxWidth, measuredWidth);
394   }
395 
396   @Implementation(minSdk = JELLY_BEAN_MR2, maxSdk = KITKAT_WATCH)
native_breakText( char[] text, int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth)397   protected int native_breakText(
398       char[] text, int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) {
399     return breakText(text, maxWidth, measuredWidth);
400   }
401 
402   @Implementation(minSdk = LOLLIPOP, maxSdk = M)
native_breakText( long native_object, long native_typeface, char[] text, int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth)403   protected static int native_breakText(
404       long native_object,
405       long native_typeface,
406       char[] text,
407       int index,
408       int count,
409       float maxWidth,
410       int bidiFlags,
411       float[] measuredWidth) {
412     return breakText(text, maxWidth, measuredWidth);
413   }
414 
415   @Implementation(minSdk = N, maxSdk = O_MR1)
nBreakText( long nObject, long nTypeface, char[] text, int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth)416   protected static int nBreakText(
417       long nObject,
418       long nTypeface,
419       char[] text,
420       int index,
421       int count,
422       float maxWidth,
423       int bidiFlags,
424       float[] measuredWidth) {
425     return breakText(text, maxWidth, measuredWidth);
426   }
427 
428   @Implementation(minSdk = P)
nBreakText( long nObject, char[] text, int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth)429   protected static int nBreakText(
430       long nObject,
431       char[] text,
432       int index,
433       int count,
434       float maxWidth,
435       int bidiFlags,
436       float[] measuredWidth) {
437     return breakText(text, maxWidth, measuredWidth);
438   }
439 
breakText(char[] text, float maxWidth, float[] measuredWidth)440   private static int breakText(char[] text, float maxWidth, float[] measuredWidth) {
441     if (measuredWidth != null) {
442       measuredWidth[0] = maxWidth;
443     }
444     return text.length;
445   }
446 
447   @Implementation(maxSdk = JELLY_BEAN_MR1)
native_breakText( String text, boolean measureForwards, float maxWidth, float[] measuredWidth)448   protected int native_breakText(
449       String text, boolean measureForwards, float maxWidth, float[] measuredWidth) {
450     return breakText(text, maxWidth, measuredWidth);
451   }
452 
453   @Implementation(minSdk = JELLY_BEAN_MR2, maxSdk = KITKAT_WATCH)
native_breakText( String text, boolean measureForwards, float maxWidth, int bidiFlags, float[] measuredWidth)454   protected int native_breakText(
455       String text, boolean measureForwards, float maxWidth, int bidiFlags, float[] measuredWidth) {
456     return breakText(text, maxWidth, measuredWidth);
457   }
458 
459   @Implementation(minSdk = LOLLIPOP, maxSdk = M)
native_breakText( long native_object, long native_typeface, String text, boolean measureForwards, float maxWidth, int bidiFlags, float[] measuredWidth)460   protected static int native_breakText(
461       long native_object,
462       long native_typeface,
463       String text,
464       boolean measureForwards,
465       float maxWidth,
466       int bidiFlags,
467       float[] measuredWidth) {
468     return breakText(text, maxWidth, measuredWidth);
469   }
470 
471   @Implementation(minSdk = N, maxSdk = O_MR1)
nBreakText( long nObject, long nTypeface, String text, boolean measureForwards, float maxWidth, int bidiFlags, float[] measuredWidth)472   protected static int nBreakText(
473       long nObject,
474       long nTypeface,
475       String text,
476       boolean measureForwards,
477       float maxWidth,
478       int bidiFlags,
479       float[] measuredWidth) {
480     return breakText(text, maxWidth, measuredWidth);
481   }
482 
483   @Implementation(minSdk = P)
nBreakText( long nObject, String text, boolean measureForwards, float maxWidth, int bidiFlags, float[] measuredWidth)484   protected static int nBreakText(
485       long nObject,
486       String text,
487       boolean measureForwards,
488       float maxWidth,
489       int bidiFlags,
490       float[] measuredWidth) {
491     return breakText(text, maxWidth, measuredWidth);
492   }
493 
breakText(String text, float maxWidth, float[] measuredWidth)494   private static int breakText(String text, float maxWidth, float[] measuredWidth) {
495     if (measuredWidth != null) {
496       measuredWidth[0] = maxWidth;
497     }
498     return text.length();
499   }
500 
501   @Implementation(minSdk = P)
nGetFontMetricsInt(long paintPtr, FontMetricsInt fmi)502   protected static int nGetFontMetricsInt(long paintPtr, FontMetricsInt fmi) {
503     if (ConfigurationRegistry.get(TextLayoutMode.Mode.class) == REALISTIC) {
504       // TODO: hack, just set values to those we see on emulator
505       int descent = 7;
506       int ascent = -28;
507       int leading = 0;
508 
509       if (fmi != null) {
510         fmi.top = -32;
511         fmi.ascent = ascent;
512         fmi.descent = descent;
513         fmi.bottom = 9;
514         fmi.leading = leading;
515       }
516       return descent - ascent + leading;
517     }
518     return 0;
519   }
520 
521   @Implementation(minSdk = O, maxSdk = O_MR1)
nGetFontMetricsInt( long nativePaint, long nativeTypeface, FontMetricsInt fmi)522   protected static int nGetFontMetricsInt(
523       long nativePaint, long nativeTypeface, FontMetricsInt fmi) {
524     return nGetFontMetricsInt(nativePaint, fmi);
525   }
526 
527   @Implementation(minSdk = N, maxSdk = N_MR1)
nGetFontMetricsInt(Object nativePaint, Object nativeTypeface, Object fmi)528   protected int nGetFontMetricsInt(Object nativePaint, Object nativeTypeface, Object fmi) {
529     return nGetFontMetricsInt((long) nativePaint, (FontMetricsInt) fmi);
530   }
531 
532   @Implementation(maxSdk = M)
getFontMetricsInt(FontMetricsInt fmi)533   protected int getFontMetricsInt(FontMetricsInt fmi) {
534     return nGetFontMetricsInt(0, fmi);
535   }
536 
537   @Implementation(minSdk = P)
nGetRunAdvance( long paintPtr, char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, int offset)538   protected static float nGetRunAdvance(
539       long paintPtr,
540       char[] text,
541       int start,
542       int end,
543       int contextStart,
544       int contextEnd,
545       boolean isRtl,
546       int offset) {
547     if (ConfigurationRegistry.get(TextLayoutMode.Mode.class) == REALISTIC) {
548       // be consistent with measureText for measurements, and measure 1 pixel per char
549       return end - start;
550     }
551     return 0f;
552   }
553 
554   @Implementation(minSdk = N, maxSdk = O_MR1)
nGetRunAdvance( long paintPtr, long typefacePtr, char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, int offset)555   protected static float nGetRunAdvance(
556       long paintPtr,
557       long typefacePtr,
558       char[] text,
559       int start,
560       int end,
561       int contextStart,
562       int contextEnd,
563       boolean isRtl,
564       int offset) {
565     return nGetRunAdvance(paintPtr, text, start, end, contextStart, contextEnd, isRtl, offset);
566   }
567 
568   @Implementation(minSdk = M, maxSdk = M)
native_getRunAdvance( long nativeObject, long nativeTypeface, char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl, int offset)569   protected static float native_getRunAdvance(
570       long nativeObject,
571       long nativeTypeface,
572       char[] text,
573       int start,
574       int end,
575       int contextStart,
576       int contextEnd,
577       boolean isRtl,
578       int offset) {
579     return nGetRunAdvance(0, text, start, end, contextStart, contextEnd, isRtl, offset);
580   }
581 
582   @Implementation(minSdk = KITKAT_WATCH, maxSdk = LOLLIPOP_MR1)
native_getTextRunAdvances( long nativeObject, long nativeTypeface, char[] text, int index, int count, int contextIndex, int contextCount, boolean isRtl, float[] advances, int advancesIndex)583   protected static float native_getTextRunAdvances(
584       long nativeObject,
585       long nativeTypeface,
586       char[] text,
587       int index,
588       int count,
589       int contextIndex,
590       int contextCount,
591       boolean isRtl,
592       float[] advances,
593       int advancesIndex) {
594     return nGetRunAdvance(
595         0, text, index, index + count, contextIndex, contextIndex + contextCount, isRtl, index);
596   }
597 
598   @Implementation(minSdk = KITKAT_WATCH, maxSdk = LOLLIPOP_MR1)
native_getTextRunAdvances( long nativeObject, long nativeTypeface, String text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float[] advances, int advancesIndex)599   protected static float native_getTextRunAdvances(
600       long nativeObject,
601       long nativeTypeface,
602       String text,
603       int start,
604       int end,
605       int contextStart,
606       int contextEnd,
607       boolean isRtl,
608       float[] advances,
609       int advancesIndex) {
610     return nGetRunAdvance(0, text.toCharArray(), start, end, contextStart, contextEnd, isRtl, 0);
611   }
612 
613   @Implementation(minSdk = JELLY_BEAN_MR2, maxSdk = KITKAT)
native_getTextRunAdvances( int nativeObject, char[] text, int index, int count, int contextIndex, int contextCount, int flags, float[] advances, int advancesIndex)614   protected static float native_getTextRunAdvances(
615       int nativeObject,
616       char[] text,
617       int index,
618       int count,
619       int contextIndex,
620       int contextCount,
621       int flags,
622       float[] advances,
623       int advancesIndex) {
624     return nGetRunAdvance(
625         0, text, index, index + count, contextIndex, contextIndex + contextCount, false, index);
626   }
627 
628   @Implementation(minSdk = JELLY_BEAN_MR2, maxSdk = KITKAT)
native_getTextRunAdvances( int nativeObject, String text, int start, int end, int contextStart, int contextEnd, int flags, float[] advances, int advancesIndex)629   protected static float native_getTextRunAdvances(
630       int nativeObject,
631       String text,
632       int start,
633       int end,
634       int contextStart,
635       int contextEnd,
636       int flags,
637       float[] advances,
638       int advancesIndex) {
639     return nGetRunAdvance(0, text.toCharArray(), start, end, contextStart, contextEnd, false, 0);
640   }
641 
642   @Implementation(maxSdk = JELLY_BEAN_MR1)
native_getTextRunAdvances( int nativeObject, char[] text, int index, int count, int contextIndex, int contextCount, int flags, float[] advances, int advancesIndex, int reserved)643   protected static float native_getTextRunAdvances(
644       int nativeObject,
645       char[] text,
646       int index,
647       int count,
648       int contextIndex,
649       int contextCount,
650       int flags,
651       float[] advances,
652       int advancesIndex,
653       int reserved) {
654     return nGetRunAdvance(
655         0, text, index, index + count, contextIndex, contextIndex + contextCount, false, index);
656   }
657 
658   @Implementation(maxSdk = JELLY_BEAN_MR1)
native_getTextRunAdvances( int nativeObject, String text, int start, int end, int contextStart, int contextEnd, int flags, float[] advances, int advancesIndex, int reserved)659   protected static float native_getTextRunAdvances(
660       int nativeObject,
661       String text,
662       int start,
663       int end,
664       int contextStart,
665       int contextEnd,
666       int flags,
667       float[] advances,
668       int advancesIndex,
669       int reserved) {
670     return nGetRunAdvance(0, text.toCharArray(), start, end, contextStart, contextEnd, false, 0);
671   }
672 }
673