Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.graphics;
     18 
     19 import com.android.ide.common.rendering.api.LayoutLog;
     20 import com.android.layoutlib.bridge.Bridge;
     21 import com.android.layoutlib.bridge.impl.DelegateManager;
     22 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
     23 
     24 import android.annotation.NonNull;
     25 import android.annotation.Nullable;
     26 import android.graphics.FontFamily_Delegate.FontVariant;
     27 import android.graphics.Paint.FontMetrics;
     28 import android.graphics.Paint.FontMetricsInt;
     29 import android.text.TextUtils;
     30 
     31 import java.awt.BasicStroke;
     32 import java.awt.Font;
     33 import java.awt.Shape;
     34 import java.awt.Stroke;
     35 import java.awt.Toolkit;
     36 import java.awt.geom.AffineTransform;
     37 import java.util.ArrayList;
     38 import java.util.Collections;
     39 import java.util.List;
     40 import java.util.Locale;
     41 
     42 import libcore.util.NativeAllocationRegistry_Delegate;
     43 
     44 /**
     45  * Delegate implementing the native methods of android.graphics.Paint
     46  *
     47  * Through the layoutlib_create tool, the original native methods of Paint have been replaced
     48  * by calls to methods of the same name in this delegate class.
     49  *
     50  * This class behaves like the original native implementation, but in Java, keeping previously
     51  * native data into its own objects and mapping them to int that are sent back and forth between
     52  * it and the original Paint class.
     53  *
     54  * @see DelegateManager
     55  *
     56  */
     57 public class Paint_Delegate {
     58 
     59     /**
     60      * Class associating a {@link Font} and its {@link java.awt.FontMetrics}.
     61      */
     62     /*package*/ static final class FontInfo {
     63         Font mFont;
     64         java.awt.FontMetrics mMetrics;
     65     }
     66 
     67     // ---- delegate manager ----
     68     private static final DelegateManager<Paint_Delegate> sManager =
     69             new DelegateManager<Paint_Delegate>(Paint_Delegate.class);
     70     private static long sFinalizer = -1;
     71 
     72     // ---- delegate helper data ----
     73 
     74     // This list can contain null elements.
     75     private List<FontInfo> mFonts;
     76 
     77     // ---- delegate data ----
     78     private int mFlags;
     79     private int mColor;
     80     private int mStyle;
     81     private int mCap;
     82     private int mJoin;
     83     private int mTextAlign;
     84     private Typeface_Delegate mTypeface;
     85     private float mStrokeWidth;
     86     private float mStrokeMiter;
     87     private float mTextSize;
     88     private float mTextScaleX;
     89     private float mTextSkewX;
     90     private int mHintingMode = Paint.HINTING_ON;
     91     private int mHyphenEdit;
     92     private float mLetterSpacing;  // not used in actual text rendering.
     93     private float mWordSpacing;  // not used in actual text rendering.
     94     // Variant of the font. A paint's variant can only be compact or elegant.
     95     private FontVariant mFontVariant = FontVariant.COMPACT;
     96 
     97     private int mPorterDuffMode = Xfermode.DEFAULT;
     98     private ColorFilter_Delegate mColorFilter;
     99     private Shader_Delegate mShader;
    100     private PathEffect_Delegate mPathEffect;
    101     private MaskFilter_Delegate mMaskFilter;
    102 
    103     private Locale mLocale = Locale.getDefault();
    104 
    105     // Used only to assert invariants.
    106     public long mNativeTypeface;
    107 
    108     // ---- Public Helper methods ----
    109 
    110     @Nullable
    111     public static Paint_Delegate getDelegate(long native_paint) {
    112         return sManager.getDelegate(native_paint);
    113     }
    114 
    115     /**
    116      * Returns the list of {@link Font} objects.
    117      */
    118     public List<FontInfo> getFonts() {
    119         return mFonts;
    120     }
    121 
    122     public boolean isAntiAliased() {
    123         return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0;
    124     }
    125 
    126     public boolean isFilterBitmap() {
    127         return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0;
    128     }
    129 
    130     public int getStyle() {
    131         return mStyle;
    132     }
    133 
    134     public int getColor() {
    135         return mColor;
    136     }
    137 
    138     public int getAlpha() {
    139         return mColor >>> 24;
    140     }
    141 
    142     public void setAlpha(int alpha) {
    143         mColor = (alpha << 24) | (mColor & 0x00FFFFFF);
    144     }
    145 
    146     public int getTextAlign() {
    147         return mTextAlign;
    148     }
    149 
    150     public float getStrokeWidth() {
    151         return mStrokeWidth;
    152     }
    153 
    154     /**
    155      * returns the value of stroke miter needed by the java api.
    156      */
    157     public float getJavaStrokeMiter() {
    158         return mStrokeMiter;
    159     }
    160 
    161     public int getJavaCap() {
    162         switch (Paint.sCapArray[mCap]) {
    163             case BUTT:
    164                 return BasicStroke.CAP_BUTT;
    165             case ROUND:
    166                 return BasicStroke.CAP_ROUND;
    167             default:
    168             case SQUARE:
    169                 return BasicStroke.CAP_SQUARE;
    170         }
    171     }
    172 
    173     public int getJavaJoin() {
    174         switch (Paint.sJoinArray[mJoin]) {
    175             default:
    176             case MITER:
    177                 return BasicStroke.JOIN_MITER;
    178             case ROUND:
    179                 return BasicStroke.JOIN_ROUND;
    180             case BEVEL:
    181                 return BasicStroke.JOIN_BEVEL;
    182         }
    183     }
    184 
    185     public Stroke getJavaStroke() {
    186         if (mPathEffect != null) {
    187             if (mPathEffect.isSupported()) {
    188                 Stroke stroke = mPathEffect.getStroke(this);
    189                 assert stroke != null;
    190                 if (stroke != null) {
    191                     return stroke;
    192                 }
    193             } else {
    194                 Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
    195                         mPathEffect.getSupportMessage(),
    196                         null, null /*data*/);
    197             }
    198         }
    199 
    200         // if no custom stroke as been set, set the default one.
    201         return new BasicStroke(
    202                     getStrokeWidth(),
    203                     getJavaCap(),
    204                     getJavaJoin(),
    205                     getJavaStrokeMiter());
    206     }
    207 
    208     /**
    209      * Returns the {@link PorterDuff.Mode} as an int
    210      */
    211     public int getPorterDuffMode() {
    212         return mPorterDuffMode;
    213     }
    214 
    215     /**
    216      * Returns the {@link ColorFilter} delegate or null if none have been set
    217      *
    218      * @return the delegate or null.
    219      */
    220     public ColorFilter_Delegate getColorFilter() {
    221         return mColorFilter;
    222     }
    223 
    224     public void setColorFilter(long colorFilterPtr) {
    225         mColorFilter = ColorFilter_Delegate.getDelegate(colorFilterPtr);
    226     }
    227 
    228     public void setShader(long shaderPtr) {
    229         mShader = Shader_Delegate.getDelegate(shaderPtr);
    230     }
    231 
    232     /**
    233      * Returns the {@link Shader} delegate or null if none have been set
    234      *
    235      * @return the delegate or null.
    236      */
    237     public Shader_Delegate getShader() {
    238         return mShader;
    239     }
    240 
    241     /**
    242      * Returns the {@link MaskFilter} delegate or null if none have been set
    243      *
    244      * @return the delegate or null.
    245      */
    246     public MaskFilter_Delegate getMaskFilter() {
    247         return mMaskFilter;
    248     }
    249 
    250     // ---- native methods ----
    251 
    252     @LayoutlibDelegate
    253     /*package*/ static int nGetFlags(long nativePaint) {
    254         // get the delegate from the native int.
    255         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    256         if (delegate == null) {
    257             return 0;
    258         }
    259 
    260         return delegate.mFlags;
    261     }
    262 
    263 
    264 
    265     @LayoutlibDelegate
    266     /*package*/ static void nSetFlags(long nativePaint, int flags) {
    267         // get the delegate from the native int.
    268         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    269         if (delegate == null) {
    270             return;
    271         }
    272 
    273         delegate.mFlags = flags;
    274     }
    275 
    276     @LayoutlibDelegate
    277     /*package*/ static void nSetFilterBitmap(long nativePaint, boolean filter) {
    278         setFlag(nativePaint, Paint.FILTER_BITMAP_FLAG, filter);
    279     }
    280 
    281     @LayoutlibDelegate
    282     /*package*/ static int nGetHinting(long nativePaint) {
    283         // get the delegate from the native int.
    284         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    285         if (delegate == null) {
    286             return Paint.HINTING_ON;
    287         }
    288 
    289         return delegate.mHintingMode;
    290     }
    291 
    292     @LayoutlibDelegate
    293     /*package*/ static void nSetHinting(long nativePaint, int mode) {
    294         // get the delegate from the native int.
    295         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    296         if (delegate == null) {
    297             return;
    298         }
    299 
    300         delegate.mHintingMode = mode;
    301     }
    302 
    303     @LayoutlibDelegate
    304     /*package*/ static void nSetAntiAlias(long nativePaint, boolean aa) {
    305         setFlag(nativePaint, Paint.ANTI_ALIAS_FLAG, aa);
    306     }
    307 
    308     @LayoutlibDelegate
    309     /*package*/ static void nSetSubpixelText(long nativePaint,
    310             boolean subpixelText) {
    311         setFlag(nativePaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
    312     }
    313 
    314     @LayoutlibDelegate
    315     /*package*/ static void nSetUnderlineText(long nativePaint,
    316             boolean underlineText) {
    317         setFlag(nativePaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
    318     }
    319 
    320     @LayoutlibDelegate
    321     /*package*/ static void nSetStrikeThruText(long nativePaint,
    322             boolean strikeThruText) {
    323         setFlag(nativePaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
    324     }
    325 
    326     @LayoutlibDelegate
    327     /*package*/ static void nSetFakeBoldText(long nativePaint,
    328             boolean fakeBoldText) {
    329         setFlag(nativePaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
    330     }
    331 
    332     @LayoutlibDelegate
    333     /*package*/ static void nSetDither(long nativePaint, boolean dither) {
    334         setFlag(nativePaint, Paint.DITHER_FLAG, dither);
    335     }
    336 
    337     @LayoutlibDelegate
    338     /*package*/ static void nSetLinearText(long nativePaint, boolean linearText) {
    339         setFlag(nativePaint, Paint.LINEAR_TEXT_FLAG, linearText);
    340     }
    341 
    342     @LayoutlibDelegate
    343     /*package*/ static int nGetColor(long nativePaint) {
    344         // get the delegate from the native int.
    345         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    346         if (delegate == null) {
    347             return 0;
    348         }
    349 
    350         return delegate.mColor;
    351     }
    352 
    353     @LayoutlibDelegate
    354     /*package*/ static void nSetColor(long nativePaint, int color) {
    355         // get the delegate from the native int.
    356         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    357         if (delegate == null) {
    358             return;
    359         }
    360 
    361         delegate.mColor = color;
    362     }
    363 
    364     @LayoutlibDelegate
    365     /*package*/ static int nGetAlpha(long nativePaint) {
    366         // get the delegate from the native int.
    367         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    368         if (delegate == null) {
    369             return 0;
    370         }
    371 
    372         return delegate.getAlpha();
    373     }
    374 
    375     @LayoutlibDelegate
    376     /*package*/ static void nSetAlpha(long nativePaint, int a) {
    377         // get the delegate from the native int.
    378         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    379         if (delegate == null) {
    380             return;
    381         }
    382 
    383         delegate.setAlpha(a);
    384     }
    385 
    386     @LayoutlibDelegate
    387     /*package*/ static float nGetStrokeWidth(long nativePaint) {
    388         // get the delegate from the native int.
    389         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    390         if (delegate == null) {
    391             return 1.f;
    392         }
    393 
    394         return delegate.mStrokeWidth;
    395     }
    396 
    397     @LayoutlibDelegate
    398     /*package*/ static void nSetStrokeWidth(long nativePaint, float width) {
    399         // get the delegate from the native int.
    400         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    401         if (delegate == null) {
    402             return;
    403         }
    404 
    405         delegate.mStrokeWidth = width;
    406     }
    407 
    408     @LayoutlibDelegate
    409     /*package*/ static float nGetStrokeMiter(long nativePaint) {
    410         // get the delegate from the native int.
    411         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    412         if (delegate == null) {
    413             return 1.f;
    414         }
    415 
    416         return delegate.mStrokeMiter;
    417     }
    418 
    419     @LayoutlibDelegate
    420     /*package*/ static void nSetStrokeMiter(long nativePaint, float miter) {
    421         // get the delegate from the native int.
    422         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    423         if (delegate == null) {
    424             return;
    425         }
    426 
    427         delegate.mStrokeMiter = miter;
    428     }
    429 
    430     @LayoutlibDelegate
    431     /*package*/ static void nSetShadowLayer(long paint, float radius, float dx, float dy,
    432             int color) {
    433         // FIXME
    434         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
    435                 "Paint.setShadowLayer is not supported.", null, null /*data*/);
    436     }
    437 
    438     @LayoutlibDelegate
    439     /*package*/ static boolean nHasShadowLayer(long paint) {
    440         // FIXME
    441         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
    442                 "Paint.hasShadowLayer is not supported.", null, null /*data*/);
    443         return false;
    444     }
    445 
    446     @LayoutlibDelegate
    447     /*package*/ static boolean nIsElegantTextHeight(long nativePaint) {
    448         // get the delegate from the native int.
    449         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    450         return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT;
    451     }
    452 
    453     @LayoutlibDelegate
    454     /*package*/ static void nSetElegantTextHeight(long nativePaint,
    455             boolean elegant) {
    456         // get the delegate from the native int.
    457         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    458         if (delegate == null) {
    459             return;
    460         }
    461 
    462         delegate.mFontVariant = elegant ? FontVariant.ELEGANT : FontVariant.COMPACT;
    463     }
    464 
    465     @LayoutlibDelegate
    466     /*package*/ static float nGetTextSize(long nativePaint) {
    467         // get the delegate from the native int.
    468         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    469         if (delegate == null) {
    470             return 1.f;
    471         }
    472 
    473         return delegate.mTextSize;
    474     }
    475 
    476     @LayoutlibDelegate
    477     /*package*/ static void nSetTextSize(long nativePaint, float textSize) {
    478         // get the delegate from the native int.
    479         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    480         if (delegate == null) {
    481             return;
    482         }
    483 
    484         if (delegate.mTextSize != textSize) {
    485             delegate.mTextSize = textSize;
    486             delegate.updateFontObject();
    487         }
    488     }
    489 
    490     @LayoutlibDelegate
    491     /*package*/ static float nGetTextScaleX(long nativePaint) {
    492         // get the delegate from the native int.
    493         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    494         if (delegate == null) {
    495             return 1.f;
    496         }
    497 
    498         return delegate.mTextScaleX;
    499     }
    500 
    501     @LayoutlibDelegate
    502     /*package*/ static void nSetTextScaleX(long nativePaint, float scaleX) {
    503         // get the delegate from the native int.
    504         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    505         if (delegate == null) {
    506             return;
    507         }
    508 
    509         if (delegate.mTextScaleX != scaleX) {
    510             delegate.mTextScaleX = scaleX;
    511             delegate.updateFontObject();
    512         }
    513     }
    514 
    515     @LayoutlibDelegate
    516     /*package*/ static float nGetTextSkewX(long nativePaint) {
    517         // get the delegate from the native int.
    518         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    519         if (delegate == null) {
    520             return 1.f;
    521         }
    522 
    523         return delegate.mTextSkewX;
    524     }
    525 
    526     @LayoutlibDelegate
    527     /*package*/ static void nSetTextSkewX(long nativePaint, float skewX) {
    528         // get the delegate from the native int.
    529         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    530         if (delegate == null) {
    531             return;
    532         }
    533 
    534         if (delegate.mTextSkewX != skewX) {
    535             delegate.mTextSkewX = skewX;
    536             delegate.updateFontObject();
    537         }
    538     }
    539 
    540     @LayoutlibDelegate
    541     /*package*/ static float nAscent(long nativePaint, long nativeTypeface) {
    542         // get the delegate
    543         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    544         if (delegate == null) {
    545             return 0;
    546         }
    547 
    548         if (delegate.mFonts.size() > 0) {
    549             java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
    550             // Android expects negative ascent so we invert the value from Java.
    551             return - javaMetrics.getAscent();
    552         }
    553 
    554         return 0;
    555     }
    556 
    557     @LayoutlibDelegate
    558     /*package*/ static float nDescent(long nativePaint, long nativeTypeface) {
    559         // get the delegate
    560         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    561         if (delegate == null) {
    562             return 0;
    563         }
    564 
    565         if (delegate.mFonts.size() > 0) {
    566             java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
    567             return javaMetrics.getDescent();
    568         }
    569 
    570         return 0;
    571 
    572     }
    573 
    574     @LayoutlibDelegate
    575     /*package*/ static float nGetFontMetrics(long nativePaint, long nativeTypeface,
    576             FontMetrics metrics) {
    577         // get the delegate
    578         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    579         if (delegate == null) {
    580             return 0;
    581         }
    582 
    583         return delegate.getFontMetrics(metrics);
    584     }
    585 
    586     @LayoutlibDelegate
    587     /*package*/ static int nGetFontMetricsInt(long nativePaint,
    588             long nativeTypeface, FontMetricsInt fmi) {
    589         // get the delegate
    590         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    591         if (delegate == null) {
    592             return 0;
    593         }
    594 
    595         if (delegate.mFonts.size() > 0) {
    596             java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
    597             if (fmi != null) {
    598                 // Android expects negative ascent so we invert the value from Java.
    599                 fmi.top = - javaMetrics.getMaxAscent();
    600                 fmi.ascent = - javaMetrics.getAscent();
    601                 fmi.descent = javaMetrics.getDescent();
    602                 fmi.bottom = javaMetrics.getMaxDescent();
    603                 fmi.leading = javaMetrics.getLeading();
    604             }
    605 
    606             return javaMetrics.getHeight();
    607         }
    608 
    609         return 0;
    610     }
    611 
    612     @LayoutlibDelegate
    613     /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, char[] text,
    614             int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) {
    615 
    616         // get the delegate
    617         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
    618         if (delegate == null) {
    619             return 0;
    620         }
    621 
    622         int inc = count > 0 ? 1 : -1;
    623 
    624         int measureIndex = 0;
    625         for (int i = index; i != index + count; i += inc, measureIndex++) {
    626             int start, end;
    627             if (i < index) {
    628                 start = i;
    629                 end = index;
    630             } else {
    631                 start = index;
    632                 end = i;
    633             }
    634 
    635             // measure from start to end
    636             RectF bounds = delegate.measureText(text, start, end - start + 1, null, 0, bidiFlags);
    637             float res = bounds.right - bounds.left;
    638 
    639             if (measuredWidth != null) {
    640                 measuredWidth[measureIndex] = res;
    641             }
    642 
    643             if (res > maxWidth) {
    644                 // we should not return this char index, but since it's 0-based
    645                 // and we need to return a count, we simply return measureIndex;
    646                 return measureIndex;
    647             }
    648 
    649         }
    650 
    651         return measureIndex;
    652     }
    653 
    654     @LayoutlibDelegate
    655     /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, String text,
    656             boolean measureForwards,
    657             float maxWidth, int bidiFlags, float[] measuredWidth) {
    658         return nBreakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
    659                 maxWidth, bidiFlags, measuredWidth);
    660     }
    661 
    662     @LayoutlibDelegate
    663     /*package*/ static long nInit() {
    664         Paint_Delegate newDelegate = new Paint_Delegate();
    665         return sManager.addNewDelegate(newDelegate);
    666     }
    667 
    668     @LayoutlibDelegate
    669     /*package*/ static long nInitWithPaint(long paint) {
    670         // get the delegate from the native int.
    671         Paint_Delegate delegate = sManager.getDelegate(paint);
    672         if (delegate == null) {
    673             return 0;
    674         }
    675 
    676         Paint_Delegate newDelegate = new Paint_Delegate(delegate);
    677         return sManager.addNewDelegate(newDelegate);
    678     }
    679 
    680     @LayoutlibDelegate
    681     /*package*/ static void nReset(long native_object) {
    682         // get the delegate from the native int.
    683         Paint_Delegate delegate = sManager.getDelegate(native_object);
    684         if (delegate == null) {
    685             return;
    686         }
    687 
    688         delegate.reset();
    689     }
    690 
    691     @LayoutlibDelegate
    692     /*package*/ static void nSet(long native_dst, long native_src) {
    693         // get the delegate from the native int.
    694         Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
    695         if (delegate_dst == null) {
    696             return;
    697         }
    698 
    699         // get the delegate from the native int.
    700         Paint_Delegate delegate_src = sManager.getDelegate(native_src);
    701         if (delegate_src == null) {
    702             return;
    703         }
    704 
    705         delegate_dst.set(delegate_src);
    706     }
    707 
    708     @LayoutlibDelegate
    709     /*package*/ static int nGetStyle(long native_object) {
    710         // get the delegate from the native int.
    711         Paint_Delegate delegate = sManager.getDelegate(native_object);
    712         if (delegate == null) {
    713             return 0;
    714         }
    715 
    716         return delegate.mStyle;
    717     }
    718 
    719     @LayoutlibDelegate
    720     /*package*/ static void nSetStyle(long native_object, int style) {
    721         // get the delegate from the native int.
    722         Paint_Delegate delegate = sManager.getDelegate(native_object);
    723         if (delegate == null) {
    724             return;
    725         }
    726 
    727         delegate.mStyle = style;
    728     }
    729 
    730     @LayoutlibDelegate
    731     /*package*/ static int nGetStrokeCap(long native_object) {
    732         // get the delegate from the native int.
    733         Paint_Delegate delegate = sManager.getDelegate(native_object);
    734         if (delegate == null) {
    735             return 0;
    736         }
    737 
    738         return delegate.mCap;
    739     }
    740 
    741     @LayoutlibDelegate
    742     /*package*/ static void nSetStrokeCap(long native_object, int cap) {
    743         // get the delegate from the native int.
    744         Paint_Delegate delegate = sManager.getDelegate(native_object);
    745         if (delegate == null) {
    746             return;
    747         }
    748 
    749         delegate.mCap = cap;
    750     }
    751 
    752     @LayoutlibDelegate
    753     /*package*/ static int nGetStrokeJoin(long native_object) {
    754         // get the delegate from the native int.
    755         Paint_Delegate delegate = sManager.getDelegate(native_object);
    756         if (delegate == null) {
    757             return 0;
    758         }
    759 
    760         return delegate.mJoin;
    761     }
    762 
    763     @LayoutlibDelegate
    764     /*package*/ static void nSetStrokeJoin(long native_object, int join) {
    765         // get the delegate from the native int.
    766         Paint_Delegate delegate = sManager.getDelegate(native_object);
    767         if (delegate == null) {
    768             return;
    769         }
    770 
    771         delegate.mJoin = join;
    772     }
    773 
    774     @LayoutlibDelegate
    775     /*package*/ static boolean nGetFillPath(long native_object, long src, long dst) {
    776         Paint_Delegate paint = sManager.getDelegate(native_object);
    777         if (paint == null) {
    778             return false;
    779         }
    780 
    781         Path_Delegate srcPath = Path_Delegate.getDelegate(src);
    782         if (srcPath == null) {
    783             return true;
    784         }
    785 
    786         Path_Delegate dstPath = Path_Delegate.getDelegate(dst);
    787         if (dstPath == null) {
    788             return true;
    789         }
    790 
    791         Stroke stroke = paint.getJavaStroke();
    792         Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape());
    793 
    794         dstPath.setJavaShape(strokeShape);
    795 
    796         // FIXME figure out the return value?
    797         return true;
    798     }
    799 
    800     @LayoutlibDelegate
    801     /*package*/ static long nSetShader(long native_object, long shader) {
    802         // get the delegate from the native int.
    803         Paint_Delegate delegate = sManager.getDelegate(native_object);
    804         if (delegate == null) {
    805             return shader;
    806         }
    807 
    808         delegate.mShader = Shader_Delegate.getDelegate(shader);
    809 
    810         return shader;
    811     }
    812 
    813     @LayoutlibDelegate
    814     /*package*/ static long nSetColorFilter(long native_object, long filter) {
    815         // get the delegate from the native int.
    816         Paint_Delegate delegate = sManager.getDelegate(native_object);
    817         if (delegate == null) {
    818             return filter;
    819         }
    820 
    821         delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);
    822 
    823         // Log warning if it's not supported.
    824         if (delegate.mColorFilter != null && !delegate.mColorFilter.isSupported()) {
    825             Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
    826                     delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
    827         }
    828 
    829         return filter;
    830     }
    831 
    832     @LayoutlibDelegate
    833     /*package*/ static void nSetXfermode(long native_object, int xfermode) {
    834         Paint_Delegate delegate = sManager.getDelegate(native_object);
    835         if (delegate == null) {
    836             return;
    837         }
    838         delegate.mPorterDuffMode = xfermode;
    839     }
    840 
    841     @LayoutlibDelegate
    842     /*package*/ static long nSetPathEffect(long native_object, long effect) {
    843         // get the delegate from the native int.
    844         Paint_Delegate delegate = sManager.getDelegate(native_object);
    845         if (delegate == null) {
    846             return effect;
    847         }
    848 
    849         delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect);
    850 
    851         return effect;
    852     }
    853 
    854     @LayoutlibDelegate
    855     /*package*/ static long nSetMaskFilter(long native_object, long maskfilter) {
    856         // get the delegate from the native int.
    857         Paint_Delegate delegate = sManager.getDelegate(native_object);
    858         if (delegate == null) {
    859             return maskfilter;
    860         }
    861 
    862         delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
    863 
    864         // since none of those are supported, display a fidelity warning right away
    865         if (delegate.mMaskFilter != null && !delegate.mMaskFilter.isSupported()) {
    866             Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
    867                     delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
    868         }
    869 
    870         return maskfilter;
    871     }
    872 
    873     @LayoutlibDelegate
    874     /*package*/ static long nSetTypeface(long native_object, long typeface) {
    875         // get the delegate from the native int.
    876         Paint_Delegate delegate = sManager.getDelegate(native_object);
    877         if (delegate == null) {
    878             return 0;
    879         }
    880 
    881         Typeface_Delegate typefaceDelegate = Typeface_Delegate.getDelegate(typeface);
    882         if (delegate.mTypeface != typefaceDelegate || delegate.mNativeTypeface != typeface) {
    883             delegate.mTypeface = Typeface_Delegate.getDelegate(typeface);
    884             delegate.mNativeTypeface = typeface;
    885             delegate.updateFontObject();
    886         }
    887         return typeface;
    888     }
    889 
    890     @LayoutlibDelegate
    891     /*package*/ static int nGetTextAlign(long native_object) {
    892         // get the delegate from the native int.
    893         Paint_Delegate delegate = sManager.getDelegate(native_object);
    894         if (delegate == null) {
    895             return 0;
    896         }
    897 
    898         return delegate.mTextAlign;
    899     }
    900 
    901     @LayoutlibDelegate
    902     /*package*/ static void nSetTextAlign(long native_object, int align) {
    903         // get the delegate from the native int.
    904         Paint_Delegate delegate = sManager.getDelegate(native_object);
    905         if (delegate == null) {
    906             return;
    907         }
    908 
    909         delegate.mTextAlign = align;
    910     }
    911 
    912     @LayoutlibDelegate
    913     /*package*/ static int nSetTextLocales(long native_object, String locale) {
    914         // get the delegate from the native int.
    915         Paint_Delegate delegate = sManager.getDelegate(native_object);
    916         if (delegate == null) {
    917             return 0;
    918         }
    919 
    920         delegate.setTextLocale(locale);
    921         return 0;
    922     }
    923 
    924     @LayoutlibDelegate
    925     /*package*/ static void nSetTextLocalesByMinikinLangListId(long paintPtr,
    926             int mMinikinLangListId) {
    927         // FIXME
    928     }
    929 
    930     @LayoutlibDelegate
    931     /*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
    932             char[] text, int index, int count, int contextIndex, int contextCount,
    933             int bidiFlags, float[] advances, int advancesIndex) {
    934 
    935         if (advances != null)
    936             for (int i = advancesIndex; i< advancesIndex+count; i++)
    937                 advances[i]=0;
    938         // get the delegate from the native int.
    939         Paint_Delegate delegate = sManager.getDelegate(native_object);
    940         if (delegate == null) {
    941             return 0.f;
    942         }
    943 
    944         // native_typeface is passed here since Framework's old implementation did not have the
    945         // typeface object associated with the Paint. Since, we follow the new framework way,
    946         // we store the typeface with the paint and use it directly.
    947         assert (native_typeface == delegate.mNativeTypeface);
    948 
    949         RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, bidiFlags);
    950         return bounds.right - bounds.left;
    951     }
    952 
    953     @LayoutlibDelegate
    954     /*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
    955             String text, int start, int end, int contextStart, int contextEnd,
    956             int bidiFlags, float[] advances, int advancesIndex) {
    957         // FIXME: support contextStart and contextEnd
    958         int count = end - start;
    959         char[] buffer = TemporaryBuffer.obtain(count);
    960         TextUtils.getChars(text, start, end, buffer, 0);
    961 
    962         return nGetTextAdvances(native_object, native_typeface, buffer, 0, count,
    963                 contextStart, contextEnd - contextStart, bidiFlags, advances, advancesIndex);
    964     }
    965 
    966     @LayoutlibDelegate
    967     /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr,
    968             char[] text, int contextStart, int contextLength, int flags, int offset,
    969             int cursorOpt) {
    970         // FIXME
    971         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
    972                 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
    973         return 0;
    974     }
    975 
    976     @LayoutlibDelegate
    977     /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr,
    978             String text, int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
    979         // FIXME
    980         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
    981                 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
    982         return 0;
    983     }
    984 
    985     @LayoutlibDelegate
    986     /*package*/ static void nGetTextPath(long native_object, long native_typeface,
    987             int bidiFlags, char[] text, int index, int count, float x, float y, long path) {
    988         // FIXME
    989         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
    990                 "Paint.getTextPath is not supported.", null, null /*data*/);
    991     }
    992 
    993     @LayoutlibDelegate
    994     /*package*/ static void nGetTextPath(long native_object, long native_typeface,
    995             int bidiFlags, String text, int start, int end, float x, float y, long path) {
    996         // FIXME
    997         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
    998                 "Paint.getTextPath is not supported.", null, null /*data*/);
    999     }
   1000 
   1001     @LayoutlibDelegate
   1002     /*package*/ static void nGetStringBounds(long nativePaint, long native_typeface,
   1003             String text, int start, int end, int bidiFlags, Rect bounds) {
   1004         nGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
   1005                 end - start, bidiFlags, bounds);
   1006     }
   1007 
   1008     @LayoutlibDelegate
   1009     /*package*/ static void nGetCharArrayBounds(long nativePaint, long native_typeface,
   1010             char[] text, int index, int count, int bidiFlags, Rect bounds) {
   1011 
   1012         // get the delegate from the native int.
   1013         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1014         if (delegate == null) {
   1015             return;
   1016         }
   1017 
   1018         // assert that the typeface passed is actually the one that we had stored.
   1019         assert (native_typeface == delegate.mNativeTypeface);
   1020 
   1021         delegate.measureText(text, index, count, null, 0, bidiFlags).roundOut(bounds);
   1022     }
   1023 
   1024     @LayoutlibDelegate
   1025     /*package*/ static long nGetNativeFinalizer() {
   1026         synchronized (Paint_Delegate.class) {
   1027             if (sFinalizer == -1) {
   1028                 sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(
   1029                         sManager::removeJavaReferenceFor);
   1030             }
   1031         }
   1032         return sFinalizer;
   1033     }
   1034 
   1035     @LayoutlibDelegate
   1036     /*package*/ static float nGetLetterSpacing(long nativePaint) {
   1037         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1038         if (delegate == null) {
   1039             return 0;
   1040         }
   1041         return delegate.mLetterSpacing;
   1042     }
   1043 
   1044     @LayoutlibDelegate
   1045     /*package*/ static void nSetLetterSpacing(long nativePaint, float letterSpacing) {
   1046         Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
   1047                 "Paint.setLetterSpacing() not supported.", null, null);
   1048         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1049         if (delegate == null) {
   1050             return;
   1051         }
   1052         delegate.mLetterSpacing = letterSpacing;
   1053     }
   1054 
   1055     @LayoutlibDelegate
   1056     /*package*/ static float nGetWordSpacing(long nativePaint) {
   1057         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1058         if (delegate == null) {
   1059             return 0;
   1060         }
   1061         return delegate.mWordSpacing;
   1062     }
   1063 
   1064     @LayoutlibDelegate
   1065     /*package*/ static void nSetWordSpacing(long nativePaint, float wordSpacing) {
   1066         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1067         if (delegate == null) {
   1068             return;
   1069         }
   1070         delegate.mWordSpacing = wordSpacing;
   1071     }
   1072 
   1073     @LayoutlibDelegate
   1074     /*package*/ static void nSetFontFeatureSettings(long nativePaint, String settings) {
   1075         Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
   1076                 "Paint.setFontFeatureSettings() not supported.", null, null);
   1077     }
   1078 
   1079     @LayoutlibDelegate
   1080     /*package*/ static int nGetHyphenEdit(long nativePaint) {
   1081         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1082         if (delegate == null) {
   1083             return 0;
   1084         }
   1085         return delegate.mHyphenEdit;
   1086     }
   1087 
   1088     @LayoutlibDelegate
   1089     /*package*/ static void nSetHyphenEdit(long nativePaint, int hyphen) {
   1090         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1091         if (delegate == null) {
   1092             return;
   1093         }
   1094         delegate.mHyphenEdit = hyphen;
   1095     }
   1096 
   1097     @LayoutlibDelegate
   1098     /*package*/ static boolean nHasGlyph(long nativePaint, long nativeTypeface, int bidiFlags,
   1099             String string) {
   1100         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1101         if (delegate == null) {
   1102             return false;
   1103         }
   1104         if (string.length() == 0) {
   1105             return false;
   1106         }
   1107         if (string.length() > 1) {
   1108             Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
   1109                     "Paint.hasGlyph() is not supported for ligatures.", null, null);
   1110             return false;
   1111         }
   1112         assert nativeTypeface == delegate.mNativeTypeface;
   1113         Typeface_Delegate typeface_delegate = Typeface_Delegate.getDelegate(nativeTypeface);
   1114 
   1115         char c = string.charAt(0);
   1116         for (Font font : typeface_delegate.getFonts(delegate.mFontVariant)) {
   1117             if (font.canDisplay(c)) {
   1118                 return true;
   1119             }
   1120         }
   1121         return false;
   1122     }
   1123 
   1124 
   1125     @LayoutlibDelegate
   1126     /*package*/ static float nGetRunAdvance(long nativePaint, long nativeTypeface,
   1127             @NonNull char[] text, int start, int end, int contextStart, int contextEnd,
   1128             boolean isRtl, int offset) {
   1129         int count = end - start;
   1130         float[] advances = new float[count];
   1131         int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
   1132         nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
   1133                 contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
   1134         int startOffset = offset - start;  // offset from start.
   1135         float sum = 0;
   1136         for (int i = 0; i < startOffset; i++) {
   1137             sum += advances[i];
   1138         }
   1139         return sum;
   1140     }
   1141 
   1142     @LayoutlibDelegate
   1143     /*package*/ static int nGetOffsetForAdvance(long nativePaint, long nativeTypeface,
   1144             char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl,
   1145             float advance) {
   1146         int count = end - start;
   1147         float[] advances = new float[count];
   1148         int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
   1149         nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
   1150                 contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
   1151         float sum = 0;
   1152         int i;
   1153         for (i = 0; i < count && sum < advance; i++) {
   1154             sum += advances[i];
   1155         }
   1156         float distanceToI = sum - advance;
   1157         float distanceToIMinus1 = advance - (sum - advances[i]);
   1158         return distanceToI > distanceToIMinus1 ? i : i - 1;
   1159     }
   1160 
   1161     // ---- Private delegate/helper methods ----
   1162 
   1163     /*package*/ Paint_Delegate() {
   1164         reset();
   1165     }
   1166 
   1167     private Paint_Delegate(Paint_Delegate paint) {
   1168         set(paint);
   1169     }
   1170 
   1171     private void set(Paint_Delegate paint) {
   1172         mFlags = paint.mFlags;
   1173         mColor = paint.mColor;
   1174         mStyle = paint.mStyle;
   1175         mCap = paint.mCap;
   1176         mJoin = paint.mJoin;
   1177         mTextAlign = paint.mTextAlign;
   1178 
   1179         boolean needsFontUpdate = false;
   1180         if (mTypeface != paint.mTypeface || mNativeTypeface != paint.mNativeTypeface) {
   1181             mTypeface = paint.mTypeface;
   1182             mNativeTypeface = paint.mNativeTypeface;
   1183             needsFontUpdate = true;
   1184         }
   1185 
   1186         if (mTextSize != paint.mTextSize) {
   1187             mTextSize = paint.mTextSize;
   1188             needsFontUpdate = true;
   1189         }
   1190 
   1191         if (mTextScaleX != paint.mTextScaleX) {
   1192             mTextScaleX = paint.mTextScaleX;
   1193             needsFontUpdate = true;
   1194         }
   1195 
   1196         if (mTextSkewX != paint.mTextSkewX) {
   1197             mTextSkewX = paint.mTextSkewX;
   1198             needsFontUpdate = true;
   1199         }
   1200 
   1201         mStrokeWidth = paint.mStrokeWidth;
   1202         mStrokeMiter = paint.mStrokeMiter;
   1203         mPorterDuffMode = paint.mPorterDuffMode;
   1204         mColorFilter = paint.mColorFilter;
   1205         mShader = paint.mShader;
   1206         mPathEffect = paint.mPathEffect;
   1207         mMaskFilter = paint.mMaskFilter;
   1208         mHintingMode = paint.mHintingMode;
   1209 
   1210         if (needsFontUpdate) {
   1211             updateFontObject();
   1212         }
   1213     }
   1214 
   1215     private void reset() {
   1216         mFlags = Paint.HIDDEN_DEFAULT_PAINT_FLAGS;
   1217         mColor = 0xFF000000;
   1218         mStyle = Paint.Style.FILL.nativeInt;
   1219         mCap = Paint.Cap.BUTT.nativeInt;
   1220         mJoin = Paint.Join.MITER.nativeInt;
   1221         mTextAlign = 0;
   1222         mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance);
   1223         mNativeTypeface = 0;
   1224         mStrokeWidth = 1.f;
   1225         mStrokeMiter = 4.f;
   1226         mTextSize = 20.f;
   1227         mTextScaleX = 1.f;
   1228         mTextSkewX = 0.f;
   1229         mPorterDuffMode = Xfermode.DEFAULT;
   1230         mColorFilter = null;
   1231         mShader = null;
   1232         mPathEffect = null;
   1233         mMaskFilter = null;
   1234         updateFontObject();
   1235         mHintingMode = Paint.HINTING_ON;
   1236     }
   1237 
   1238     /**
   1239      * Update the {@link Font} object from the typeface, text size and scaling
   1240      */
   1241     @SuppressWarnings("deprecation")
   1242     private void updateFontObject() {
   1243         if (mTypeface != null) {
   1244             // Get the fonts from the TypeFace object.
   1245             List<Font> fonts = mTypeface.getFonts(mFontVariant);
   1246 
   1247             if (fonts.isEmpty()) {
   1248                 mFonts = Collections.emptyList();
   1249                 return;
   1250             }
   1251 
   1252             // create new font objects as well as FontMetrics, based on the current text size
   1253             // and skew info.
   1254             int nFonts = fonts.size();
   1255             ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(nFonts);
   1256             //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
   1257             for (int i = 0; i < nFonts; i++) {
   1258                 Font font = fonts.get(i);
   1259                 if (font == null) {
   1260                     // If the font is null, add null to infoList. When rendering the text, if this
   1261                     // null is reached, a warning will be logged.
   1262                     infoList.add(null);
   1263                     continue;
   1264                 }
   1265                 FontInfo info = new FontInfo();
   1266                 info.mFont = font.deriveFont(mTextSize);
   1267                 if (mTextScaleX != 1.0 || mTextSkewX != 0) {
   1268                     // TODO: support skew
   1269                     info.mFont = info.mFont.deriveFont(new AffineTransform(
   1270                             mTextScaleX, mTextSkewX, 0, 1, 0, 0));
   1271                 }
   1272                 // The metrics here don't have anti-aliasing set.
   1273                 info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont);
   1274 
   1275                 infoList.add(info);
   1276             }
   1277 
   1278             mFonts = Collections.unmodifiableList(infoList);
   1279         }
   1280     }
   1281 
   1282     /*package*/ RectF measureText(char[] text, int index, int count, float[] advances,
   1283             int advancesIndex, int bidiFlags) {
   1284         return new BidiRenderer(null, this, text)
   1285                 .renderText(index, index + count, bidiFlags, advances, advancesIndex, false);
   1286     }
   1287 
   1288     /*package*/ RectF measureText(char[] text, int index, int count, float[] advances,
   1289             int advancesIndex, boolean isRtl) {
   1290         return new BidiRenderer(null, this, text)
   1291                 .renderText(index, index + count, isRtl, advances, advancesIndex, false);
   1292     }
   1293 
   1294     private float getFontMetrics(FontMetrics metrics) {
   1295         if (mFonts.size() > 0) {
   1296             java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics;
   1297             if (metrics != null) {
   1298                 // Android expects negative ascent so we invert the value from Java.
   1299                 metrics.top = - javaMetrics.getMaxAscent();
   1300                 metrics.ascent = - javaMetrics.getAscent();
   1301                 metrics.descent = javaMetrics.getDescent();
   1302                 metrics.bottom = javaMetrics.getMaxDescent();
   1303                 metrics.leading = javaMetrics.getLeading();
   1304             }
   1305 
   1306             return javaMetrics.getHeight();
   1307         }
   1308 
   1309         return 0;
   1310     }
   1311 
   1312     private void setTextLocale(String locale) {
   1313         mLocale = new Locale(locale);
   1314     }
   1315 
   1316     private static void setFlag(long nativePaint, int flagMask, boolean flagValue) {
   1317         // get the delegate from the native int.
   1318         Paint_Delegate delegate = sManager.getDelegate(nativePaint);
   1319         if (delegate == null) {
   1320             return;
   1321         }
   1322 
   1323         if (flagValue) {
   1324             delegate.mFlags |= flagMask;
   1325         } else {
   1326             delegate.mFlags &= ~flagMask;
   1327         }
   1328     }
   1329 }
   1330