package com.glview.hwui; import android.graphics.Color; import com.glview.graphics.Typeface; import com.glview.graphics.font.FontUtils; import com.glview.graphics.shader.BaseShader; public class GLPaint { float mStrokeWidth; public int mColor; int mAlpha; Style mStyle; BaseShader mShader; int mFlags = 0; int mTextSize; Typeface mTypeface; float mShadowRadius; float mShadowDx, mShadowDy; int mShadowColor; boolean mHasShadow = false; /** * Paint flag that enables antialiasing when drawing. * * <p>Enabling this flag will cause all draw operations that support * antialiasing to use it.</p> * * @see #Paint(int) * @see #setFlags(int) */ public static final int ANTI_ALIAS_FLAG = 0x01; /** * Paint flag that enables bilinear sampling on scaled bitmaps. * * <p>If cleared, scaled bitmaps will be drawn with nearest neighbor * sampling, likely resulting in artifacts. This should generally be on * when drawing bitmaps, unless performance-bound (rendering to software * canvas) or preferring pixelation artifacts to blurriness when scaling * significantly.</p> * * <p>If bitmaps are scaled for device density at creation time (as * resource bitmaps often are) the filtering will already have been * done.</p> * * @see #Paint(int) * @see #setFlags(int) */ public static final int FILTER_BITMAP_FLAG = 0x02; /** * Paint flag that enables dithering when blitting. * * <p>Enabling this flag applies a dither to any blit operation where the * target's colour space is more constrained than the source. * * @see #Paint(int) * @see #setFlags(int) */ public static final int DITHER_FLAG = 0x04; /** * Paint flag that applies an underline decoration to drawn text. * * @see #Paint(int) * @see #setFlags(int) */ public static final int UNDERLINE_TEXT_FLAG = 0x08; /** * Paint flag that applies a strike-through decoration to drawn text. * * @see #Paint(int) * @see #setFlags(int) */ public static final int STRIKE_THRU_TEXT_FLAG = 0x10; /** * Paint flag that applies a synthetic bolding effect to drawn text. * * <p>Enabling this flag will cause text draw operations to apply a * simulated bold effect when drawing a {@link Typeface} that is not * already bold.</p> * * @see #Paint(int) * @see #setFlags(int) */ public static final int FAKE_BOLD_TEXT_FLAG = 0x20; /** * Paint flag that enables smooth linear scaling of text. * * <p>Enabling this flag does not actually scale text, but rather adjusts * text draw operations to deal gracefully with smooth adjustment of scale. * When this flag is enabled, font hinting is disabled to prevent shape * deformation between scale factors, and glyph caching is disabled due to * the large number of glyph images that will be generated.</p> * * <p>{@link #SUBPIXEL_TEXT_FLAG} should be used in conjunction with this * flag to prevent glyph positions from snapping to whole pixel values as * scale factor is adjusted.</p> * * @see #Paint(int) * @see #setFlags(int) */ public static final int LINEAR_TEXT_FLAG = 0x40; /** * Paint flag that enables subpixel positioning of text. * * <p>Enabling this flag causes glyph advances to be computed with subpixel * accuracy.</p> * * <p>This can be used with {@link #LINEAR_TEXT_FLAG} to prevent text from * jittering during smooth scale transitions.</p> * * @see #Paint(int) * @see #setFlags(int) */ public static final int SUBPIXEL_TEXT_FLAG = 0x80; /** Legacy Paint flag, no longer used. */ public static final int DEV_KERN_TEXT_FLAG = 0x100; /** @hide bit mask for the flag enabling subpixel glyph rendering for text */ public static final int LCD_RENDER_TEXT_FLAG = 0x200; /** * Paint flag that enables the use of bitmap fonts when drawing text. * * <p>Disabling this flag will prevent text draw operations from using * embedded bitmap strikes in fonts, causing fonts with both scalable * outlines and bitmap strikes to draw only the scalable outlines, and * fonts with only bitmap strikes to not draw at all.</p> * * @see #Paint(int) * @see #setFlags(int) */ public static final int EMBEDDED_BITMAP_TEXT_FLAG = 0x400; /** @hide bit mask for the flag forcing freetype's autohinter on for text */ public static final int AUTO_HINTING_TEXT_FLAG = 0x800; /** @hide bit mask for the flag enabling vertical rendering for text */ public static final int VERTICAL_TEXT_FLAG = 0x1000; // we use this when we first create a paint static final int DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG | EMBEDDED_BITMAP_TEXT_FLAG; public GLPaint() { this(0); } public GLPaint(int flags) { setFlags(flags | DEFAULT_PAINT_FLAGS); reset(); } public void set(GLPaint paint) { if (paint != null) { mStrokeWidth = paint.mStrokeWidth; mColor = paint.mColor; mAlpha = paint.mAlpha; mStyle = paint.mStyle; mTextSize = paint.mTextSize; mTypeface = paint.mTypeface; mShader = paint.mShader; setShadowLayer(paint.mShadowRadius, paint.mShadowDx, paint.mShadowDy, paint.mShadowColor); } else { reset(); } } public void reset() { mStrokeWidth = 1f; mColor = Color.WHITE; mAlpha = 255; mStyle = Style.FILL; mTextSize = 25; mTypeface = null; mShader = null; clearShadowLayer(); } /** * Return the paint's flags. Use the Flag enum to test flag values. * * @return the paint's flags (see enums ending in _Flag for bit masks) */ public int getFlags() { return mFlags; } /** * Set the paint's flags. Use the Flag enum to specific flag values. * * @param flags The new flag bits for the paint */ public void setFlags(int flags) { mFlags = flags; } /** * Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set * AntiAliasing smooths out the edges of what is being drawn, but is has * no impact on the interior of the shape. See setDither() and * setFilterBitmap() to affect how colors are treated. * * @return true if the antialias bit is set in the paint's flags. */ public final boolean isAntiAlias() { return (getFlags() & ANTI_ALIAS_FLAG) != 0; } /** * Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit * AntiAliasing smooths out the edges of what is being drawn, but is has * no impact on the interior of the shape. See setDither() and * setFilterBitmap() to affect how colors are treated. * * @param aa true to set the antialias bit in the flags, false to clear it */ public void setAntiAlias(boolean aa) { mFlags |= ANTI_ALIAS_FLAG; } /** * Helper for getFlags(), returning true if DITHER_FLAG bit is set * Dithering affects how colors that are higher precision than the device * are down-sampled. No dithering is generally faster, but higher precision * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to * distribute the error inherent in this process, to reduce the visual * artifacts. * * @return true if the dithering bit is set in the paint's flags. */ public final boolean isDither() { return (getFlags() & DITHER_FLAG) != 0; } /** * Helper for setFlags(), setting or clearing the DITHER_FLAG bit * Dithering affects how colors that are higher precision than the device * are down-sampled. No dithering is generally faster, but higher precision * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to * distribute the error inherent in this process, to reduce the visual * artifacts. * * @param dither true to set the dithering bit in flags, false to clear it */ public void setDither(boolean dither) { mFlags |= DITHER_FLAG; } public void setColor(int color) { mColor = color; } public int getColor() { return mColor; } public void setStrokeWidth(float width) { mStrokeWidth = width; } public float getStrokeWidth() { return mStrokeWidth; } public int getAlpha() { return mAlpha; } public void setAlpha(int alpha) { mAlpha = alpha; } public Style getStyle() { return mStyle; } public void setStyle(Style style) { mStyle = style; } public int getTextSize() { return mTextSize; } public void setTextSize(float textSize) { if (textSize > 500 || textSize < 5) { throw new IllegalArgumentException("textSize should be in range[5-500], set=" + textSize); } mTextSize = (int) (textSize + 0.5f); } public Typeface getTypeface() { return mTypeface != null ? mTypeface : Typeface.DEFAULT; } public void setTypeface(Typeface typeface) { mTypeface = typeface; } public void setShadowLayer(float radius, float dx, float dy, int shadowColor) { if (mShadowRadius > 25) { throw new IllegalArgumentException("Shadow radius must not big than 25!"); } mShadowRadius = radius; mShadowDx = dx; mShadowDy = dy; mShadowColor = shadowColor; mHasShadow = mShadowRadius >= 1 && mShadowColor != 0; } public float getShadowRadius() { return mShadowRadius; } public float getShadowDx() { return mShadowDx; } public float getShadowDy() { return mShadowDy; } public int getShadowColor() { return mShadowColor; } public boolean hasShadow() { return mHasShadow; } /** * Clear the shadow layer. */ public void clearShadowLayer() { setShadowLayer(0, 0, 0, 0); } public void setShader(BaseShader shader) { mShader = shader; } public BaseShader getShader() { return mShader; } /** * The Style specifies if the primitive being drawn is filled, stroked, or * both (in the same color). The default is FILL. */ public enum Style { /** * Geometry and text drawn with this style will be filled, ignoring all * stroke-related settings in the paint. */ FILL, /** * Geometry and text drawn with this style will be stroked, respecting * the stroke-related fields on the paint. */ STROKE, /** * Geometry and text drawn with this style will be both filled and * stroked at the same time, respecting the stroke-related fields on * the paint. This mode can give unexpected results if the geometry * is oriented counter-clockwise. This restriction does not apply to * either FILL or STROKE. */ FILL_AND_STROKE; } public float measureText(char[] text, int index, int count) { return FontUtils.measureText(this, text, index, count); } public float measureText(CharSequence text, int start, int end) { return FontUtils.measureText(this, text, start, end); } public float measureText(CharSequence text) { return measureText(text, 0, text.length()); } /** * Return the font's interline spacing, given the Paint's settings for * typeface, textSize, etc. If metrics is not null, return the fontmetric * values in it. Note: all values have been converted to integers from * floats, in such a way has to make the answers useful for both spacing * and clipping. If you want more control over the rounding, call * getFontMetrics(). * * @return the font's interline spacing. */ public int getFontMetricsInt(FontMetricsInt fmi) { return FontUtils.getFontMetricsInt(this, fmi); } public FontMetricsInt getFontMetricsInt() { FontMetricsInt fm = new FontMetricsInt(); getFontMetricsInt(fm); return fm; } /** * Convenience method for callers that want to have FontMetrics values as * integers. */ public static class FontMetricsInt { public int top; public int ascent; public int descent; public int bottom; public int leading; @Override public String toString() { return "FontMetricsInt: top=" + top + " ascent=" + ascent + " descent=" + descent + " bottom=" + bottom + " leading=" + leading; } } }