1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h"
9b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com#include "SkAnnotation.h"
10791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkAutoKern.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
12791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkData.h"
13532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com#include "SkDeviceProperties.h"
14c4b84aef1adeb68bc853f35abb85b79fa1fcaac6rmistry#include "SkDraw.h"
15791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkFontDescriptor.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFontHost.h"
17791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkGlyphCache.h"
1815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com#include "SkImageFilter.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
2097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#include "SkMaskGamma.h"
218b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
228b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
23791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkPaintDefaults.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathEffect.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRasterizer.h"
2628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkScalar.h"
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h"
28791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkShader.h"
29791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkStringUtils.h"
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStroke.h"
3128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkTextFormatParams.h"
32e69137620ab0b5b40d230318c8e11b822f63cb9dreed@google.com#include "SkTextToPathIter.h"
33ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com#include "SkTLazy.h"
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypeface.h"
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
36791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
37aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orgenum {
38aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    kColor_DirtyBit               = 1 <<  0,
3945d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kTextSize_DirtyBit            = 1 <<  1,
4045d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kTextScaleX_DirtyBit          = 1 <<  2,
4145d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kTextSkewX_DirtyBit           = 1 <<  3,
4245d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kStrokeWidth_DirtyBit         = 1 <<  4,
4345d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kStrokeMiter_DirtyBit         = 1 <<  5,
4445d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org
4545d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kPOD_DirtyBitMask             = 63,
4645d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org
4745d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kPathEffect_DirtyBit          = 1 <<  6,
4845d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kShader_DirtyBit              = 1 <<  7,
4945d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kXfermode_DirtyBit            = 1 <<  8,
5045d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kMaskFilter_DirtyBit          = 1 <<  9,
5145d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kColorFilter_DirtyBit         = 1 << 10,
5245d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kRasterizer_DirtyBit          = 1 << 11,
5345d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kLooper_DirtyBit              = 1 << 12,
5445d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kImageFilter_DirtyBit         = 1 << 13,
5545d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kTypeface_DirtyBit            = 1 << 14,
5645d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kAnnotation_DirtyBit          = 1 << 15,
57aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org};
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
59a3237875f807aed9608cb4a023bc044f32850727reed@google.com// define this to get a printf for out-of-range parameter in setters
60a3237875f807aed9608cb4a023bc044f32850727reed@google.com// e.g. setTextSize(-1)
61a3237875f807aed9608cb4a023bc044f32850727reed@google.com//#define SK_REPORT_API_RANGE_CHECK
62a3237875f807aed9608cb4a023bc044f32850727reed@google.com
6356c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
64f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#define GEN_ID_INC                  fGenerationID++
65f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
66f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#else
67f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#define GEN_ID_INC
68f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#define GEN_ID_INC_EVAL(expression)
69f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
70f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
71a3122b9b1ec66efef606d8797b7b16b6634e08d2reed@android.comSkPaint::SkPaint() {
72aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fTypeface    = NULL;
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPathEffect  = NULL;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader      = NULL;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode    = NULL;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMaskFilter  = NULL;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColorFilter = NULL;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRasterizer  = NULL;
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLooper      = NULL;
8015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    fImageFilter = NULL;
81b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    fAnnotation  = NULL;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
83f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fTextSize   = SkPaintDefaults_TextSize;
84f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fTextScaleX = SK_Scalar1;
85f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fTextSkewX  = 0;
86f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fColor      = SK_ColorBLACK;
87f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fWidth      = 0;
88f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fMiterLimit = SkPaintDefaults_MiterLimit;
89e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
90e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    // Zero all bitfields, then set some non-zero defaults.
91f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfieldsUInt           = 0;
92f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fFlags        = SkPaintDefaults_Flags;
93f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fCapType      = kDefault_Cap;
94f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fJoinType     = kDefault_Join;
95f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fTextAlign    = kLeft_Align;
96f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fStyle        = kFill_Style;
97f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fTextEncoding = kUTF8_TextEncoding;
98f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fHinting      = SkPaintDefaults_Hinting;
99e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
100e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fDirtyBits    = 0;
10156c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
102f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    fGenerationID = 0;
103f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1066fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint::SkPaint(const SkPaint& src) {
107e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define COPY(field) field = src.field
108e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define REF_COPY(field) field = SkSafeRef(src.field)
109e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
110e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fTypeface);
111e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fPathEffect);
112e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fShader);
113e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fXfermode);
114e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fMaskFilter);
115e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fColorFilter);
116e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fRasterizer);
117e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fLooper);
118e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fImageFilter);
119e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fAnnotation);
120e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
121e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSize);
122e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextScaleX);
123e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSkewX);
124e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fColor);
125e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fWidth);
126e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fMiterLimit);
127e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fBitfields);
128e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fDirtyBits);
12940078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
13040078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
131e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fGenerationID);
13240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#endif
133e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
134e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef COPY
135e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef REF_COPY
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1386fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint::~SkPaint() {
13982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fTypeface);
14082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fPathEffect);
14182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fShader);
14282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fXfermode);
14382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fMaskFilter);
14482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fColorFilter);
14582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fRasterizer);
14682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fLooper);
14715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    SkSafeUnref(fImageFilter);
148b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    SkSafeUnref(fAnnotation);
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1516fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint& SkPaint::operator=(const SkPaint& src) {
152f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org    if (this == &src) {
153f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org        return *this;
154f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org    }
155f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org
156e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define COPY(field) field = src.field
157e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field)
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
159e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    SkASSERT(&src);
16082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
161e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fTypeface);
162e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fPathEffect);
163e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fShader);
164e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fXfermode);
165e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fMaskFilter);
166e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fColorFilter);
167e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fRasterizer);
168e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fLooper);
169e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fImageFilter);
170e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fAnnotation);
171e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
172e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSize);
173e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextScaleX);
174e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSkewX);
175e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fColor);
176e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fWidth);
177e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fMiterLimit);
178e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fBitfields);
179e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fDirtyBits);
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18156c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
182e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    ++fGenerationID;
183f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *this;
186e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
187e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef COPY
188e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef REF_COPY
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
191b265741cc17f897b349caacdb890119e4111a415robertphillips@google.combool operator==(const SkPaint& a, const SkPaint& b) {
192e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define EQUAL(field) (a.field == b.field)
193ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    // Don't check fGenerationID, which can be different for logically equal paints.
194ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    // fDirtyBits is a very quick check for non-equality, so check it first.
195ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    return EQUAL(fDirtyBits)
196ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein        && EQUAL(fTypeface)
197e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fPathEffect)
198e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fShader)
199e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fXfermode)
200e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fMaskFilter)
201e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fColorFilter)
202e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fRasterizer)
203e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fLooper)
204e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fImageFilter)
205e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fAnnotation)
206e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextSize)
207e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextScaleX)
208e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextSkewX)
209e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fColor)
210e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fWidth)
211e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fMiterLimit)
212f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        && EQUAL(fBitfieldsUInt)
213e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        ;
214e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef EQUAL
215b265741cc17f897b349caacdb890119e4111a415robertphillips@google.com}
216b265741cc17f897b349caacdb890119e4111a415robertphillips@google.com
2176fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::reset() {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint init;
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22056c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
221f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    uint32_t oldGenerationID = fGenerationID;
222f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *this = init;
22456c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
225f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    fGenerationID = oldGenerationID + 1;
226f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
227f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com}
228f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
22956c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
230f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.comuint32_t SkPaint::getGenerationID() const {
231f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    return fGenerationID;
232f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com}
2334bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com
2344bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.comvoid SkPaint::setGenerationID(uint32_t generationID) {
2354bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com    fGenerationID = generationID;
2364bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com}
23760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com#endif
23860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com
239c9683151367b2033a26b1e2ebe6b3902d2064bdbreed@google.comvoid SkPaint::setFilterLevel(FilterLevel level) {
240f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    GEN_ID_INC_EVAL((unsigned) level != fBitfields.fFilterLevel);
241f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fFilterLevel = level;
242c9683151367b2033a26b1e2ebe6b3902d2064bdbreed@google.com}
243c9683151367b2033a26b1e2ebe6b3902d2064bdbreed@google.com
244f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.comvoid SkPaint::setHinting(Hinting hintingLevel) {
245f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    GEN_ID_INC_EVAL((unsigned) hintingLevel != fBitfields.fHinting);
246f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fHinting = hintingLevel;
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2496fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setFlags(uint32_t flags) {
250f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    GEN_ID_INC_EVAL(flags != fBitfields.fFlags);
251f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fFlags = flags;
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2546fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAntiAlias(bool doAA) {
255f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2586fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setDither(bool doDither) {
259f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doDither, kDither_Flag));
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2626fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setSubpixelText(bool doSubpixel) {
263f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2666fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setLCDRenderText(bool doLCDRender) {
267f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
268309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org}
269309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org
2706fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
271f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
272e95c91e6d9201d50d0b84fbc3d2f53f92f753e0bagl@chromium.org}
273e95c91e6d9201d50d0b84fbc3d2f53f92f753e0bagl@chromium.org
2746fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAutohinted(bool useAutohinter) {
275f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
276a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org}
277a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org
2786fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setLinearText(bool doLinearText) {
279f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
282830a23e39bb4a126e573940cd6e354732e295b10reed@google.comvoid SkPaint::setVerticalText(bool doVertical) {
283f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doVertical, kVerticalText_Flag));
284830a23e39bb4a126e573940cd6e354732e295b10reed@google.com}
285830a23e39bb4a126e573940cd6e354732e295b10reed@google.com
2866fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setUnderlineText(bool doUnderline) {
287f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doUnderline, kUnderlineText_Flag));
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2906fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrikeThruText(bool doStrikeThru) {
291f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doStrikeThru, kStrikeThruText_Flag));
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2946fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setFakeBoldText(bool doFakeBold) {
295f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setDevKernText(bool doDevKern) {
299f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
302b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.orgvoid SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
303f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
304b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.org}
305b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.org
3066fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStyle(Style style) {
3076fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)style < kStyleCount) {
308f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        GEN_ID_INC_EVAL((unsigned)style != fBitfields.fStyle);
309f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fStyle = style;
310f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
311a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
312a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
313a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3146fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3176fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setColor(SkColor color) {
318f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(color != fColor);
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColor = color;
320ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, color != SK_ColorBLACK, kColor_DirtyBit);
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3236fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAlpha(U8CPU a) {
324f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
325f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com                                  SkColorGetG(fColor), SkColorGetB(fColor)));
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3286fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
329f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    this->setColor(SkColorSetARGB(a, r, g, b));
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3326fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeWidth(SkScalar width) {
3336fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (width >= 0) {
334f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL(width != fWidth);
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWidth = width;
336ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein        fDirtyBits = SkSetClearMask(fDirtyBits, width != 0, kStrokeWidth_DirtyBit);
337f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
338a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
339a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
340a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3416fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3446fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeMiter(SkScalar limit) {
3456fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (limit >= 0) {
346f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL(limit != fMiterLimit);
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMiterLimit = limit;
348ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein        fDirtyBits = SkSetClearMask(fDirtyBits,
349ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein                                    limit != SkPaintDefaults_MiterLimit,
350ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein                                    kStrokeMiter_DirtyBit);
351f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
352a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
353a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
354a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3556fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3586fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeCap(Cap ct) {
3596fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)ct < kCapCount) {
360f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        GEN_ID_INC_EVAL((unsigned)ct != fBitfields.fCapType);
361f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fCapType = SkToU8(ct);
3626fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
363a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
364a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
365a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3666fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3696fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeJoin(Join jt) {
3706fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)jt < kJoinCount) {
371f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        GEN_ID_INC_EVAL((unsigned)jt != fBitfields.fJoinType);
372f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fJoinType = SkToU8(jt);
3736fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
374a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
375a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
376a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3776fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3826fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextAlign(Align align) {
3836fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)align < kAlignCount) {
384f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        GEN_ID_INC_EVAL((unsigned)align != fBitfields.fTextAlign);
385f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fTextAlign = SkToU8(align);
3866fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
387a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
388a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
389a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3906fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3936fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextSize(SkScalar ts) {
394c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    if (ts >= 0) {
395f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL(ts != fTextSize);
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTextSize = ts;
397ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein        fDirtyBits = SkSetClearMask(fDirtyBits, ts != SkPaintDefaults_TextSize, kTextSize_DirtyBit);
3986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
399a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
400a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextSize() called with negative value\n");
401a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
4026fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4056fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextScaleX(SkScalar scaleX) {
406f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(scaleX != fTextScaleX);
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTextScaleX = scaleX;
408ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, scaleX != SK_Scalar1, kTextScaleX_DirtyBit);
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4116fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextSkewX(SkScalar skewX) {
412f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(skewX != fTextSkewX);
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTextSkewX = skewX;
414ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, skewX != 0, kTextSkewX_DirtyBit);
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4176fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextEncoding(TextEncoding encoding) {
4186fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)encoding <= kGlyphID_TextEncoding) {
419f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        GEN_ID_INC_EVAL((unsigned)encoding != fBitfields.fTextEncoding);
420f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fTextEncoding = encoding;
4216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
422a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
423a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
424a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
4256fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4286fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4306fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkTypeface* SkPaint::setTypeface(SkTypeface* font) {
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fTypeface, font);
432f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC;
433ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, font != NULL, kTypeface_DirtyBit);
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return font;
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4376fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fRasterizer, r);
439f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC;
440ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, r != NULL, kRasterizer_DirtyBit);
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return r;
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4446fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fLooper, looper);
446f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC;
447ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, looper != NULL, kLooper_DirtyBit);
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return looper;
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comSkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
45215356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    SkRefCnt_SafeAssign(fImageFilter, imageFilter);
45315356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    GEN_ID_INC;
454ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, imageFilter != NULL, kImageFilter_DirtyBit);
45515356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    return imageFilter;
45615356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com}
45715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
458b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.comSkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
459b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    SkRefCnt_SafeAssign(fAnnotation, annotation);
460b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    GEN_ID_INC;
461ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, annotation != NULL, kAnnotation_DirtyBit);
462b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    return annotation;
463b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com}
464b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
467ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comstatic SkScalar mag2(SkScalar x, SkScalar y) {
468ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return x * x + y * y;
469ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
470ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
471ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comstatic bool tooBig(const SkMatrix& m, SkScalar ma2max) {
472ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return  mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
473ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            ||
474ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
475ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
476ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
477ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.combool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
478ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkASSERT(!ctm.hasPerspective());
479ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkASSERT(!textM.hasPerspective());
480ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
481ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkMatrix matrix;
482ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    matrix.setConcat(ctm, textM);
483ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return tooBig(matrix, MaxCacheSize2());
484ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
485ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
486ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
487ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com///////////////////////////////////////////////////////////////////////////////
488ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGlyphCache.h"
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
49290808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.comstatic void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
49390808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                           void* context) {
49490808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
495f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com}
496f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkPaint::textToGlyphs(const void* textData, size_t byteLength,
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          uint16_t glyphs[]) const {
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (byteLength == 0) {
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
50272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(textData != NULL);
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == glyphs) {
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        switch (this->getTextEncoding()) {
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kUTF8_TextEncoding:
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkUTF8_CountUnichars((const char*)textData, byteLength);
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kUTF16_TextEncoding:
5102cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
51168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case kUTF32_TextEncoding:
5122cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkToInt(byteLength >> 2);
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kGlyphID_TextEncoding:
5142cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkToInt(byteLength >> 1);
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
5160c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
52072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we get here, we have a valid glyphs[] array, so time to fill it in
52272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // handle this encoding before the setup for the glyphcache
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we want to ignore the low bit of byteLength
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(glyphs, textData, byteLength >> 1 << 1);
5272cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org        return SkToInt(byteLength >> 1);
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
52972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
530532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*    cache = autoCache.getCache();
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = text + byteLength;
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t*   gptr = glyphs;
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (this->getTextEncoding()) {
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkPaint::kUTF8_TextEncoding:
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkPaint::kUTF16_TextEncoding: {
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint16_t* text16 = (const uint16_t*)text;
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint16_t* stop16 = (const uint16_t*)stop;
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text16 < stop16) {
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
55168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case kUTF32_TextEncoding: {
55268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* text32 = (const int32_t*)text;
55368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* stop32 = (const int32_t*)stop;
55468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            while (text32 < stop32) {
55568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                *gptr++ = cache->unicharToGlyph(*text32++);
55668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            }
55768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            break;
55868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        }
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
5600c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5622cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org    return SkToInt(gptr - glyphs);
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
565a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.combool SkPaint::containsText(const void* textData, size_t byteLength) const {
566a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    if (0 == byteLength) {
567a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        return true;
568a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
56972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
570a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    SkASSERT(textData != NULL);
57172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
572a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    // handle this encoding before the setup for the glyphcache
573a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
574a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
575a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        size_t count = byteLength >> 1;
576a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        for (size_t i = 0; i < count; i++) {
577a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            if (0 == glyphID[i]) {
578a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                return false;
579a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
580a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
581a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        return true;
582a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
58372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
584532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
585a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    SkGlyphCache*    cache = autoCache.getCache();
586a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com
587a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    switch (this->getTextEncoding()) {
588a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        case SkPaint::kUTF8_TextEncoding: {
589a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const char* text = static_cast<const char*>(textData);
590a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const char* stop = text + byteLength;
591a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            while (text < stop) {
592a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
593a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                    return false;
594a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                }
595a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
596a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            break;
597a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
598a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        case SkPaint::kUTF16_TextEncoding: {
599a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const uint16_t* text = static_cast<const uint16_t*>(textData);
600a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const uint16_t* stop = text + (byteLength >> 1);
601a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            while (text < stop) {
602a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
603a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                    return false;
604a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                }
605a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
606a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            break;
607a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
60868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case SkPaint::kUTF32_TextEncoding: {
60968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* text = static_cast<const int32_t*>(textData);
61068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* stop = text + (byteLength >> 2);
61168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            while (text < stop) {
61268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                if (0 == cache->unicharToGlyph(*text++)) {
61368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                    return false;
61468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                }
61568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            }
61668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            break;
61768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        }
618a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        default:
6190c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
620a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            return false;
621a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
622a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    return true;
623a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com}
624a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com
6259d3a985aa3c82605346ed1518375a8c384b925e5reed@android.comvoid SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
6269d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com                               SkUnichar textData[]) const {
6279d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    if (count <= 0) {
6289d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com        return;
6299d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    }
6309d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
6319d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkASSERT(glyphs != NULL);
6329d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkASSERT(textData != NULL);
6339d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
634532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
6359d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkGlyphCache*    cache = autoCache.getCache();
6369d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
6379d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    for (int index = 0; index < count; index++) {
6389d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com        textData[index] = cache->glyphToUnichar(glyphs[index]);
6399d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    }
6409d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com}
6419d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6446fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
6456fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
64872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6526fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
6536fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
65672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6606fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
6616fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
664fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6686fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
6696fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
672fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
67768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
67868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
67968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
68068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
68168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
68268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
68368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
68468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharMetrics(uni);
68568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
68668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
68768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_prev(SkGlyphCache* cache,
68868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
68968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
69068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
691fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
69268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
69368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *--ptr;
69468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
69568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharMetrics(uni);
69668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
69768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
6986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
6996fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
70272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID);
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7106fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
7116fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
71472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr -= 1;
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID);
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7226fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
7236fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
72672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7306fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
7316fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
73472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7386fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
7396fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
74272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
7476fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
75072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
75468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
75568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
75668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
75768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
758fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
75968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
76068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
76168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
76268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharAdvance(uni);
76368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
76468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
76568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getAdvance_utf32_prev(SkGlyphCache* cache,
76668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
76768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
76868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
769fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
77068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
77168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *--ptr;
77268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
77368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharAdvance(uni);
77468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
77568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
7766fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
7776fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
78072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDAdvance(glyphID);
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7886fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
7896fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
79272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr -= 1;
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDAdvance(glyphID);
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
8016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                                bool needFullMetrics) const {
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const SkMeasureCacheProc gMeasureCacheProcs[] = {
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_next,
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_next,
80568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_next,
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_next,
80772cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_prev,
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_prev,
81068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_prev,
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_prev,
81272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf8_next,
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf16_next,
81568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getAdvance_utf32_next,
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_glyph_next,
81772cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf8_prev,
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf16_prev,
82068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getAdvance_utf32_prev,
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_glyph_prev
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
82372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned index = this->getTextEncoding();
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8266fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (kBackward_TextBufferDirection == tbd) {
82768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        index += 4;
8286fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
8296fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!needFullMetrics && !this->isDevKernText()) {
83068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        index += 8;
8316fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return gMeasureCacheProcs[index];
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
8406fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                        const char** text, SkFixed, SkFixed) {
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
84372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
8486fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                    const char** text, SkFixed x, SkFixed y) {
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
85172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8556fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
8566fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                        const char** text, SkFixed, SkFixed) {
8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
85972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
8646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                     const char** text, SkFixed x, SkFixed y) {
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
86772cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    x, y);
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
87268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
87368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                    const char** text, SkFixed, SkFixed) {
87468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
87568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
876fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
87768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
87868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
87968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
88068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharMetrics(uni);
88168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
88268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
88368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
88468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                    const char** text, SkFixed x, SkFixed y) {
88568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
88668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
887fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
88868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
889584f337832d585e23037e59517f7bcc420424692commit-bot@chromium.org    SkUnichar uni = *ptr++;
89068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
8918d38d516c0f17d8d9f6b170055ac05ac181c0554sugoi@google.com    return cache->getUnicharMetrics(uni, x, y);
89268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
89368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
8946fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
8956fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                         const char** text, SkFixed, SkFixed) {
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
89872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID);
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
9076fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                     const char** text, SkFixed x, SkFixed y) {
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
91072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID, x, y);
9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9186fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkDrawCacheProc SkPaint::getDrawCacheProc() const {
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const SkDrawCacheProc gDrawCacheProcs[] = {
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_00,
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_00,
92268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_00,
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_00,
92472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_xy,
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_xy,
92768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_xy,
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_xy
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
93072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned index = this->getTextEncoding();
932f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    if (fBitfields.fFlags & kSubpixelText_Flag) {
93368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        index += 4;
9346fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
93572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return gDrawCacheProcs[index];
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
942ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com#define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE (   \
943ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kDevKernText_Flag          |       \
944ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kLinearText_Flag           |       \
945ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kLCDRenderText_Flag        |       \
946ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kEmbeddedBitmapText_Flag   |       \
947ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kAutoHinting_Flag          |       \
948ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kGenA8FromLCD_Flag )
949ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
950ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkScalar SkPaint::setupForAsPaths() {
951ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    uint32_t flags = this->getFlags();
952ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // clear the flags we don't care about
953ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
954ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // set the flags we do care about
955ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    flags |= SkPaint::kSubpixelText_Flag;
9568f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
957ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setFlags(flags);
958ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setHinting(SkPaint::kNo_Hinting);
9598f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
960ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar textSize = fTextSize;
961ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setTextSize(kCanonicalTextSizeForPaths);
962ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return textSize / kCanonicalTextSizeForPaths;
963ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
964ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
965ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comclass SkCanonicalizePaint {
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
967ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
968c4b84aef1adeb68bc853f35abb85b79fa1fcaac6rmistry        if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) {
969ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            SkPaint* p = fLazy.set(paint);
970ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            fScale = p->setupForAsPaths();
971ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            fPaint = p;
972ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        }
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9746fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com
975ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& getPaint() const { return *fPaint; }
9768f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
977ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    /**
978ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     *  Returns 0 if the paint was unmodified, or the scale factor need to
979ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     *  the original textSize
980ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     */
981ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar getScale() const { return fScale; }
98272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
984ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint*   fPaint;
985ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar         fScale;
986ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkTLazy<SkPaint> fLazy;
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9896fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic void set_bounds(const SkGlyph& g, SkRect* bounds) {
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->set(SkIntToScalar(g.fLeft),
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fTop),
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fLeft + g.fWidth),
9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fTop + g.fHeight));
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
996e88f551b38c2893566b7016d906b1455e43542f5reed@android.com// 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
997e88f551b38c2893566b7016d906b1455e43542f5reed@android.com// we don't overflow along the way
998e88f551b38c2893566b7016d906b1455e43542f5reed@android.comtypedef int64_t Sk48Dot16;
999e88f551b38c2893566b7016d906b1455e43542f5reed@android.com
10008f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.comstatic inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
10018f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com    return (float) (x * 1.5258789e-5);   // x * (1 / 65536.0f)
10028f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com}
1003e88f551b38c2893566b7016d906b1455e43542f5reed@android.com
100444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
1005e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    SkScalar sx = Sk48Dot16ToScalar(dx);
10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->join(SkIntToScalar(g.fLeft) + sx,
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fTop),
10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fLeft + g.fWidth) + sx,
10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fTop + g.fHeight));
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
101244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
101344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    SkScalar sy = Sk48Dot16ToScalar(dy);
101444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    bounds->join(SkIntToScalar(g.fLeft),
101544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fTop) + sy,
101644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fLeft + g.fWidth),
101744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fTop + g.fHeight) + sy);
101844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com}
101944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
102044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comtypedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
102144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
102244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com// xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
102344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic SkFixed advance(const SkGlyph& glyph, int xyIndex) {
102444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    SkASSERT(0 == xyIndex || 1 == xyIndex);
102544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    return (&glyph.fAdvanceX)[xyIndex];
102644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com}
102744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkPaint::measure_text(SkGlyphCache* cache,
10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               const char* text, size_t byteLength,
10306fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                               int* count, SkRect* bounds) const {
10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count);
10326fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (byteLength == 0) {
10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *count = 0;
10346fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (bounds) {
10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bounds->setEmpty();
10366fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMeasureCacheProc glyphCacheProc;
10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
104249f085dddff10473b6ebf832a974288300224e60bsalomon                                               bounds);
10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
104444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    int xyIndex;
104544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    JoinBoundsProc joinBoundsProc;
104644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    if (this->isVerticalText()) {
104744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        xyIndex = 1;
104844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        joinBoundsProc = join_bounds_y;
104944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    } else {
105044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        xyIndex = 0;
105144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        joinBoundsProc = join_bounds_x;
105244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    }
105344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int         n = 1;
10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = (const char*)text + byteLength;
10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph* g = &glyphCacheProc(cache, &text);
1057e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // our accumulated fixed-point advances might overflow 16.16, so we use
1058e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // a 48.16 (64bit) accumulator, and then convert that to scalar at the
1059e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // very end.
106044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    Sk48Dot16 x = advance(*g, xyIndex);
10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoKern  autokern;
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == bounds) {
10656fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (this->isDevKernText()) {
10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rsb;
10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rsb = g->fRsbDelta;
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
107044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10726fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
107444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(glyphCacheProc(cache, &text), xyIndex);
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10776fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        set_bounds(*g, bounds);
10796fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (this->isDevKernText()) {
10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rsb;
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rsb = g->fRsbDelta;
10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
108544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                joinBoundsProc(*g, bounds, x);
108644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(*g, xyIndex);
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10886fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
109144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                joinBoundsProc(*g, bounds, x);
109244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(*g, xyIndex);
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text == stop);
10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *count = n;
1099e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    return Sk48Dot16ToScalar(x);
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
110299ae881a7f55a03c2b16fb5704e6e90ea86d965dreedSkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const {
11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL || length == 0);
11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1106ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1107ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1108ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
110972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
111099ae881a7f55a03c2b16fb5704e6e90ea86d965dreed    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar width = 0;
111472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
11156fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (length > 0) {
11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int tempCount;
11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1118ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        width = paint.measure_text(cache, text, length, &tempCount, bounds);
11196fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (scale) {
11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            width = SkScalarMul(width, scale);
11216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if (bounds) {
11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fTop = SkScalarMul(bounds->fTop, scale);
11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fRight = SkScalarMul(bounds->fRight, scale);
11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
112846348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com    } else if (bounds) {
112946348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com        // ensure that even if we don't measure_text we still update the bounds
113046348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com        bounds->setEmpty();
11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return width;
11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef bool (*SkTextBufferPred)(const char* text, const char* stop);
11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11376fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool forward_textBufferPred(const char* text, const char* stop) {
11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return text < stop;
11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11416fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool backward_textBufferPred(const char* text, const char* stop) {
11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return text > stop;
11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
11466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                             const char** text, size_t length,
11476fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                             const char** stop) {
11486fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (SkPaint::kForward_TextBufferDirection == tbd) {
11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *stop = *text + length;
11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return forward_textBufferPred;
11516fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // text should point to the end of the buffer, and stop to the beginning
11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *stop = *text;
11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *text += length;
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return backward_textBufferPred;
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comsize_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          SkScalar* measuredWidth,
11616fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                          TextBufferDirection tbd) const {
11626fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (0 == length || 0 >= maxWidth) {
11636fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (measuredWidth) {
11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *measuredWidth = 0;
11656fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1169c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    if (0 == fTextSize) {
1170c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        if (measuredWidth) {
1171c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com            *measuredWidth = 0;
1172c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        }
1173c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        return length;
1174c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    }
1175c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com
11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(textD != NULL);
11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textD;
11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1179ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1180ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1181ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1183ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // adjust max in case we changed the textSize in paint
1184ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    if (scale) {
1185ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        maxWidth /= scale;
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
118772cf4927e503f49c4bd07369e85764ddde57071breed@google.com
1188ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1191ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false);
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char*      stop;
11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
1194ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const int        xyIndex = paint.isVerticalText() ? 1 : 0;
1195e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // use 64bits for our accumulator, to avoid overflowing 16.16
1196e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    Sk48Dot16        max = SkScalarToFixed(maxWidth);
1197e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    Sk48Dot16        width = 0;
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoKern  autokern;
12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (this->isDevKernText()) {
12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int rsb = 0;
12036fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        while (pred(text, stop)) {
12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const char* curr = text;
12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const SkGlyph& g = glyphCacheProc(cache, &text);
120644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com            SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
12076fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if ((width += x) > max) {
12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                width -= x;
12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                text = curr;
12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            rsb = g.fRsbDelta;
12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12146fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
12156fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        while (pred(text, stop)) {
12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const char* curr = text;
121744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com            SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
12186fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if ((width += x) > max) {
12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                width -= x;
12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                text = curr;
12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
122572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
12266fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (measuredWidth) {
1227e88f551b38c2893566b7016d906b1455e43542f5reed@android.com        SkScalar scalarWidth = Sk48Dot16ToScalar(width);
12286fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (scale) {
12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            scalarWidth = SkScalarMul(scalarWidth, scale);
12306fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *measuredWidth = scalarWidth;
12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
123372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return the number of bytes measured
12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (kForward_TextBufferDirection == tbd) ?
12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                text - stop + length : stop - text + length;
12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12416fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
12420a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com    *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;   // don't detach the cache
12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
124690808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.comstatic void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
124790808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                                void* context) {
124890808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12516fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1252ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1253ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1254ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
12558f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
12566fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    SkMatrix zoomMatrix, *zoomPtr = NULL;
12576fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (zoom) {
12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        zoomMatrix.setScale(zoom, zoom);
12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        zoomPtr = &zoomMatrix;
12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    FontMetrics storage;
12636fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == metrics) {
12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics = &storage;
12656fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
126672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
1267ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12696fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (scale) {
12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fTop = SkScalarMul(metrics->fTop, scale);
12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
12750a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
12760a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
12770a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
12780a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
12790bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org        metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
12800bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org        metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return metrics->fDescent - metrics->fAscent + metrics->fLeading;
12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12856fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12876fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->set(g.fLeft * scale,
12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g.fTop * scale,
12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (g.fLeft + g.fWidth) * scale,
12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (g.fTop + g.fHeight) * scale);
12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12946fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comint SkPaint::getTextWidths(const void* textData, size_t byteLength,
12956fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                           SkScalar widths[], SkRect bounds[]) const {
12966fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (0 == byteLength) {
12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
12986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
130049f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(textData);
13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13026fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == widths && NULL == bounds) {
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->countText(textData, byteLength);
13046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1306ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1307ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1308ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1310ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMeasureCacheProc  glyphCacheProc;
1313ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
131449f085dddff10473b6ebf832a974288300224e60bsalomon                                               bounds);
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = text + byteLength;
13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int         count = 0;
1319ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const int   xyIndex = paint.isVerticalText() ? 1 : 0;
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (this->isDevKernText()) {
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we adjust the widths returned here through auto-kerning
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoKern  autokern;
13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkFixed     prevWidth = 0;
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (scale) {
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkFixed  adjust = autokern.adjust(g);
13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if (count > 0) {
13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        SkScalar w = SkFixedToScalar(prevWidth + adjust);
13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        *widths++ = SkScalarMul(w, scale);
13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
133644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    prevWidth = advance(g, xyIndex);
13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++, scale);
13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count > 0 && widths) {
13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkFixed  adjust = autokern.adjust(g);
13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if (count > 0) {
13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        *widths++ = SkFixedToScalar(prevWidth + adjust);
13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
135544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    prevWidth = advance(g, xyIndex);
13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++);
13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count > 0 && widths) {
13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *widths = SkFixedToScalar(prevWidth);
13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no devkern
13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (scale) {
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
137144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            scale);
13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++, scale);
13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
138344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    *widths++ = SkFixedToScalar(advance(g, xyIndex));
13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++);
13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text == stop);
13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13976fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::getTextPath(const void* textData, size_t length,
14026fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                          SkScalar x, SkScalar y, SkPath* path) const {
14036fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    SkASSERT(length == 0 || textData != NULL);
14046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com
14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
14066fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (text == NULL || length == 0 || path == NULL) {
14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
14086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1410166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    SkTextToPathIter    iter(text, length, *this, false);
14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix            matrix;
14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar            prevXPos = 0;
14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setScale(iter.getPathScale(), iter.getPathScale());
14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.postTranslate(x, y);
14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path->reset();
14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar        xpos;
14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPath*   iterPath;
14207b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    while (iter.next(&iterPath, &xpos)) {
14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        matrix.postTranslate(xpos - prevXPos, 0);
14227b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (iterPath) {
14237b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            path->addPath(*iterPath, matrix);
14247b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prevXPos = xpos;
14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1429ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.comvoid SkPaint::getPosTextPath(const void* textData, size_t length,
1430ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com                             const SkPoint pos[], SkPath* path) const {
1431ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkASSERT(length == 0 || textData != NULL);
1432ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1433ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    const char* text = (const char*)textData;
1434ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    if (text == NULL || length == 0 || path == NULL) {
1435ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        return;
1436ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    }
1437ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1438ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkTextToPathIter    iter(text, length, *this, false);
1439ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkMatrix            matrix;
1440ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkPoint             prevPos;
1441ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    prevPos.set(0, 0);
1442ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1443ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1444ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    path->reset();
1445ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1446ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    unsigned int    i = 0;
1447ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    const SkPath*   iterPath;
14487b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    while (iter.next(&iterPath, NULL)) {
1449ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
14507b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (iterPath) {
14517b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            path->addPath(*iterPath, matrix);
14527b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
1453ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        prevPos = pos[i];
1454ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        i++;
1455ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    }
1456ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com}
1457ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void add_flattenable(SkDescriptor* desc, uint32_t tag,
14598b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org                            SkWriteBuffer* buffer) {
14608b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
14618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14632739b27d7d13691603d07982ff0d6dd0658bd364reed@google.com// SkFontHost can override this choice in FilterRec()
14646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic SkMask::Format computeMaskFormat(const SkPaint& paint) {
14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t flags = paint.getFlags();
14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1467b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org    // Antialiasing being disabled trumps all other settings.
146865dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    if (!(flags & SkPaint::kAntiAlias_Flag)) {
1469b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org        return SkMask::kBW_Format;
1470f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com    }
1471f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com
147265dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    if (flags & SkPaint::kLCDRenderText_Flag) {
1473f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        return SkMask::kLCD16_Format;
147465dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    }
1475b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org
1476b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org    return SkMask::kA8_Format;
14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14791cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com// if linear-text is on, then we force hinting to be off (since that's sort of
14801cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com// the point of linear-text.
14811cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.comstatic SkPaint::Hinting computeHinting(const SkPaint& paint) {
14821cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    SkPaint::Hinting h = paint.getHinting();
14831cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    if (paint.isLinearText()) {
14841cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        h = SkPaint::kNo_Hinting;
14851cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    }
14861cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    return h;
14871cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com}
14881cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com
14891f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com// return true if the paint is just a single color (i.e. not a shader). If its
14901f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com// a shader, then we can't compute a const luminance for it :(
14911f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.comstatic bool justAColor(const SkPaint& paint, SkColor* color) {
14928367b8cb7a6b2f163ee41365323cb219b7049b15reed    SkColor c = paint.getColor();
14938367b8cb7a6b2f163ee41365323cb219b7049b15reed
14948367b8cb7a6b2f163ee41365323cb219b7049b15reed    SkShader* shader = paint.getShader();
14958367b8cb7a6b2f163ee41365323cb219b7049b15reed    if (shader && !shader->asLuminanceColor(&c)) {
14961f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        return false;
14971f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
14981f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    if (paint.getColorFilter()) {
14991f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        c = paint.getColorFilter()->filterColor(c);
15001f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
15011f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    if (color) {
15021f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        *color = c;
15031f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
15041f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    return true;
15051f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com}
15061f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com
1507ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.comstatic SkColor computeLuminanceColor(const SkPaint& paint) {
1508ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    SkColor c;
1509ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    if (!justAColor(paint, &c)) {
1510ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com        c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1511ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    }
1512ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    return c;
1513ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com}
1514813d38b7a07957f2990ccca52ddab55fe0b1c632reed@google.com
1515dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com#define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
1516dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com
15174f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com// Beyond this size, LCD doesn't appreciably improve quality, but it always
15184f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com// cost more RAM and draws slower, so we set a cap.
1519c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com#ifndef SK_MAX_SIZE_FOR_LCDTEXT
1520c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com    #define SK_MAX_SIZE_FOR_LCDTEXT    48
1521c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com#endif
15224f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com
15234f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.comstatic bool tooBigForLCD(const SkScalerContext::Rec& rec) {
1524e78f7cfced5787f741d0e1a4911b2bea2dfa2f02commit-bot@chromium.org    SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
1525e78f7cfced5787f741d0e1a4911b2bea2dfa2f02commit-bot@chromium.org                    rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
1526e78f7cfced5787f741d0e1a4911b2bea2dfa2f02commit-bot@chromium.org    SkScalar size = SkScalarSqrt(SkScalarAbs(area)) * rec.fTextSize;
1527e78f7cfced5787f741d0e1a4911b2bea2dfa2f02commit-bot@chromium.org    return size > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
15284f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com}
15294f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com
153072cf4927e503f49c4bd07369e85764ddde57071breed@google.com/*
153172cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  Return the scalar with only limited fractional precision. Used to consolidate matrices
153272cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  that vary only slightly when we create our key into the font cache, since the font scaler
153372cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  typically returns the same looking resuts for tiny changes in the matrix.
153472cf4927e503f49c4bd07369e85764ddde57071breed@google.com */
1535f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comstatic SkScalar sk_relax(SkScalar x) {
1536f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int n = sk_float_round2int(x * 1024);
1537f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    return n / 1024.0f;
1538f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
1539f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
154036a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.comvoid SkScalerContext::MakeRec(const SkPaint& paint,
1541532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              const SkDeviceProperties* deviceProperties,
1542532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              const SkMatrix* deviceMatrix,
1543532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              Rec* rec) {
15448d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com    SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
15458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1546cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    SkTypeface* typeface = paint.getTypeface();
1547cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    if (NULL == typeface) {
1548cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com        typeface = SkTypeface::GetDefaultTypeface();
1549cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    }
1550ec730b9cafaa3b2a4df7e7ceb3ab50601796fbe5bungeman    rec->fFontID = typeface->uniqueID();
15518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fTextSize = paint.getTextSize();
15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fPreScaleX = paint.getTextScaleX();
15538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fPreSkewX  = paint.getTextSkewX();
15548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15556fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (deviceMatrix) {
1556f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1557f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1558f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1559f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
15606fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
15618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
15628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
15638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
156472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
15658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint::Style  style = paint.getStyle();
15668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar        strokeWidth = paint.getStrokeWidth();
156772cf4927e503f49c4bd07369e85764ddde57071breed@google.com
1568ffe49f5380dd5062073efeda70f2f91682c828careed@google.com    unsigned flags = 0;
15694526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org
15706fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isFakeBoldText()) {
15714526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#ifdef SK_USE_FREETYPE_EMBOLDEN
15724526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org        flags |= SkScalerContext::kEmbolden_Flag;
15734526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#else
157428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
157528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpKeys,
157628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpValues,
157728be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpLength);
15788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
157972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
15806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (style == SkPaint::kFill_Style) {
15818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            style = SkPaint::kStrokeAndFill_Style;
15828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
15836fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strokeWidth += extra;
15856fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
15864526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#endif
15878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15896fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isDevKernText()) {
15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkScalerContext::kDevKernText_Flag;
15916fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
159272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
15936fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (style != SkPaint::kFill_Style && strokeWidth > 0) {
15948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fFrameWidth = strokeWidth;
15958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fMiterLimit = paint.getStrokeMiter();
15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (style == SkPaint::kStrokeAndFill_Style) {
15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkScalerContext::kFrameAndFill_Flag;
16006fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
16016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
16028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fFrameWidth = 0;
16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fMiterLimit = 0;
16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fStrokeJoin = 0;
16058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
160702b5331078861b02b61e9a93f845617a7c900409reed@google.com    rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
160802b5331078861b02b61e9a93f845617a7c900409reed@google.com
1609532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) {
16104a8126e7f81384526629b1e21bf89b632ea13cd9reed        if (tooBigForLCD(*rec)) {
161102b5331078861b02b61e9a93f845617a7c900409reed@google.com            rec->fMaskFormat = SkMask::kA8_Format;
16124a8126e7f81384526629b1e21bf89b632ea13cd9reed            flags |= SkScalerContext::kGenA8FromLCD_Flag;
161302b5331078861b02b61e9a93f845617a7c900409reed@google.com        } else {
16144a8126e7f81384526629b1e21bf89b632ea13cd9reed            SkPixelGeometry geometry = deviceProperties
16154a8126e7f81384526629b1e21bf89b632ea13cd9reed                                     ? deviceProperties->fPixelGeometry
16164a8126e7f81384526629b1e21bf89b632ea13cd9reed                                     : SkSurfacePropsDefaultPixelGeometry();
16174a8126e7f81384526629b1e21bf89b632ea13cd9reed            switch (geometry) {
16184a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kUnknown_SkPixelGeometry:
16194a8126e7f81384526629b1e21bf89b632ea13cd9reed                    // eeek, can't support LCD
16204a8126e7f81384526629b1e21bf89b632ea13cd9reed                    rec->fMaskFormat = SkMask::kA8_Format;
16214a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kGenA8FromLCD_Flag;
16224a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
16234a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kRGB_H_SkPixelGeometry:
16244a8126e7f81384526629b1e21bf89b632ea13cd9reed                    // our default, do nothing.
16254a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
16264a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kBGR_H_SkPixelGeometry:
16274a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
16284a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
16294a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kRGB_V_SkPixelGeometry:
16304a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kLCD_Vertical_Flag;
16314a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
16324a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kBGR_V_SkPixelGeometry:
16334a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kLCD_Vertical_Flag;
16344a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
16354a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
163602b5331078861b02b61e9a93f845617a7c900409reed@google.com            }
163702b5331078861b02b61e9a93f845617a7c900409reed@google.com        }
163802b5331078861b02b61e9a93f845617a7c900409reed@google.com    }
163902b5331078861b02b61e9a93f845617a7c900409reed@google.com
16406fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isEmbeddedBitmapText()) {
164102b5331078861b02b61e9a93f845617a7c900409reed@google.com        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
16426fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
16436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isSubpixelText()) {
164402b5331078861b02b61e9a93f845617a7c900409reed@google.com        flags |= SkScalerContext::kSubpixelPositioning_Flag;
16456fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
16466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isAutohinted()) {
1647f6f56878bc96386882721b15ba610984185d3dc9bungeman@google.com        flags |= SkScalerContext::kForceAutohinting_Flag;
16486fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
1649830a23e39bb4a126e573940cd6e354732e295b10reed@google.com    if (paint.isVerticalText()) {
1650830a23e39bb4a126e573940cd6e354732e295b10reed@google.com        flags |= SkScalerContext::kVertical_Flag;
1651830a23e39bb4a126e573940cd6e354732e295b10reed@google.com    }
16528351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
16538351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com        flags |= SkScalerContext::kGenA8FromLCD_Flag;
16548351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com    }
165502b5331078861b02b61e9a93f845617a7c900409reed@google.com    rec->fFlags = SkToU16(flags);
165636a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com
1657ffe49f5380dd5062073efeda70f2f91682c828careed@google.com    // these modify fFlags, so do them after assigning fFlags
16589d7576724cf9602ff778b18126e0fef0ab3d3bf2reed@google.com    rec->setHinting(computeHinting(paint));
165997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
1660ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    rec->setLuminanceColor(computeLuminanceColor(paint));
1661532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1662532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    if (NULL == deviceProperties) {
1663532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1664532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        rec->setPaintGamma(SK_GAMMA_EXPONENT);
1665532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    } else {
16664a8126e7f81384526629b1e21bf89b632ea13cd9reed        rec->setDeviceGamma(deviceProperties->getGamma());
1667532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1668532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //For now always set the paint gamma equal to the device gamma.
1669532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //The math in SkMaskGamma can handle them being different,
1670532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //but it requires superluminous masks when
1671532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
16724a8126e7f81384526629b1e21bf89b632ea13cd9reed        rec->setPaintGamma(deviceProperties->getGamma());
1673532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    }
1674532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1675532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com#ifdef SK_GAMMA_CONTRAST
1676532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    rec->setContrast(SK_GAMMA_CONTRAST);
1677ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com#else
1678532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    /**
1679532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
1680532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * With lower values small text appears washed out (though correctly so).
1681532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * With higher values lcd fringing is worse and the smoothing effect of
1682532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * partial coverage is diminished.
1683532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     */
16844b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    rec->setContrast(0.5f);
1685ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com#endif
1686532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
16872bf82d843d8896dd10bb86adc1e974c6d52324e6bungeman@google.com    rec->fReservedAlign = 0;
1688fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
168936a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com    /*  Allow the fonthost to modify our rec before we use it as a key into the
169036a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        cache. This way if we're asking for something that they will ignore,
169136a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        they can modify our rec up front, so we don't create duplicate cache
169236a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        entries.
169336a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com     */
1694fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com    typeface->onFilterRec(rec);
16953e8ae5b457558435218a864dd0e852f83abfe802reed@google.com
169610d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    // be sure to call PostMakeRec(rec) before you actually use it!
169710d2d4d1062ef56526f187e6716c5e747689b598reed@google.com}
169810d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
169910d2d4d1062ef56526f187e6716c5e747689b598reed@google.com/**
170097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
170197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
170297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * to hold it until the returned pointer is refed or forgotten.
170310d2d4d1062ef56526f187e6716c5e747689b598reed@google.com */
170497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comSK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
170510d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
1706ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.comstatic SkMaskGamma* gLinearMaskGamma = NULL;
1707b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkMaskGamma* gMaskGamma = NULL;
1708b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gContrast = SK_ScalarMin;
1709b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gPaintGamma = SK_ScalarMin;
1710b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gDeviceGamma = SK_ScalarMin;
171197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
171297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
171397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * the returned SkMaskGamma pointer is refed or forgotten.
171497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
1715a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comstatic const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
1716b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein    gMaskGammaCacheMutex.assertHeld();
1717ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1718ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com        if (NULL == gLinearMaskGamma) {
1719ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com            gLinearMaskGamma = SkNEW(SkMaskGamma);
1720ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com        }
1721a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        return *gLinearMaskGamma;
1722ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    }
172397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
172497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        SkSafeUnref(gMaskGamma);
1725b1a72cb90a9b515978bc9abda1f267f31a544e08bungeman@google.com        gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
172697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gContrast = contrast;
172797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gPaintGamma = paintGamma;
172897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gDeviceGamma = deviceGamma;
172997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    }
1730a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    return *gMaskGamma;
173197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com}
173297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
1733b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com/*static*/ void SkPaint::Term() {
1734b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1735b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com
1736ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    SkSafeUnref(gLinearMaskGamma);
17375987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com    gLinearMaskGamma = NULL;
1738b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkSafeUnref(gMaskGamma);
17395987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com    gMaskGamma = NULL;
1740b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gContrast = SK_ScalarMin;)
1741b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
1742b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
1743b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com}
1744b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com
174597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
174697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com *  We ensure that the rec is self-consistent and efficient (where possible)
174797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
17488d38d516c0f17d8d9f6b170055ac05ac181c0554sugoi@google.comvoid SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
174910d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    /**
175010d2d4d1062ef56526f187e6716c5e747689b598reed@google.com     *  If we're asking for A8, we force the colorlum to be gray, since that
175197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com     *  limits the number of unique entries, and the scaler will only look at
175297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com     *  the lum of one of them.
175310d2d4d1062ef56526f187e6716c5e747689b598reed@google.com     */
1754dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com    switch (rec->fMaskFormat) {
1755dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kLCD16_Format:
1756dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kLCD32_Format: {
1757dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // filter down the luminance color to a finite number of bits
175897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            SkColor color = rec->getLuminanceColor();
1759b5715a1c8003e4a8af2301ab44aeef043547808ereed@google.com            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1760dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
1761dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        }
1762dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kA8_Format: {
1763dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // filter down the luminance to a single component, since A8 can't
1764dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // use per-component information
176597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            SkColor color = rec->getLuminanceColor();
1766dc1cf66483e93c2d12d938bc1ce3b8c60cc68da5jvanverth            U8CPU lum = SkComputeLuminance(SkColorGetR(color),
1767dc1cf66483e93c2d12d938bc1ce3b8c60cc68da5jvanverth                                           SkColorGetG(color),
1768dc1cf66483e93c2d12d938bc1ce3b8c60cc68da5jvanverth                                           SkColorGetB(color));
1769dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // reduce to our finite number of bits
177097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            color = SkColorSetRGB(lum, lum, lum);
1771b5715a1c8003e4a8af2301ab44aeef043547808ereed@google.com            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1772dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
1773dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        }
1774dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kBW_Format:
1775dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // No need to differentiate gamma if we're BW
1776532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com            rec->ignorePreBlend();
1777dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
17783e8ae5b457558435218a864dd0e852f83abfe802reed@google.com    }
17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
17818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MIN_SIZE_FOR_EFFECT_BUFFER  1024
17828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178317fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#ifdef SK_DEBUG
178417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com    #define TEST_DESC
178517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#endif
178617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com
1787ffe49f5380dd5062073efeda70f2f91682c828careed@google.com/*
1788ffe49f5380dd5062073efeda70f2f91682c828careed@google.com *  ignoreGamma tells us that the caller just wants metrics that are unaffected
17892d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth *  by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
17902d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth *  contrast = 0, luminanceColor = transparent black.
1791ffe49f5380dd5062073efeda70f2f91682c828careed@google.com */
1792532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.comvoid SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
1793532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                             const SkMatrix* deviceMatrix,
179490808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                             void (*proc)(SkTypeface*, const SkDescriptor*, void*),
179557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com                             void* context, bool ignoreGamma) const {
17968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalerContext::Rec    rec;
17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1798532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
179957f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    if (ignoreGamma) {
18002d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        rec.ignorePreBlend();
180157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    }
18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t          descSize = sizeof(rec);
18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int             entryCount = 1;
18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect*   pe = this->getPathEffect();
18068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMaskFilter*   mf = this->getMaskFilter();
18078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRasterizer*   ra = this->getRasterizer();
18088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18098b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkWriteBuffer    peBuffer, mfBuffer, raBuffer;
18108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (pe) {
18128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        peBuffer.writeFlattenable(pe);
18138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org        descSize += peBuffer.bytesWritten();
18148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
18158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
18168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // seems like we could support kLCD as well at this point...
18178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mf) {
18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        mfBuffer.writeFlattenable(mf);
18208b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org        descSize += mfBuffer.bytesWritten();
18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
1823a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        /* Pre-blend is not currently applied to filtered text.
1824a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           The primary filter is blur, for which contrast makes no sense,
1825a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           and for which the destination guess error is more visible.
1826a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           Also, all existing users of blur have calibrated for linear. */
1827a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        rec.ignorePreBlend();
18288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (ra) {
18308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        raBuffer.writeFlattenable(ra);
18318b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org        descSize += raBuffer.bytesWritten();
18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
183510d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
183610d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    ///////////////////////////////////////////////////////////////////////////
183710d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    // Now that we're done tweaking the rec, call the PostMakeRec cleanup
183897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    SkScalerContext::PostMakeRec(*this, &rec);
1839fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    descSize += SkDescriptor::ComputeOverhead(entryCount);
18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoDescriptor    ad(descSize);
18438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDescriptor*       desc = ad.getDesc();
18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    desc->init();
18468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (pe) {
18498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
18508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mf) {
18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
18538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (ra) {
18558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(descSize == desc->getLength());
18598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    desc->computeChecksum();
18608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
186117fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#ifdef TEST_DESC
186217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com    {
186317fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // Check that we completely write the bytes in desc (our key), and that
186417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // there are no uninitialized bytes. If there were, then we would get
186517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // false-misses (or worse, false-hits) in our fontcache.
186617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        //
186717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // We do this buy filling 2 others, one with 0s and the other with 1s
186817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // and create those, and then check that all 3 are identical.
186917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkAutoDescriptor    ad1(descSize);
187017fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkAutoDescriptor    ad2(descSize);
187117fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkDescriptor*       desc1 = ad1.getDesc();
187217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkDescriptor*       desc2 = ad2.getDesc();
1873fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
187417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        memset(desc1, 0x00, descSize);
187517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        memset(desc2, 0xFF, descSize);
1876fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
187717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc1->init();
187817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc2->init();
187917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
188017fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1881fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
188217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        if (pe) {
188317fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
188417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
188517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        }
188617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        if (mf) {
188717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
188817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
188917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        }
189017fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        if (ra) {
189117fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
189217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
189317fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        }
1894fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
189517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkASSERT(descSize == desc1->getLength());
189617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkASSERT(descSize == desc2->getLength());
189717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc1->computeChecksum();
189817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc2->computeChecksum();
189917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkASSERT(!memcmp(desc, desc1, descSize));
190017fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkASSERT(!memcmp(desc, desc2, descSize));
190117fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com    }
190217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#endif
1903fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
190490808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    proc(fTypeface, desc, context);
19058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1907532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.comSkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
19082d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                   const SkMatrix* deviceMatrix,
19092d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                   bool ignoreGamma) const {
19108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache* cache;
19112d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma);
19128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache;
19138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
191597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
191697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
191797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
191897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com//static
191997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comSkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
192097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1921a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
1922a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com                                                   rec.getPaintGamma(),
1923a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com                                                   rec.getDeviceGamma());
1924a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    return maskGamma.preBlend(rec.getLuminanceColor());
192597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com}
192697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
19272d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthsize_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
19282d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        SkScalar deviceGamma, int* width, int* height) {
19292d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
19302d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
19312d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   paintGamma,
19322d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   deviceGamma);
19332d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19342d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    maskGamma.getGammaTableDimensions(width, height);
19352d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    size_t size = (*width)*(*height)*sizeof(uint8_t);
19362d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19372d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    return size;
19382d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth}
19392d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19402d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthvoid SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
19412d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                      void* data) {
19422d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
19432d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
19442d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   paintGamma,
19452d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   deviceGamma);
19462d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    int width, height;
19472d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    maskGamma.getGammaTableDimensions(&width, &height);
19482d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    size_t size = width*height*sizeof(uint8_t);
19492d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const uint8_t* gammaTables = maskGamma.getGammaTables();
19502d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    memcpy(data, gammaTables, size);
19512d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth}
19522d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19532d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
19558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uintptr_t asint(const void* p) {
1959aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return reinterpret_cast<uintptr_t>(p);
1960aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
1961aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1962aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comunion Scalar32 {
1963aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkScalar    fScalar;
1964aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    uint32_t    f32;
1965aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com};
1966aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1967aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1968aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1969aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    Scalar32 tmp;
1970aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    tmp.fScalar = value;
1971aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    *ptr = tmp.f32;
1972aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return ptr + 1;
1973aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
1974aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1975aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic SkScalar read_scalar(const uint32_t*& ptr) {
1976aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1977aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    Scalar32 tmp;
1978aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    tmp.f32 = *ptr++;
1979aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return tmp.fScalar;
1980aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
1981aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1982aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1983aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(a == (uint8_t)a);
1984aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(b == (uint8_t)b);
1985aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(c == (uint8_t)c);
1986aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(d == (uint8_t)d);
1987aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return (a << 24) | (b << 16) | (c << 8) | d;
1988aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
1989aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
199085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#ifdef SK_DEBUG
199185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
199285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        SkASSERT(bitCount > 0 && bitCount <= 32);
199385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        uint32_t mask = ~0U;
199485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        mask >>= (32 - bitCount);
199585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        SkASSERT(0 == (value & ~mask));
199685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
199785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#else
199885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    #define ASSERT_FITS_IN(value, bitcount)
199985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#endif
200085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
2001aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comenum FlatFlags {
200297f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    kHasTypeface_FlatFlag                      = 0x01,
200397f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    kHasEffects_FlatFlag                       = 0x02,
200497f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
2005667b98d947892cec939669bccf204ab9ed565c4eskia.committer@gmail.com
200685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFlatFlagMask = 0x7,
200785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org};
200885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
200985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgenum BitsPerField {
201085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFlags_BPF  = 16,
201185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kHint_BPF   = 2,
201285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kAlign_BPF  = 2,
201385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFilter_BPF = 2,
201485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFlatFlags_BPF  = 3,
2015aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com};
2016aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
201785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic inline int BPF_Mask(int bits) {
201885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (1 << bits) - 1;
201985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
202085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
202185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
202285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org                                 unsigned filter, unsigned flatFlags) {
202385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(flags, kFlags_BPF);
202485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(hint, kHint_BPF);
202585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(align, kAlign_BPF);
202685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(filter, kFilter_BPF);
202785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
202885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
202985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
203085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // add more bits in the future.
203185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
203285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
203385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
203485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
203585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFlags(packed >> 16);
203685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
203785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
203885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFilterLevel((SkPaint::FilterLevel)((packed >> 10) & BPF_Mask(kFilter_BPF)));
203985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (FlatFlags)(packed & kFlatFlagMask);
204085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
204185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
204285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org// V22_COMPATIBILITY_CODE
204385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic FlatFlags unpack_paint_flags_v22(SkPaint* paint, uint32_t packed) {
204485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    enum {
204585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        kFilterBitmap_Flag    = 0x02,
204685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        kHighQualityFilterBitmap_Flag = 0x4000,
2047667b98d947892cec939669bccf204ab9ed565c4eskia.committer@gmail.com
204885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        kAll_Flags = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag
204985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    };
205085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
205185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // previously flags:16, textAlign:8, flatFlags:8
205285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // now flags:16, hinting:4, textAlign:4, flatFlags:8
205385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    unsigned flags = packed >> 16;
205485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    int filter = 0;
205585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    if (flags & kFilterBitmap_Flag) {
205685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        filter |= 1;
205785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
205885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    if (flags & kHighQualityFilterBitmap_Flag) {
205985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        filter |= 2;
206085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
206185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFilterLevel((SkPaint::FilterLevel)filter);
206285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    flags &= ~kAll_Flags;   // remove these (now dead) bit flags
206385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
206485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFlags(flags);
2065667b98d947892cec939669bccf204ab9ed565c4eskia.committer@gmail.com
206685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // hinting added later. 0 in this nibble means use the default.
206785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    uint32_t hinting = (packed >> 12) & 0xF;
206885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setHinting(0 == hinting ? SkPaint::kNormal_Hinting : static_cast<SkPaint::Hinting>(hinting-1));
206985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setTextAlign(static_cast<SkPaint::Align>((packed >> 8) & 0xF));
207085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (FlatFlags)(packed & kFlatFlagMask);
207185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
207285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
2073aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com// The size of a flat paint's POD fields
2074d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comstatic const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
20751f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        1 * sizeof(SkColor) +
20761f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        1 * sizeof(uint16_t) +
20771f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        6 * sizeof(uint8_t);
2078aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2079aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com/*  To save space/time, we analyze the paint, and write a truncated version of
2080aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    it if there are not tricky elements like shaders, etc.
2081aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com */
20828b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPaint::flatten(SkWriteBuffer& buffer) const {
2083aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    uint8_t flatFlags = 0;
2084aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (this->getTypeface()) {
2085aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        flatFlags |= kHasTypeface_FlatFlag;
2086aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
2087aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (asint(this->getPathEffect()) |
2088aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getShader()) |
2089aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getXfermode()) |
2090aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getMaskFilter()) |
2091aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getColorFilter()) |
2092aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getRasterizer()) |
209354e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        asint(this->getLooper()) |
2094b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com        asint(this->getAnnotation()) |
209554e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        asint(this->getImageFilter())) {
2096aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        flatFlags |= kHasEffects_FlatFlag;
2097aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
2098c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com
20998b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
21008b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    uint32_t* ptr = buffer.reserve(kPODPaintSize);
21018b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
21028b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextSize());
21038b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextScaleX());
21048b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextSkewX());
21058b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getStrokeWidth());
21068b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getStrokeMiter());
21078b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    *ptr++ = this->getColor();
210885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
210985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
211085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org                              this->getFilterLevel(), flatFlags);
21118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
21128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org                    this->getStyle(), this->getTextEncoding());
2113aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2114aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    // now we're done with ptr and the (pre)reserved space. If we need to write
2115aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    // additional fields, use the buffer directly
2116aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasTypeface_FlatFlag) {
2117aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeTypeface(this->getTypeface());
2118aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
2119aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasEffects_FlatFlag) {
2120aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getPathEffect());
2121aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getShader());
2122aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getXfermode());
2123aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getMaskFilter());
2124aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getColorFilter());
2125aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getRasterizer());
2126aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getLooper());
212754e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        buffer.writeFlattenable(this->getImageFilter());
21280cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com
21290cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        if (fAnnotation) {
21300cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            buffer.writeBool(true);
21310cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            fAnnotation->writeToBuffer(buffer);
21320cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        } else {
21330cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            buffer.writeBool(false);
21340cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        }
2135aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
21368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21388b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPaint::unflatten(SkReadBuffer& buffer) {
21398b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
21408b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    const void* podData = buffer.skip(kPODPaintSize);
21418b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
21428b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
21438b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    // the order we read must match the order we wrote in flatten()
21448b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextSize(read_scalar(pod));
21458b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextScaleX(read_scalar(pod));
21468b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextSkewX(read_scalar(pod));
21478b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeWidth(read_scalar(pod));
21488b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeMiter(read_scalar(pod));
21498b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setColor(*pod++);
21508b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
215185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    unsigned flatFlags = 0;
21527ed173b1ebac84671fb0dc1b9bd323a5e6e63771commit-bot@chromium.org    if (buffer.isVersionLT(SkReadBuffer::kFilterLevelIsEnum_Version)) {
215385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        flatFlags = unpack_paint_flags_v22(this, *pod++);
215485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    } else {
215585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        flatFlags = unpack_paint_flags(this, *pod++);
215685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
21578b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
215885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    uint32_t tmp = *pod++;
21598b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
21608b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
21618b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
21628b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
2163aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2164aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasTypeface_FlatFlag) {
2165aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setTypeface(buffer.readTypeface());
2166aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    } else {
2167aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setTypeface(NULL);
2168aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
2169aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2170aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasEffects_FlatFlag) {
2171353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
2172353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setShader(buffer.readShader()));
2173353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setXfermode(buffer.readXfermode()));
2174353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
2175353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
2176353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
2177353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
2178353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
2179fbc58a305518fe611113a51649bf557c991ac8cfskia.committer@gmail.com
21800cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        if (buffer.readBool()) {
2181d957984c1efbd18f3b2bbeca78d282837c5a2ae1commit-bot@chromium.org            this->setAnnotation(SkAnnotation::Create(buffer))->unref();
21820cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        }
2183aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    } else {
2184aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setPathEffect(NULL);
2185aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setShader(NULL);
2186aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setXfermode(NULL);
2187aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setMaskFilter(NULL);
2188aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setColorFilter(NULL);
2189aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setRasterizer(NULL);
2190aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setLooper(NULL);
219154e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        this->setImageFilter(NULL);
2192aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
219397f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org
21943b6255493e458c6b2c1412af908581f0bf3f6b70djsollen    if (buffer.isVersionLT(SkReadBuffer::kRemoveAndroidPaintOpts_Version) &&
21953b6255493e458c6b2c1412af908581f0bf3f6b70djsollen            flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
21963b6255493e458c6b2c1412af908581f0bf3f6b70djsollen        SkString tag;
21973b6255493e458c6b2c1412af908581f0bf3f6b70djsollen        buffer.readUInt();
21983b6255493e458c6b2c1412af908581f0bf3f6b70djsollen        buffer.readString(&tag);
21993b6255493e458c6b2c1412af908581f0bf3f6b70djsollen        buffer.readBool();
220097f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    }
22018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
220582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkShader* SkPaint::setShader(SkShader* shader) {
2206f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(shader != fShader);
22078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fShader, shader);
2208ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, shader != NULL, kShader_DirtyBit);
22098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return shader;
22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
221282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
2213f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(filter != fColorFilter);
22148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fColorFilter, filter);
2215ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, filter != NULL, kColorFilter_DirtyBit);
22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
22178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
221982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
2220f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(mode != fXfermode);
22218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fXfermode, mode);
2222ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, mode != NULL, kXfermode_DirtyBit);
22238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return mode;
22248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22260baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.comSkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
2227d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    SkSafeUnref(fXfermode);
2228d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    fXfermode = SkXfermode::Create(mode);
2229f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC;
2230ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, fXfermode != NULL, kXfermode_DirtyBit);
2231d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    return fXfermode;
2232d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com}
2233d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com
223482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
2235f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(effect != fPathEffect);
22368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fPathEffect, effect);
2237ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, effect != NULL, kPathEffect_DirtyBit);
22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return effect;
22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
224182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
2242f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(filter != fMaskFilter);
22438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMaskFilter, filter);
2244ee902cd4f4b3c8f355c0f4de35152a14904ec54amtklein    fDirtyBits = SkSetClearMask(fDirtyBits, filter != NULL, kMaskFilter_DirtyBit);
22458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
22468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
224882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
22498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22504bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.combool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
22514bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com                          const SkRect* cullRect) const {
2252fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    SkStrokeRec rec(*this);
22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2254fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    const SkPath* srcPtr = &src;
2255fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    SkPath tmpPath;
225672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
22574bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com    if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
2258fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        srcPtr = &tmpPath;
22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
22608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2261fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    if (!rec.applyToPath(dst, *srcPtr)) {
2262fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        if (srcPtr == &tmpPath) {
2263fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // If path's were copy-on-write, this trick would not be needed.
2264fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // As it is, we want to save making a deep-copy from tmpPath -> dst
2265fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // since we know we're just going to delete tmpPath when we return,
2266fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // so the swap saves that copy.
2267fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            dst->swap(tmpPath);
2268fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        } else {
2269fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            *dst = *srcPtr;
2270d3521f1a8dc07fe84d6a8f2151b0c176ff1ec8careed@google.com        }
2271d3521f1a8dc07fe84d6a8f2151b0c176ff1ec8careed@google.com    }
2272fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    return !rec.isHairlineStyle();
22738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2275e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.comconst SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
2276a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com                                           SkRect* storage,
2277a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com                                           Style style) const {
22788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(storage);
22799efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2280e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    const SkRect* src = &origSrc;
2281e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com
22829efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    if (this->getLooper()) {
22839efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2284e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        this->getLooper()->computeFastBounds(*this, *src, storage);
22859efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        return *storage;
22869efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    }
22879efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2288e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    SkRect tmpSrc;
2289e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    if (this->getPathEffect()) {
2290e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2291e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        src = &tmpSrc;
2292e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    }
2293e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com
2294a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (kFill_Style != style) {
22959efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        // since we're stroked, outset the rect by the radius (and join type)
22969efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkScalar radius = SkScalarHalf(this->getStrokeWidth());
22979efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (0 == radius) {  // hairline
22989efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            radius = SK_Scalar1;
22999efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
23009efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            SkScalar scale = this->getStrokeMiter();
23019efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            if (scale > SK_Scalar1) {
23029efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com                radius = SkScalarMul(radius, scale);
23039efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            }
23048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2305e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        storage->set(src->fLeft - radius, src->fTop - radius,
2306e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com                     src->fRight + radius, src->fBottom + radius);
23079efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    } else {
2308e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        *storage = *src;
23098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23109efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
23119efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    if (this->getMaskFilter()) {
23129efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        this->getMaskFilter()->computeFastBounds(*storage, storage);
23139efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    }
23149efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2315336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (this->getImageFilter()) {
2316336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        this->getImageFilter()->computeFastBounds(*storage, storage);
2317336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
2318336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
2319d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    return *storage;
23208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23220f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
232383658305a1bda2d862f50145ecf5cb697b575e86reed
2324791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.comvoid SkPaint::toString(SkString* str) const {
2325791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2326791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2327791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkTypeface* typeface = this->getTypeface();
232849f085dddff10473b6ebf832a974288300224e60bsalomon    if (typeface) {
2329d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman        SkDynamicMemoryWStream ostream;
2330d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman        typeface->serialize(&ostream);
2331d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman        SkAutoTUnref<SkStreamAsset> istream(ostream.detachAsStream());
2332d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman        SkFontDescriptor descriptor(istream);
2333791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2334791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Font Family Name:</dt><dd>");
2335791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getFamilyName());
2336791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd><dt>Font Full Name:</dt><dd>");
2337791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getFullName());
2338791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd><dt>Font PS Name:</dt><dd>");
2339791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getPostscriptName());
2340791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd><dt>Font File Name:</dt><dd>");
2341791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getFontFileName());
2342791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2343791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2344791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2345791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextSize:</dt><dd>");
2346791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextSize());
2347791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2348791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2349791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextScaleX:</dt><dd>");
2350791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextScaleX());
2351791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2352791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2353791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextSkewX:</dt><dd>");
2354791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextSkewX());
2355791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2356791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2357791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkPathEffect* pathEffect = this->getPathEffect();
235849f085dddff10473b6ebf832a974288300224e60bsalomon    if (pathEffect) {
2359791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>PathEffect:</dt><dd>");
2360791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2361791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2362791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2363791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkShader* shader = this->getShader();
236449f085dddff10473b6ebf832a974288300224e60bsalomon    if (shader) {
2365791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Shader:</dt><dd>");
23661202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        shader->toString(str);
2367791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2368791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2369791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2370791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkXfermode* xfer = this->getXfermode();
237149f085dddff10473b6ebf832a974288300224e60bsalomon    if (xfer) {
2372791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Xfermode:</dt><dd>");
23731202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        xfer->toString(str);
2374791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2375791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2376791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2377791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkMaskFilter* maskFilter = this->getMaskFilter();
237849f085dddff10473b6ebf832a974288300224e60bsalomon    if (maskFilter) {
2379791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>MaskFilter:</dt><dd>");
23801202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        maskFilter->toString(str);
2381791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2382791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2383791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2384791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkColorFilter* colorFilter = this->getColorFilter();
238549f085dddff10473b6ebf832a974288300224e60bsalomon    if (colorFilter) {
2386791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>ColorFilter:</dt><dd>");
23871202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        colorFilter->toString(str);
2388791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2389791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2390791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2391791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkRasterizer* rasterizer = this->getRasterizer();
239249f085dddff10473b6ebf832a974288300224e60bsalomon    if (rasterizer) {
2393791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Rasterizer:</dt><dd>");
2394791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2395791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2396791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2397791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkDrawLooper* looper = this->getLooper();
239849f085dddff10473b6ebf832a974288300224e60bsalomon    if (looper) {
2399791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>DrawLooper:</dt><dd>");
24001202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        looper->toString(str);
2401791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2402791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2403791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2404791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkImageFilter* imageFilter = this->getImageFilter();
240549f085dddff10473b6ebf832a974288300224e60bsalomon    if (imageFilter) {
2406791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>ImageFilter:</dt><dd>");
2407791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2408791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2409791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2410791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkAnnotation* annotation = this->getAnnotation();
241149f085dddff10473b6ebf832a974288300224e60bsalomon    if (annotation) {
2412791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Annotation:</dt><dd>");
2413791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2414791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2415791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2416791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Color:</dt><dd>0x");
2417791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkColor color = this->getColor();
2418791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendHex(color);
2419791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2420791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2421791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Stroke Width:</dt><dd>");
2422791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getStrokeWidth());
2423791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2424791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2425791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Stroke Miter:</dt><dd>");
2426791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getStrokeMiter());
2427791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2428791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2429791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Flags:</dt><dd>(");
2430791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (this->getFlags()) {
2431791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        bool needSeparator = false;
2432791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
2433791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
2434791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
2435791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
2436791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
2437791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
2438791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
2439791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
2440791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
2441791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isEmbeddedBitmapText(),
2442791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com                          "EmbeddedBitmapText", &needSeparator);
2443791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
2444791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
2445791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
2446791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com                          "GenA8FromLCD", &needSeparator);
2447791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    } else {
2448791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("None");
2449791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2450791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(")</dd>");
2451791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
24523e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    str->append("<dt>FilterLevel:</dt><dd>");
24533e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" };
24543e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    str->append(gFilterLevelStrings[this->getFilterLevel()]);
24553e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    str->append("</dd>");
24563e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com
2457791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextAlign:</dt><dd>");
2458791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
2459791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gTextAlignStrings[this->getTextAlign()]);
2460791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2461791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2462791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>CapType:</dt><dd>");
2463791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
2464791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gStrokeCapStrings[this->getStrokeCap()]);
2465791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2466791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2467791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>JoinType:</dt><dd>");
2468791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
2469791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gJoinStrings[this->getStrokeJoin()]);
2470791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2471791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2472791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Style:</dt><dd>");
2473791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
2474791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gStyleStrings[this->getStyle()]);
2475791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2476791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2477791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextEncoding:</dt><dd>");
2478791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
2479791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gTextEncodingStrings[this->getTextEncoding()]);
2480791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2481791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2482791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Hinting:</dt><dd>");
2483791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
2484791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gHintingStrings[this->getHinting()]);
2485791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2486791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2487791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd></dl></dl>");
2488791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com}
2489791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#endif
2490791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
24916fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
24928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24936fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool has_thick_frame(const SkPaint& paint) {
24946fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    return  paint.getStrokeWidth() > 0 &&
24956fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            paint.getStyle() != SkPaint::kFill_Style;
24968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
24978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
24998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    const SkPaint& paint,
2500166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com                                    bool applyStrokeAndPathEffects)
2501166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com                                    : fPaint(paint) {
25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
25038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                true);
25048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2505166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    fPaint.setLinearText(true);
25068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
25078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
25098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        applyStrokeAndPathEffects = false;
25106fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
25118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2512166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    // can't use our canonical size if we need to apply patheffects
2513166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    if (fPaint.getPathEffect() == NULL) {
25148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
25158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2516166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com        if (has_thick_frame(fPaint)) {
2517166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com            fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
2518166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com        }
25196fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
25208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fScale = SK_Scalar1;
25216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
252272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
25236fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!applyStrokeAndPathEffects) {
25248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setStyle(SkPaint::kFill_Style);
25258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setPathEffect(NULL);
25268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25282d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    fCache = fPaint.detachCache(NULL, NULL, false);
25298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint::Style  style = SkPaint::kFill_Style;
25318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect*   pe = NULL;
25328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25336fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!applyStrokeAndPathEffects) {
25348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        style = paint.getStyle();   // restore
25358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        pe = paint.getPathEffect();     // restore
25368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setStyle(style);
25388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setPathEffect(pe);
25398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setMaskFilter(paint.getMaskFilter());    // restore
25408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now compute fXOffset if needed
25428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar xOffset = 0;
25446fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
25458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int      count;
25466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
25476fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                                         &count, NULL), fScale);
25486fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
25498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            width = SkScalarHalf(width);
25506fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
25518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        xOffset = -width;
25528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXPos = xOffset;
25548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPrevAdvance = 0;
25558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fText = text;
25578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStop = text + length;
25587b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com
255944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    fXYIndex = paint.isVerticalText() ? 1 : 0;
25608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25626fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkTextToPathIter::~SkTextToPathIter() {
25638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache::AttachCache(fCache);
25648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25667b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.combool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
25677b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    if (fText < fStop) {
25688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
25698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
257144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
25728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25736fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (glyph.fWidth) {
25747b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            if (path) {
25757b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com                *path = fCache->findPath(glyph);
25767b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            }
25777b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        } else {
25787b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            if (path) {
25797b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com                *path = NULL;
25806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            }
25818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
25827b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (xpos) {
25837b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            *xpos = fXPos;
25847b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
25857b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        return true;
25868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25877b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    return false;
25888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2589dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com
2590dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com///////////////////////////////////////////////////////////////////////////////
2591dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com
2592dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.combool SkPaint::nothingToDraw() const {
2593733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com    if (fLooper) {
2594733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com        return false;
2595733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com    }
2596dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    SkXfermode::Mode mode;
2597dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    if (SkXfermode::AsMode(fXfermode, &mode)) {
2598dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com        switch (mode) {
2599dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kSrcOver_Mode:
2600dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kSrcATop_Mode:
2601dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDstOut_Mode:
2602dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDstOver_Mode:
2603dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kPlus_Mode:
2604dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com                return 0 == this->getAlpha();
2605dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDst_Mode:
2606dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com                return true;
2607dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            default:
2608dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com                break;
2609dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com        }
2610dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    }
2611dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    return false;
2612dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com}
2613aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2614aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orginline static unsigned popcount(uint8_t x) {
2615aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    // As in Hacker's delight, adapted for just 8 bits.
2616aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    x = (x & 0x55) + ((x >> 1) & 0x55);  // a b c d w x y z -> a+b c+d w+x y+z
2617aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    x = (x & 0x33) + ((x >> 2) & 0x33);  // a+b c+d w+x y+z -> a+b+c+d w+x+y+z
2618aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    x = (x & 0x0F) + ((x >> 4) & 0x0F);  // a+b+c+d w+x+y+z -> a+b+c+d+w+x+y+z
2619aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    return x;
2620aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org}
2621aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2622aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orgvoid SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
2623aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    const uint32_t dirty = paint.fDirtyBits;
2624aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
262545d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    // Each of the low 7 dirty bits corresponds to a 4-byte flat value,
262645d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    // plus one for the dirty bits and one for the bitfields
262745d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    const size_t flatBytes = 4 * (popcount(dirty & kPOD_DirtyBitMask) + 2);
2628aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    SkASSERT(flatBytes <= 32);
2629aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    uint32_t* u32 = buffer.reserve(flatBytes);
2630aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    *u32++ = dirty;
2631f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    *u32++ = paint.fBitfieldsUInt;
263245d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    if (0 == dirty) {
2633aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        return;
2634aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    }
2635aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2636aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#define F(dst, field) if (dirty & k##field##_DirtyBit) *dst++ = paint.get##field()
2637aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(u32, Color);
2638aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    SkScalar* f32 = reinterpret_cast<SkScalar*>(u32);
2639aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, TextSize);
2640aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, TextScaleX);
2641aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, TextSkewX);
2642aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, StrokeWidth);
2643aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, StrokeMiter);
2644aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#undef F
2645aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#define F(field) if (dirty & k##field##_DirtyBit) buffer.writeFlattenable(paint.get##field())
2646aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(PathEffect);
2647aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Shader);
2648aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Xfermode);
2649aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(MaskFilter);
2650aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(ColorFilter);
2651aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Rasterizer);
2652aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Looper);
2653aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(ImageFilter);
2654aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#undef F
2655aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & kTypeface_DirtyBit) buffer.writeTypeface(paint.getTypeface());
2656aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & kAnnotation_DirtyBit) paint.getAnnotation()->writeToBuffer(buffer);
2657aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org}
2658aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2659aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orgvoid SkPaint::FlatteningTraits::Unflatten(SkReadBuffer& buffer, SkPaint* paint) {
2660aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    const uint32_t dirty = buffer.readUInt();
2661f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    paint->fBitfieldsUInt = buffer.readUInt();
2662aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty == 0) {
2663aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        return;
2664aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    }
2665aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#define F(field, reader) if (dirty & k##field##_DirtyBit) paint->set##field(buffer.reader())
2666aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org// Same function, except it unrefs the object newly set on the paint:
2667aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#define F_UNREF(field, reader)                      \
2668aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & k##field##_DirtyBit)                \
2669aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        paint->set##field(buffer.reader())->unref()
2670aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2671aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Color,       readUInt);
2672aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(TextSize,    readScalar);
2673aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(TextScaleX,  readScalar);
2674aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(TextSkewX,   readScalar);
2675aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(StrokeWidth, readScalar);
2676aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(StrokeMiter, readScalar);
2677aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(PathEffect,  readPathEffect);
2678aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(Shader,      readShader);
2679aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(Xfermode,    readXfermode);
2680aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(MaskFilter,  readMaskFilter);
2681aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(ColorFilter, readColorFilter);
2682aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(Rasterizer,  readRasterizer);
2683aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(Looper,      readDrawLooper);
2684aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(ImageFilter, readImageFilter);
2685aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Typeface,    readTypeface);
2686aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#undef F
2687aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#undef F_UNREF
2688aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & kAnnotation_DirtyBit) {
2689d957984c1efbd18f3b2bbeca78d282837c5a2ae1commit-bot@chromium.org        paint->setAnnotation(SkAnnotation::Create(buffer))->unref();
2690aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    }
2691aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    SkASSERT(dirty == paint->fDirtyBits);
2692aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org}
2693