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"
14791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkFontDescriptor.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFontHost.h"
16791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkGlyphCache.h"
1715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com#include "SkImageFilter.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
1997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#include "SkMaskGamma.h"
208b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
218b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
22791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkPaintDefaults.h"
2397f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org#include "SkPaintOptionsAndroid.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,
5745d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    kPaintOptionsAndroid_DirtyBit = 1 << 16,
58aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org};
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
60a3237875f807aed9608cb4a023bc044f32850727reed@google.com// define this to get a printf for out-of-range parameter in setters
61a3237875f807aed9608cb4a023bc044f32850727reed@google.com// e.g. setTextSize(-1)
62a3237875f807aed9608cb4a023bc044f32850727reed@google.com//#define SK_REPORT_API_RANGE_CHECK
63a3237875f807aed9608cb4a023bc044f32850727reed@google.com
6456c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
65f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#define GEN_ID_INC                  fGenerationID++
66f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
67f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#else
68f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#define GEN_ID_INC
69f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#define GEN_ID_INC_EVAL(expression)
70f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
71f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
72a3122b9b1ec66efef606d8797b7b16b6634e08d2reed@android.comSkPaint::SkPaint() {
73aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fTypeface    = NULL;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPathEffect  = NULL;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader      = NULL;
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode    = NULL;
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMaskFilter  = NULL;
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColorFilter = NULL;
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRasterizer  = NULL;
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLooper      = NULL;
8115356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    fImageFilter = NULL;
82b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    fAnnotation  = NULL;
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
84e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fTextSize     = SkPaintDefaults_TextSize;
85e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fTextScaleX   = SK_Scalar1;
86e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fTextSkewX    = 0;
87e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fColor        = SK_ColorBLACK;
88e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fWidth        = 0;
89e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fMiterLimit   = SkPaintDefaults_MiterLimit;
90e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
91e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    // Zero all bitfields, then set some non-zero defaults.
92e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fBitfields    = 0;
93e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fFlags        = SkPaintDefaults_Flags;
94e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fCapType      = kDefault_Cap;
95e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fJoinType     = kDefault_Join;
96e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fTextAlign    = kLeft_Align;
97e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fStyle        = kFill_Style;
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTextEncoding = kUTF8_TextEncoding;
99e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fHinting      = SkPaintDefaults_Hinting;
100e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
101e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    fDirtyBits    = 0;
10256c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
103c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org    new (&fPaintOptionsAndroid) SkPaintOptionsAndroid;
104f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    fGenerationID = 0;
105f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint::SkPaint(const SkPaint& src) {
109e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define COPY(field) field = src.field
110e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define REF_COPY(field) field = SkSafeRef(src.field)
111e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
112e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fTypeface);
113e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fPathEffect);
114e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fShader);
115e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fXfermode);
116e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fMaskFilter);
117e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fColorFilter);
118e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fRasterizer);
119e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fLooper);
120e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fImageFilter);
121e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fAnnotation);
122e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
123e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSize);
124e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextScaleX);
125e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSkewX);
126e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fColor);
127e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fWidth);
128e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fMiterLimit);
129e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fBitfields);
130e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fDirtyBits);
13140078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
13240078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
13340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com    new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
134e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fGenerationID);
13540078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com#endif
136e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
137e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef COPY
138e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef REF_COPY
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1416fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint::~SkPaint() {
14282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fTypeface);
14382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fPathEffect);
14482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fShader);
14582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fXfermode);
14682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fMaskFilter);
14782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fColorFilter);
14882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fRasterizer);
14982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fLooper);
15015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    SkSafeUnref(fImageFilter);
151b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    SkSafeUnref(fAnnotation);
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1546fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint& SkPaint::operator=(const SkPaint& src) {
155f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org    if (this == &src) {
156f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org        return *this;
157f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org    }
158f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org
159e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define COPY(field) field = src.field
160e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field)
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
162e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    SkASSERT(&src);
16382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
164e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fTypeface);
165e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fPathEffect);
166e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fShader);
167e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fXfermode);
168e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fMaskFilter);
169e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fColorFilter);
170e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fRasterizer);
171e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fLooper);
172e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fImageFilter);
173e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fAnnotation);
174e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
175e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSize);
176e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextScaleX);
177e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSkewX);
178e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fColor);
179e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fWidth);
180e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fMiterLimit);
181e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fBitfields);
182e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fDirtyBits);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18456c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
185c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org    fPaintOptionsAndroid.~SkPaintOptionsAndroid();
186c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org    new (&fPaintOptionsAndroid) SkPaintOptionsAndroid(src.fPaintOptionsAndroid);
187e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    ++fGenerationID;
188f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *this;
191e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
192e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef COPY
193e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef REF_COPY
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
196b265741cc17f897b349caacdb890119e4111a415robertphillips@google.combool operator==(const SkPaint& a, const SkPaint& b) {
197e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define EQUAL(field) (a.field == b.field)
198e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    // Don't check fGenerationID or fDirtyBits, which can be different for logically equal paints.
199e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    return EQUAL(fTypeface)
200e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fPathEffect)
201e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fShader)
202e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fXfermode)
203e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fMaskFilter)
204e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fColorFilter)
205e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fRasterizer)
206e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fLooper)
207e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fImageFilter)
208e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fAnnotation)
209e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextSize)
210e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextScaleX)
211e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextSkewX)
212e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fColor)
213e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fWidth)
214e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fMiterLimit)
215e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fBitfields)
216b265741cc17f897b349caacdb890119e4111a415robertphillips@google.com#ifdef SK_BUILD_FOR_ANDROID
217e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fPaintOptionsAndroid)
218b265741cc17f897b349caacdb890119e4111a415robertphillips@google.com#endif
219e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        ;
220e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef EQUAL
221b265741cc17f897b349caacdb890119e4111a415robertphillips@google.com}
222b265741cc17f897b349caacdb890119e4111a415robertphillips@google.com
2236fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::reset() {
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint init;
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22656c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
227f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    uint32_t oldGenerationID = fGenerationID;
228f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *this = init;
23056c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
231f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    fGenerationID = oldGenerationID + 1;
232f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com#endif
233f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com}
234f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
23556c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
236f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.comuint32_t SkPaint::getGenerationID() const {
237f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    return fGenerationID;
238f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com}
2394bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com
2404bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.comvoid SkPaint::setGenerationID(uint32_t generationID) {
2414bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com    fGenerationID = generationID;
2424bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com}
243f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
24460abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.comunsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
245ba3284e7bbb830749206414890f8152e421969f2bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
24660abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com    SkGlyphCache* cache = autoCache.getCache();
24760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com    return cache->getBaseGlyphCount(text);
24860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com}
249c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org
250c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.orgvoid SkPaint::setPaintOptionsAndroid(const SkPaintOptionsAndroid& options) {
251c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org    if (options != fPaintOptionsAndroid) {
252c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org        fPaintOptionsAndroid = options;
253c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org        GEN_ID_INC;
254aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        fDirtyBits |= kPaintOptionsAndroid_DirtyBit;
255c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org    }
256c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org}
25760abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com#endif
25860abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com
259c9683151367b2033a26b1e2ebe6b3902d2064bdbreed@google.comvoid SkPaint::setFilterLevel(FilterLevel level) {
26085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    GEN_ID_INC_EVAL((unsigned) level != fFilterLevel);
26185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    fFilterLevel = level;
262c9683151367b2033a26b1e2ebe6b3902d2064bdbreed@google.com}
263c9683151367b2033a26b1e2ebe6b3902d2064bdbreed@google.com
264f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.comvoid SkPaint::setHinting(Hinting hintingLevel) {
265f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
266f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    fHinting = hintingLevel;
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2696fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setFlags(uint32_t flags) {
270f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(fFlags != flags);
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fFlags = flags;
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2746fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAntiAlias(bool doAA) {
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2786fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setDither(bool doDither) {
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2826fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setSubpixelText(bool doSubpixel) {
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2866fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setLCDRenderText(bool doLCDRender) {
287309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org    this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
288309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org}
289309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org
2906fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
291e95c91e6d9201d50d0b84fbc3d2f53f92f753e0bagl@chromium.org    this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
292e95c91e6d9201d50d0b84fbc3d2f53f92f753e0bagl@chromium.org}
293e95c91e6d9201d50d0b84fbc3d2f53f92f753e0bagl@chromium.org
2946fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAutohinted(bool useAutohinter) {
295a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org    this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
296a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org}
297a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org
2986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setLinearText(bool doLinearText) {
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
302830a23e39bb4a126e573940cd6e354732e295b10reed@google.comvoid SkPaint::setVerticalText(bool doVertical) {
303830a23e39bb4a126e573940cd6e354732e295b10reed@google.com    this->setFlags(SkSetClearMask(fFlags, doVertical, kVerticalText_Flag));
304830a23e39bb4a126e573940cd6e354732e295b10reed@google.com}
305830a23e39bb4a126e573940cd6e354732e295b10reed@google.com
3066fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setUnderlineText(bool doUnderline) {
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3106fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrikeThruText(bool doStrikeThru) {
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3146fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setFakeBoldText(bool doFakeBold) {
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3186fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setDevKernText(bool doDevKern) {
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
322b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.orgvoid SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
323b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.org    this->setFlags(SkSetClearMask(fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
324b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.org}
325b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.org
3266fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStyle(Style style) {
3276fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)style < kStyleCount) {
328f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL((unsigned)style != fStyle);
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStyle = style;
330f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
331a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
332a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
333a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3346fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3376fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setColor(SkColor color) {
338f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(color != fColor);
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColor = color;
340aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits |= kColor_DirtyBit;
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAlpha(U8CPU a) {
344f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
345f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com                                  SkColorGetG(fColor), SkColorGetB(fColor)));
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3486fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
349f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    this->setColor(SkColorSetARGB(a, r, g, b));
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3526fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeWidth(SkScalar width) {
3536fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (width >= 0) {
354f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL(width != fWidth);
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWidth = width;
356aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        fDirtyBits |= kStrokeWidth_DirtyBit;
357f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
358a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
359a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
360a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3616fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeMiter(SkScalar limit) {
3656fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (limit >= 0) {
366f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL(limit != fMiterLimit);
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMiterLimit = limit;
368aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        fDirtyBits |= kStrokeMiter_DirtyBit;
369f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
370a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
371a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
372a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3736fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3766fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeCap(Cap ct) {
3776fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)ct < kCapCount) {
378f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL((unsigned)ct != fCapType);
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fCapType = SkToU8(ct);
3806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
381a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
382a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
383a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3846fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3876fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeJoin(Join jt) {
3886fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)jt < kJoinCount) {
389f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fJoinType = SkToU8(jt);
3916fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
392a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
393a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
394a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3956fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4006fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextAlign(Align align) {
4016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)align < kAlignCount) {
402f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTextAlign = SkToU8(align);
4046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
405a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
406a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
407a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
4086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4116fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextSize(SkScalar ts) {
412c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    if (ts >= 0) {
413f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL(ts != fTextSize);
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTextSize = ts;
415aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        fDirtyBits |= kTextSize_DirtyBit;
4166fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
417a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
418a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextSize() called with negative value\n");
419a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
4206fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4236fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextScaleX(SkScalar scaleX) {
424f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(scaleX != fTextScaleX);
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTextScaleX = scaleX;
426aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits |= kTextScaleX_DirtyBit;
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4296fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextSkewX(SkScalar skewX) {
430f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(skewX != fTextSkewX);
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTextSkewX = skewX;
432aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits |= kTextSkewX_DirtyBit;
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4356fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextEncoding(TextEncoding encoding) {
4366fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)encoding <= kGlyphID_TextEncoding) {
437f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com        GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTextEncoding = encoding;
4396fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
440a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
441a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
442a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
4436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
448aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org// Returns dst with the given bitmask enabled or disabled, depending on value.
449aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orginline static uint32_t set_mask(uint32_t dst, uint32_t bitmask, bool value) {
450aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    return value ? (dst | bitmask) : (dst & ~bitmask);
451aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org}
452aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
4536fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkTypeface* SkPaint::setTypeface(SkTypeface* font) {
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fTypeface, font);
455f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC;
456aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kTypeface_DirtyBit, font != NULL);
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return font;
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4606fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fRasterizer, r);
462f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC;
463aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kRasterizer_DirtyBit, r != NULL);
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return r;
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4676fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fLooper, looper);
469f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC;
470aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kLooper_DirtyBit, looper != NULL);
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return looper;
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
47415356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comSkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
47515356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    SkRefCnt_SafeAssign(fImageFilter, imageFilter);
47615356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    GEN_ID_INC;
477aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kImageFilter_DirtyBit, imageFilter != NULL);
47815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    return imageFilter;
47915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com}
48015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
481b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.comSkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
482b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    SkRefCnt_SafeAssign(fAnnotation, annotation);
483b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    GEN_ID_INC;
484aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kAnnotation_DirtyBit, annotation != NULL);
485b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    return annotation;
486b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com}
487b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
490ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comstatic SkScalar mag2(SkScalar x, SkScalar y) {
491ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return x * x + y * y;
492ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
493ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
494ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comstatic bool tooBig(const SkMatrix& m, SkScalar ma2max) {
495ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return  mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
496ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            ||
497ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
498ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
499ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
500ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.combool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
501ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkASSERT(!ctm.hasPerspective());
502ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkASSERT(!textM.hasPerspective());
503ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
504ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkMatrix matrix;
505ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    matrix.setConcat(ctm, textM);
506ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return tooBig(matrix, MaxCacheSize2());
507ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
508ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
509ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.combool SkPaint::tooBigToUseCache(const SkMatrix& ctm) const {
510ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkMatrix textM;
511ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return TooBigToUseCache(ctm, *this->setTextMatrix(&textM));
512ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
513ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
514ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.combool SkPaint::tooBigToUseCache() const {
515ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkMatrix textM;
516ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return tooBig(*this->setTextMatrix(&textM), MaxCacheSize2());
517ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
518ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
519ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com///////////////////////////////////////////////////////////////////////////////
520ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGlyphCache.h"
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
52490808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.comstatic void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
52590808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                           void* context) {
52690808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
527f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com}
528f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkPaint::textToGlyphs(const void* textData, size_t byteLength,
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          uint16_t glyphs[]) const {
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (byteLength == 0) {
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
53472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(textData != NULL);
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == glyphs) {
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        switch (this->getTextEncoding()) {
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kUTF8_TextEncoding:
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkUTF8_CountUnichars((const char*)textData, byteLength);
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kUTF16_TextEncoding:
5422cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
54368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case kUTF32_TextEncoding:
5442cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkToInt(byteLength >> 2);
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kGlyphID_TextEncoding:
5462cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkToInt(byteLength >> 1);
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
5480c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
55272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we get here, we have a valid glyphs[] array, so time to fill it in
55472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // handle this encoding before the setup for the glyphcache
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we want to ignore the low bit of byteLength
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(glyphs, textData, byteLength >> 1 << 1);
5592cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org        return SkToInt(byteLength >> 1);
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
56172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
562532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*    cache = autoCache.getCache();
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = text + byteLength;
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t*   gptr = glyphs;
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (this->getTextEncoding()) {
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkPaint::kUTF8_TextEncoding:
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkPaint::kUTF16_TextEncoding: {
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint16_t* text16 = (const uint16_t*)text;
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint16_t* stop16 = (const uint16_t*)stop;
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text16 < stop16) {
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
58368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case kUTF32_TextEncoding: {
58468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* text32 = (const int32_t*)text;
58568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* stop32 = (const int32_t*)stop;
58668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            while (text32 < stop32) {
58768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                *gptr++ = cache->unicharToGlyph(*text32++);
58868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            }
58968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            break;
59068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        }
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
5920c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5942cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org    return SkToInt(gptr - glyphs);
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
597a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.combool SkPaint::containsText(const void* textData, size_t byteLength) const {
598a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    if (0 == byteLength) {
599a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        return true;
600a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
60172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
602a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    SkASSERT(textData != NULL);
60372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
604a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    // handle this encoding before the setup for the glyphcache
605a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
606a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
607a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        size_t count = byteLength >> 1;
608a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        for (size_t i = 0; i < count; i++) {
609a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            if (0 == glyphID[i]) {
610a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                return false;
611a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
612a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
613a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        return true;
614a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
61572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
616532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
617a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    SkGlyphCache*    cache = autoCache.getCache();
618a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com
619a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    switch (this->getTextEncoding()) {
620a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        case SkPaint::kUTF8_TextEncoding: {
621a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const char* text = static_cast<const char*>(textData);
622a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const char* stop = text + byteLength;
623a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            while (text < stop) {
624a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
625a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                    return false;
626a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                }
627a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
628a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            break;
629a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
630a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        case SkPaint::kUTF16_TextEncoding: {
631a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const uint16_t* text = static_cast<const uint16_t*>(textData);
632a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const uint16_t* stop = text + (byteLength >> 1);
633a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            while (text < stop) {
634a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
635a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                    return false;
636a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                }
637a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
638a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            break;
639a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
64068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case SkPaint::kUTF32_TextEncoding: {
64168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* text = static_cast<const int32_t*>(textData);
64268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* stop = text + (byteLength >> 2);
64368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            while (text < stop) {
64468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                if (0 == cache->unicharToGlyph(*text++)) {
64568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                    return false;
64668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                }
64768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            }
64868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            break;
64968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        }
650a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        default:
6510c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
652a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            return false;
653a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
654a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    return true;
655a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com}
656a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com
6579d3a985aa3c82605346ed1518375a8c384b925e5reed@android.comvoid SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
6589d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com                               SkUnichar textData[]) const {
6599d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    if (count <= 0) {
6609d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com        return;
6619d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    }
6629d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
6639d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkASSERT(glyphs != NULL);
6649d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkASSERT(textData != NULL);
6659d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
666532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
6679d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkGlyphCache*    cache = autoCache.getCache();
6689d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
6699d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    for (int index = 0; index < count; index++) {
6709d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com        textData[index] = cache->glyphToUnichar(glyphs[index]);
6719d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    }
6729d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com}
6739d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6766fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
6776fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
68072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6846fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
6856fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
68872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6926fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
6936fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
696fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7006fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
7016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
704fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
70868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
70968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
71068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
71168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
71268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
71368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
71468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
71568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
71668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharMetrics(uni);
71768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
71868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
71968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_prev(SkGlyphCache* cache,
72068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
72168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
72268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
723fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
72468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
72568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *--ptr;
72668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
72768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharMetrics(uni);
72868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
72968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
7306fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_glyph_next(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    const uint16_t* ptr = *(const uint16_t**)text;
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID);
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7426fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
7436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
74672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr -= 1;
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID);
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7546fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
7556fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
75872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7626fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
7636fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
76672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7706fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
7716fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
77472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7786fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
7796fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
78272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
78668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
78768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
78868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
78968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
790fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
79168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
79268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
79368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
79468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharAdvance(uni);
79568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
79668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
79768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getAdvance_utf32_prev(SkGlyphCache* cache,
79868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
79968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
80068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
801fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
80268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
80368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *--ptr;
80468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
80568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharAdvance(uni);
80668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
80768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
8086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
8096fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
81272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDAdvance(glyphID);
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8206fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
8216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
82472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr -= 1;
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDAdvance(glyphID);
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
8336fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                                bool needFullMetrics) const {
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const SkMeasureCacheProc gMeasureCacheProcs[] = {
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_next,
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_next,
83768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_next,
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_next,
83972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_prev,
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_prev,
84268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_prev,
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_prev,
84472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf8_next,
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf16_next,
84768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getAdvance_utf32_next,
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_glyph_next,
84972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf8_prev,
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf16_prev,
85268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getAdvance_utf32_prev,
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_glyph_prev
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
85572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned index = this->getTextEncoding();
8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8586fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (kBackward_TextBufferDirection == tbd) {
85968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        index += 4;
8606fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
8616fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!needFullMetrics && !this->isDevKernText()) {
86268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        index += 8;
8636fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return gMeasureCacheProcs[index];
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
8726fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                        const char** text, SkFixed, SkFixed) {
8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
87572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
8806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                    const char** text, SkFixed x, SkFixed y) {
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
88372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8876fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
8886fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                        const char** text, SkFixed, SkFixed) {
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
89172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
8966fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                     const char** text, SkFixed x, SkFixed y) {
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
89972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    x, y);
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
90468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
90568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                    const char** text, SkFixed, SkFixed) {
90668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
90768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
908fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
90968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
91068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
91168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
91268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharMetrics(uni);
91368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
91468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
91568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
91668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                    const char** text, SkFixed x, SkFixed y) {
91768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
91868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
919fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
92068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
921584f337832d585e23037e59517f7bcc420424692commit-bot@chromium.org    SkUnichar uni = *ptr++;
92268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
9238d38d516c0f17d8d9f6b170055ac05ac181c0554sugoi@google.com    return cache->getUnicharMetrics(uni, x, y);
92468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
92568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
9266fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
9276fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                         const char** text, SkFixed, SkFixed) {
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
93072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID);
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
9396fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                     const char** text, SkFixed x, SkFixed y) {
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
94272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID, x, y);
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9506fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkDrawCacheProc SkPaint::getDrawCacheProc() const {
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const SkDrawCacheProc gDrawCacheProcs[] = {
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_00,
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_00,
95468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_00,
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_00,
95672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_xy,
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_xy,
95968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_xy,
9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_xy
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
96272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned index = this->getTextEncoding();
9646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (fFlags & kSubpixelText_Flag) {
96568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        index += 4;
9666fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
96772cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return gDrawCacheProcs[index];
9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
974ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com#define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE (   \
975ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kDevKernText_Flag          |       \
976ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kLinearText_Flag           |       \
977ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kLCDRenderText_Flag        |       \
978ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kEmbeddedBitmapText_Flag   |       \
979ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kAutoHinting_Flag          |       \
980ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kGenA8FromLCD_Flag )
981ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
982ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkScalar SkPaint::setupForAsPaths() {
983ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    uint32_t flags = this->getFlags();
984ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // clear the flags we don't care about
985ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
986ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // set the flags we do care about
987ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    flags |= SkPaint::kSubpixelText_Flag;
9888f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
989ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setFlags(flags);
990ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setHinting(SkPaint::kNo_Hinting);
9918f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
992ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar textSize = fTextSize;
993ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setTextSize(kCanonicalTextSizeForPaths);
994ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return textSize / kCanonicalTextSizeForPaths;
995ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
996ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
997ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comclass SkCanonicalizePaint {
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
999ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
1000ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        if (paint.isLinearText() || paint.tooBigToUseCache()) {
1001ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            SkPaint* p = fLazy.set(paint);
1002ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            fScale = p->setupForAsPaths();
1003ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            fPaint = p;
1004ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        }
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10066fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com
1007ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& getPaint() const { return *fPaint; }
10088f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
1009ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    /**
1010ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     *  Returns 0 if the paint was unmodified, or the scale factor need to
1011ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     *  the original textSize
1012ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     */
1013ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar getScale() const { return fScale; }
101472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
1016ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint*   fPaint;
1017ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar         fScale;
1018ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkTLazy<SkPaint> fLazy;
10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic void set_bounds(const SkGlyph& g, SkRect* bounds) {
10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->set(SkIntToScalar(g.fLeft),
10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fTop),
10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fLeft + g.fWidth),
10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fTop + g.fHeight));
10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1028e88f551b38c2893566b7016d906b1455e43542f5reed@android.com// 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
1029e88f551b38c2893566b7016d906b1455e43542f5reed@android.com// we don't overflow along the way
1030e88f551b38c2893566b7016d906b1455e43542f5reed@android.comtypedef int64_t Sk48Dot16;
1031e88f551b38c2893566b7016d906b1455e43542f5reed@android.com
10328f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.comstatic inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
10338f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com    return (float) (x * 1.5258789e-5);   // x * (1 / 65536.0f)
10348f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com}
1035e88f551b38c2893566b7016d906b1455e43542f5reed@android.com
103644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
1037e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    SkScalar sx = Sk48Dot16ToScalar(dx);
10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->join(SkIntToScalar(g.fLeft) + sx,
10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fTop),
10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fLeft + g.fWidth) + sx,
10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fTop + g.fHeight));
10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
104444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
104544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    SkScalar sy = Sk48Dot16ToScalar(dy);
104644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    bounds->join(SkIntToScalar(g.fLeft),
104744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fTop) + sy,
104844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fLeft + g.fWidth),
104944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fTop + g.fHeight) + sy);
105044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com}
105144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
105244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comtypedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
105344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
105444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com// xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
105544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic SkFixed advance(const SkGlyph& glyph, int xyIndex) {
105644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    SkASSERT(0 == xyIndex || 1 == xyIndex);
105744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    return (&glyph.fAdvanceX)[xyIndex];
105844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com}
105944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkPaint::measure_text(SkGlyphCache* cache,
10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               const char* text, size_t byteLength,
10626fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                               int* count, SkRect* bounds) const {
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count);
10646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (byteLength == 0) {
10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *count = 0;
10666fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (bounds) {
10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bounds->setEmpty();
10686fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMeasureCacheProc glyphCacheProc;
10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                               NULL != bounds);
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
107644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    int xyIndex;
107744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    JoinBoundsProc joinBoundsProc;
107844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    if (this->isVerticalText()) {
107944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        xyIndex = 1;
108044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        joinBoundsProc = join_bounds_y;
108144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    } else {
108244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        xyIndex = 0;
108344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        joinBoundsProc = join_bounds_x;
108444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    }
108544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int         n = 1;
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = (const char*)text + byteLength;
10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph* g = &glyphCacheProc(cache, &text);
1089e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // our accumulated fixed-point advances might overflow 16.16, so we use
1090e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // a 48.16 (64bit) accumulator, and then convert that to scalar at the
1091e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // very end.
109244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    Sk48Dot16 x = advance(*g, xyIndex);
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoKern  autokern;
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10966fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == bounds) {
10976fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (this->isDevKernText()) {
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rsb;
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rsb = g->fRsbDelta;
11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
110244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
110644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(glyphCacheProc(cache, &text), xyIndex);
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11096fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        set_bounds(*g, bounds);
11116fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (this->isDevKernText()) {
11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rsb;
11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rsb = g->fRsbDelta;
11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
111744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                joinBoundsProc(*g, bounds, x);
111844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(*g, xyIndex);
11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11206fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
112344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                joinBoundsProc(*g, bounds, x);
112444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(*g, xyIndex);
11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text == stop);
11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *count = n;
1131e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    return Sk48Dot16ToScalar(x);
11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkPaint::measureText(const void* textData, size_t length,
11356fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                              SkRect* bounds, SkScalar zoom) const {
11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL || length == 0);
11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1139ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1140ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1141ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
114272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
11436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    SkMatrix zoomMatrix, *zoomPtr = NULL;
11446fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (zoom) {
11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        zoomMatrix.setScale(zoom, zoom);
11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        zoomPtr = &zoomMatrix;
11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1149ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkAutoGlyphCache    autoCache(paint, NULL, zoomPtr);
11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar width = 0;
115372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
11546fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (length > 0) {
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int tempCount;
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1157ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        width = paint.measure_text(cache, text, length, &tempCount, bounds);
11586fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (scale) {
11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            width = SkScalarMul(width, scale);
11606fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if (bounds) {
11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fTop = SkScalarMul(bounds->fTop, scale);
11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fRight = SkScalarMul(bounds->fRight, scale);
11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
116746348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com    } else if (bounds) {
116846348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com        // ensure that even if we don't measure_text we still update the bounds
116946348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com        bounds->setEmpty();
11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return width;
11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef bool (*SkTextBufferPred)(const char* text, const char* stop);
11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11766fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool forward_textBufferPred(const char* text, const char* stop) {
11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return text < stop;
11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool backward_textBufferPred(const char* text, const char* stop) {
11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return text > stop;
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
11856fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                             const char** text, size_t length,
11866fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                             const char** stop) {
11876fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (SkPaint::kForward_TextBufferDirection == tbd) {
11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *stop = *text + length;
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return forward_textBufferPred;
11906fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // text should point to the end of the buffer, and stop to the beginning
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *stop = *text;
11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *text += length;
11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return backward_textBufferPred;
11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comsize_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          SkScalar* measuredWidth,
12006fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                          TextBufferDirection tbd) const {
12016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (0 == length || 0 >= maxWidth) {
12026fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (measuredWidth) {
12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *measuredWidth = 0;
12046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1208c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    if (0 == fTextSize) {
1209c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        if (measuredWidth) {
1210c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com            *measuredWidth = 0;
1211c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        }
1212c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        return length;
1213c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    }
1214c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com
12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(textD != NULL);
12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textD;
12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1218ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1219ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1220ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1222ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // adjust max in case we changed the textSize in paint
1223ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    if (scale) {
1224ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        maxWidth /= scale;
12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
122672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
1227ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1230ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(tbd, false);
12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char*      stop;
12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
1233ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const int        xyIndex = paint.isVerticalText() ? 1 : 0;
1234e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // use 64bits for our accumulator, to avoid overflowing 16.16
1235e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    Sk48Dot16        max = SkScalarToFixed(maxWidth);
1236e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    Sk48Dot16        width = 0;
12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoKern  autokern;
12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12406fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (this->isDevKernText()) {
12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int rsb = 0;
12426fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        while (pred(text, stop)) {
12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const char* curr = text;
12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const SkGlyph& g = glyphCacheProc(cache, &text);
124544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com            SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
12466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if ((width += x) > max) {
12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                width -= x;
12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                text = curr;
12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            rsb = g.fRsbDelta;
12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12536fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
12546fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        while (pred(text, stop)) {
12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const char* curr = text;
125644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com            SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
12576fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if ((width += x) > max) {
12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                width -= x;
12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                text = curr;
12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
126472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
12656fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (measuredWidth) {
1266e88f551b38c2893566b7016d906b1455e43542f5reed@android.com        SkScalar scalarWidth = Sk48Dot16ToScalar(width);
12676fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (scale) {
12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            scalarWidth = SkScalarMul(scalarWidth, scale);
12696fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *measuredWidth = scalarWidth;
12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
127272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return the number of bytes measured
12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (kForward_TextBufferDirection == tbd) ?
12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                text - stop + length : stop - text + length;
12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
12810a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com    *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;   // don't detach the cache
12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
128590808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.comstatic void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
128690808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                                void* context) {
128790808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12906fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1291ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1292ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1293ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
12948f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
12956fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    SkMatrix zoomMatrix, *zoomPtr = NULL;
12966fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (zoom) {
12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        zoomMatrix.setScale(zoom, zoom);
12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        zoomPtr = &zoomMatrix;
12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    FontMetrics storage;
13026fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == metrics) {
13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics = &storage;
13046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
130572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
1306ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (scale) {
13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fTop = SkScalarMul(metrics->fTop, scale);
13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
13140a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
13150a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
13160a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
13170a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
13180bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org        metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
13190bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org        metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return metrics->fDescent - metrics->fAscent + metrics->fLeading;
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13246fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13266fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->set(g.fLeft * scale,
13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g.fTop * scale,
13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (g.fLeft + g.fWidth) * scale,
13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (g.fTop + g.fHeight) * scale);
13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13336fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comint SkPaint::getTextWidths(const void* textData, size_t byteLength,
13346fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                           SkScalar widths[], SkRect bounds[]) const {
13356fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (0 == byteLength) {
13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
13376fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(NULL != textData);
13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13416fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == widths && NULL == bounds) {
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->countText(textData, byteLength);
13436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1345ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1346ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1347ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1349ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMeasureCacheProc  glyphCacheProc;
1352ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    glyphCacheProc = paint.getMeasureCacheProc(kForward_TextBufferDirection,
13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                               NULL != bounds);
13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = text + byteLength;
13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int         count = 0;
1358ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const int   xyIndex = paint.isVerticalText() ? 1 : 0;
13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13606fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (this->isDevKernText()) {
13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we adjust the widths returned here through auto-kerning
13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoKern  autokern;
13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkFixed     prevWidth = 0;
13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (scale) {
13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkFixed  adjust = autokern.adjust(g);
13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if (count > 0) {
13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        SkScalar w = SkFixedToScalar(prevWidth + adjust);
13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        *widths++ = SkScalarMul(w, scale);
13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
137544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    prevWidth = advance(g, xyIndex);
13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++, scale);
13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count > 0 && widths) {
13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkFixed  adjust = autokern.adjust(g);
13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if (count > 0) {
13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        *widths++ = SkFixedToScalar(prevWidth + adjust);
13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
139444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    prevWidth = advance(g, xyIndex);
13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++);
13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count > 0 && widths) {
14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *widths = SkFixedToScalar(prevWidth);
14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no devkern
14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (scale) {
14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
141044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            scale);
14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++, scale);
14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
142244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    *widths++ = SkFixedToScalar(advance(g, xyIndex));
14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++);
14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text == stop);
14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14366fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14406fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::getTextPath(const void* textData, size_t length,
14416fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                          SkScalar x, SkScalar y, SkPath* path) const {
14426fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    SkASSERT(length == 0 || textData != NULL);
14436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com
14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
14456fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (text == NULL || length == 0 || path == NULL) {
14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
14476fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1449166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    SkTextToPathIter    iter(text, length, *this, false);
14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix            matrix;
14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar            prevXPos = 0;
14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setScale(iter.getPathScale(), iter.getPathScale());
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.postTranslate(x, y);
14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path->reset();
14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar        xpos;
14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPath*   iterPath;
14597b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    while (iter.next(&iterPath, &xpos)) {
14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        matrix.postTranslate(xpos - prevXPos, 0);
14617b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (iterPath) {
14627b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            path->addPath(*iterPath, matrix);
14637b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prevXPos = xpos;
14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1468ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.comvoid SkPaint::getPosTextPath(const void* textData, size_t length,
1469ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com                             const SkPoint pos[], SkPath* path) const {
1470ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkASSERT(length == 0 || textData != NULL);
1471ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1472ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    const char* text = (const char*)textData;
1473ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    if (text == NULL || length == 0 || path == NULL) {
1474ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        return;
1475ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    }
1476ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1477ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkTextToPathIter    iter(text, length, *this, false);
1478ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkMatrix            matrix;
1479ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkPoint             prevPos;
1480ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    prevPos.set(0, 0);
1481ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1482ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1483ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    path->reset();
1484ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1485ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    unsigned int    i = 0;
1486ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    const SkPath*   iterPath;
14877b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    while (iter.next(&iterPath, NULL)) {
1488ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
14897b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (iterPath) {
14907b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            path->addPath(*iterPath, matrix);
14917b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
1492ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        prevPos = pos[i];
1493ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        i++;
1494ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    }
1495ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com}
1496ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
14978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void add_flattenable(SkDescriptor* desc, uint32_t tag,
14988b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org                            SkWriteBuffer* buffer) {
14998b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15022739b27d7d13691603d07982ff0d6dd0658bd364reed@google.com// SkFontHost can override this choice in FilterRec()
15036fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic SkMask::Format computeMaskFormat(const SkPaint& paint) {
15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t flags = paint.getFlags();
15058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1506b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org    // Antialiasing being disabled trumps all other settings.
150765dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    if (!(flags & SkPaint::kAntiAlias_Flag)) {
1508b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org        return SkMask::kBW_Format;
1509f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com    }
1510f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com
151165dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    if (flags & SkPaint::kLCDRenderText_Flag) {
1512f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        return SkMask::kLCD16_Format;
151365dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    }
1514b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org
1515b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org    return SkMask::kA8_Format;
15168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15181cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com// if linear-text is on, then we force hinting to be off (since that's sort of
15191cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com// the point of linear-text.
15201cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.comstatic SkPaint::Hinting computeHinting(const SkPaint& paint) {
15211cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    SkPaint::Hinting h = paint.getHinting();
15221cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    if (paint.isLinearText()) {
15231cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        h = SkPaint::kNo_Hinting;
15241cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    }
15251cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    return h;
15261cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com}
15271cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com
15281f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com// return true if the paint is just a single color (i.e. not a shader). If its
15291f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com// a shader, then we can't compute a const luminance for it :(
15301f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.comstatic bool justAColor(const SkPaint& paint, SkColor* color) {
15311f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    if (paint.getShader()) {
15321f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        return false;
15331f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
15341f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    SkColor c = paint.getColor();
15351f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    if (paint.getColorFilter()) {
15361f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        c = paint.getColorFilter()->filterColor(c);
15371f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
15381f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    if (color) {
15391f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        *color = c;
15401f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
15411f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    return true;
15421f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com}
15431f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com
1544ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.comstatic SkColor computeLuminanceColor(const SkPaint& paint) {
1545ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    SkColor c;
1546ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    if (!justAColor(paint, &c)) {
1547ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com        c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1548ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    }
1549ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    return c;
1550ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com}
1551813d38b7a07957f2990ccca52ddab55fe0b1c632reed@google.com
1552dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com#define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
1553dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com
15544f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com// Beyond this size, LCD doesn't appreciably improve quality, but it always
15554f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com// cost more RAM and draws slower, so we set a cap.
1556c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com#ifndef SK_MAX_SIZE_FOR_LCDTEXT
1557c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com    #define SK_MAX_SIZE_FOR_LCDTEXT    48
1558c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com#endif
15594f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com
15604f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.comstatic bool tooBigForLCD(const SkScalerContext::Rec& rec) {
1561e78f7cfced5787f741d0e1a4911b2bea2dfa2f02commit-bot@chromium.org    SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
1562e78f7cfced5787f741d0e1a4911b2bea2dfa2f02commit-bot@chromium.org                    rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
1563e78f7cfced5787f741d0e1a4911b2bea2dfa2f02commit-bot@chromium.org    SkScalar size = SkScalarSqrt(SkScalarAbs(area)) * rec.fTextSize;
1564e78f7cfced5787f741d0e1a4911b2bea2dfa2f02commit-bot@chromium.org    return size > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
15654f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com}
15664f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com
156772cf4927e503f49c4bd07369e85764ddde57071breed@google.com/*
156872cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  Return the scalar with only limited fractional precision. Used to consolidate matrices
156972cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  that vary only slightly when we create our key into the font cache, since the font scaler
157072cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  typically returns the same looking resuts for tiny changes in the matrix.
157172cf4927e503f49c4bd07369e85764ddde57071breed@google.com */
1572f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comstatic SkScalar sk_relax(SkScalar x) {
1573f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int n = sk_float_round2int(x * 1024);
1574f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    return n / 1024.0f;
1575f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
1576f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
157736a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.comvoid SkScalerContext::MakeRec(const SkPaint& paint,
1578532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              const SkDeviceProperties* deviceProperties,
1579532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              const SkMatrix* deviceMatrix,
1580532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              Rec* rec) {
15818d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com    SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
15828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1583cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    SkTypeface* typeface = paint.getTypeface();
1584cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    if (NULL == typeface) {
1585cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com        typeface = SkTypeface::GetDefaultTypeface();
1586cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    }
1587cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    rec->fOrigFontID = typeface->uniqueID();
15887d26c590f6bc431a5ecf5c25619b64d058613a4dreed@google.com    rec->fFontID = rec->fOrigFontID;
15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fTextSize = paint.getTextSize();
15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fPreScaleX = paint.getTextScaleX();
15918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fPreSkewX  = paint.getTextSkewX();
15928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15936fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (deviceMatrix) {
1594f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1595f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1596f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1597f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
15986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
16008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
16018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
160272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint::Style  style = paint.getStyle();
16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar        strokeWidth = paint.getStrokeWidth();
160572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
1606ffe49f5380dd5062073efeda70f2f91682c828careed@google.com    unsigned flags = 0;
16074526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org
16086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isFakeBoldText()) {
16094526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#ifdef SK_USE_FREETYPE_EMBOLDEN
16104526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org        flags |= SkScalerContext::kEmbolden_Flag;
16114526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#else
161228be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
161328be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpKeys,
161428be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpValues,
161528be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpLength);
16168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
161772cf4927e503f49c4bd07369e85764ddde57071breed@google.com
16186fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (style == SkPaint::kFill_Style) {
16198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            style = SkPaint::kStrokeAndFill_Style;
16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
16216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
16228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strokeWidth += extra;
16236fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
16244526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#endif
16258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16276fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isDevKernText()) {
16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkScalerContext::kDevKernText_Flag;
16296fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
163072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
16316fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (style != SkPaint::kFill_Style && strokeWidth > 0) {
16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fFrameWidth = strokeWidth;
16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fMiterLimit = paint.getStrokeMiter();
16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
16358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16366fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (style == SkPaint::kStrokeAndFill_Style) {
16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkScalerContext::kFrameAndFill_Flag;
16386fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
16396fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fFrameWidth = 0;
16418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fMiterLimit = 0;
16428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fStrokeJoin = 0;
16438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
164502b5331078861b02b61e9a93f845617a7c900409reed@google.com    rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
164602b5331078861b02b61e9a93f845617a7c900409reed@google.com
1647532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkDeviceProperties::Geometry geometry = deviceProperties
1648532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                                          ? deviceProperties->fGeometry
1649532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                                          : SkDeviceProperties::Geometry::MakeDefault();
1650532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    if (SkMask::kLCD16_Format == rec->fMaskFormat || SkMask::kLCD32_Format == rec->fMaskFormat) {
1651532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        if (!geometry.isOrientationKnown() || !geometry.isLayoutKnown() || tooBigForLCD(*rec)) {
165202b5331078861b02b61e9a93f845617a7c900409reed@google.com            // eeek, can't support LCD
165302b5331078861b02b61e9a93f845617a7c900409reed@google.com            rec->fMaskFormat = SkMask::kA8_Format;
165402b5331078861b02b61e9a93f845617a7c900409reed@google.com        } else {
1655532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com            if (SkDeviceProperties::Geometry::kVertical_Orientation == geometry.getOrientation()) {
165602b5331078861b02b61e9a93f845617a7c900409reed@google.com                flags |= SkScalerContext::kLCD_Vertical_Flag;
165702b5331078861b02b61e9a93f845617a7c900409reed@google.com            }
1658532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com            if (SkDeviceProperties::Geometry::kBGR_Layout == geometry.getLayout()) {
165902b5331078861b02b61e9a93f845617a7c900409reed@google.com                flags |= SkScalerContext::kLCD_BGROrder_Flag;
166002b5331078861b02b61e9a93f845617a7c900409reed@google.com            }
166102b5331078861b02b61e9a93f845617a7c900409reed@google.com        }
166202b5331078861b02b61e9a93f845617a7c900409reed@google.com    }
166302b5331078861b02b61e9a93f845617a7c900409reed@google.com
16646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isEmbeddedBitmapText()) {
166502b5331078861b02b61e9a93f845617a7c900409reed@google.com        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
16666fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
16676fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isSubpixelText()) {
166802b5331078861b02b61e9a93f845617a7c900409reed@google.com        flags |= SkScalerContext::kSubpixelPositioning_Flag;
16696fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
16706fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isAutohinted()) {
1671f6f56878bc96386882721b15ba610984185d3dc9bungeman@google.com        flags |= SkScalerContext::kForceAutohinting_Flag;
16726fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
1673830a23e39bb4a126e573940cd6e354732e295b10reed@google.com    if (paint.isVerticalText()) {
1674830a23e39bb4a126e573940cd6e354732e295b10reed@google.com        flags |= SkScalerContext::kVertical_Flag;
1675830a23e39bb4a126e573940cd6e354732e295b10reed@google.com    }
16768351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
16778351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com        flags |= SkScalerContext::kGenA8FromLCD_Flag;
16788351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com    }
167902b5331078861b02b61e9a93f845617a7c900409reed@google.com    rec->fFlags = SkToU16(flags);
168036a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com
1681ffe49f5380dd5062073efeda70f2f91682c828careed@google.com    // these modify fFlags, so do them after assigning fFlags
16829d7576724cf9602ff778b18126e0fef0ab3d3bf2reed@google.com    rec->setHinting(computeHinting(paint));
168397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
1684ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    rec->setLuminanceColor(computeLuminanceColor(paint));
1685532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1686532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    if (NULL == deviceProperties) {
1687532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1688532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        rec->setPaintGamma(SK_GAMMA_EXPONENT);
1689532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    } else {
1690532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        rec->setDeviceGamma(deviceProperties->fGamma);
1691532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1692532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //For now always set the paint gamma equal to the device gamma.
1693532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //The math in SkMaskGamma can handle them being different,
1694532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //but it requires superluminous masks when
1695532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
1696532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        rec->setPaintGamma(deviceProperties->fGamma);
1697532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    }
1698532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1699532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com#ifdef SK_GAMMA_CONTRAST
1700532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    rec->setContrast(SK_GAMMA_CONTRAST);
1701ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com#else
1702532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    /**
1703532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
1704532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * With lower values small text appears washed out (though correctly so).
1705532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * With higher values lcd fringing is worse and the smoothing effect of
1706532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * partial coverage is diminished.
1707532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     */
17084b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    rec->setContrast(0.5f);
1709ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com#endif
1710532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
17112bf82d843d8896dd10bb86adc1e974c6d52324e6bungeman@google.com    rec->fReservedAlign = 0;
1712fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
171336a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com    /*  Allow the fonthost to modify our rec before we use it as a key into the
171436a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        cache. This way if we're asking for something that they will ignore,
171536a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        they can modify our rec up front, so we don't create duplicate cache
171636a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        entries.
171736a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com     */
1718fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com    typeface->onFilterRec(rec);
17193e8ae5b457558435218a864dd0e852f83abfe802reed@google.com
172010d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    // be sure to call PostMakeRec(rec) before you actually use it!
172110d2d4d1062ef56526f187e6716c5e747689b598reed@google.com}
172210d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
172310d2d4d1062ef56526f187e6716c5e747689b598reed@google.com/**
172497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
172597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
172697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * to hold it until the returned pointer is refed or forgotten.
172710d2d4d1062ef56526f187e6716c5e747689b598reed@google.com */
172897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comSK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
172910d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
1730ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.comstatic SkMaskGamma* gLinearMaskGamma = NULL;
1731b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkMaskGamma* gMaskGamma = NULL;
1732b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gContrast = SK_ScalarMin;
1733b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gPaintGamma = SK_ScalarMin;
1734b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gDeviceGamma = SK_ScalarMin;
173597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
173697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
173797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * the returned SkMaskGamma pointer is refed or forgotten.
173897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
1739a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comstatic const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
1740b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein    gMaskGammaCacheMutex.assertHeld();
1741ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1742ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com        if (NULL == gLinearMaskGamma) {
1743ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com            gLinearMaskGamma = SkNEW(SkMaskGamma);
1744ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com        }
1745a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        return *gLinearMaskGamma;
1746ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    }
174797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
174897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        SkSafeUnref(gMaskGamma);
1749b1a72cb90a9b515978bc9abda1f267f31a544e08bungeman@google.com        gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
175097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gContrast = contrast;
175197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gPaintGamma = paintGamma;
175297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gDeviceGamma = deviceGamma;
175397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    }
1754a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    return *gMaskGamma;
175597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com}
175697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
1757b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com/*static*/ void SkPaint::Term() {
1758b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1759b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com
1760ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    SkSafeUnref(gLinearMaskGamma);
17615987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com    gLinearMaskGamma = NULL;
1762b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkSafeUnref(gMaskGamma);
17635987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com    gMaskGamma = NULL;
1764b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gContrast = SK_ScalarMin;)
1765b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
1766b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
1767b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com}
1768b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com
176997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
177097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com *  We ensure that the rec is self-consistent and efficient (where possible)
177197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
17728d38d516c0f17d8d9f6b170055ac05ac181c0554sugoi@google.comvoid SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
177310d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    /**
177410d2d4d1062ef56526f187e6716c5e747689b598reed@google.com     *  If we're asking for A8, we force the colorlum to be gray, since that
177597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com     *  limits the number of unique entries, and the scaler will only look at
177697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com     *  the lum of one of them.
177710d2d4d1062ef56526f187e6716c5e747689b598reed@google.com     */
1778dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com    switch (rec->fMaskFormat) {
1779dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kLCD16_Format:
1780dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kLCD32_Format: {
1781dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // filter down the luminance color to a finite number of bits
178297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            SkColor color = rec->getLuminanceColor();
1783b5715a1c8003e4a8af2301ab44aeef043547808ereed@google.com            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1784dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
1785dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        }
1786dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kA8_Format: {
1787dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // filter down the luminance to a single component, since A8 can't
1788dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // use per-component information
1789fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
179097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            SkColor color = rec->getLuminanceColor();
1791b1a72cb90a9b515978bc9abda1f267f31a544e08bungeman@google.com            U8CPU lum = SkColorSpaceLuminance::computeLuminance(rec->getPaintGamma(), color);
1792fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com            //If we are asked to look like LCD, look like LCD.
1793fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com            if (!(rec->fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
1794fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com                // HACK: Prevents green from being pre-blended as white.
1795fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com                lum -= ((255 - lum) * lum) / 255;
1796fd668cfffe3fdcfbf6e0b858343a62818d337590bungeman@google.com            }
1797fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1798dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // reduce to our finite number of bits
179997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            color = SkColorSetRGB(lum, lum, lum);
1800b5715a1c8003e4a8af2301ab44aeef043547808ereed@google.com            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1801dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
1802dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        }
1803dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kBW_Format:
1804dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // No need to differentiate gamma if we're BW
1805532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com            rec->ignorePreBlend();
1806dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
18073e8ae5b457558435218a864dd0e852f83abfe802reed@google.com    }
18088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
18098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MIN_SIZE_FOR_EFFECT_BUFFER  1024
18118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
181217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#ifdef SK_DEBUG
181317fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com    #define TEST_DESC
181417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#endif
181517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com
1816ffe49f5380dd5062073efeda70f2f91682c828careed@google.com/*
1817ffe49f5380dd5062073efeda70f2f91682c828careed@google.com *  ignoreGamma tells us that the caller just wants metrics that are unaffected
18182d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth *  by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
18192d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth *  contrast = 0, luminanceColor = transparent black.
1820ffe49f5380dd5062073efeda70f2f91682c828careed@google.com */
1821532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.comvoid SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
1822532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                             const SkMatrix* deviceMatrix,
182390808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                             void (*proc)(SkTypeface*, const SkDescriptor*, void*),
182457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com                             void* context, bool ignoreGamma) const {
18258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalerContext::Rec    rec;
18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1827532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkScalerContext::MakeRec(*this, deviceProperties, deviceMatrix, &rec);
182857f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    if (ignoreGamma) {
18292d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth        rec.ignorePreBlend();
183057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    }
18318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t          descSize = sizeof(rec);
18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int             entryCount = 1;
18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect*   pe = this->getPathEffect();
18358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMaskFilter*   mf = this->getMaskFilter();
18368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRasterizer*   ra = this->getRasterizer();
18378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18388b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkWriteBuffer    peBuffer, mfBuffer, raBuffer;
18398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (pe) {
18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        peBuffer.writeFlattenable(pe);
18428b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org        descSize += peBuffer.bytesWritten();
18438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // seems like we could support kLCD as well at this point...
18468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mf) {
18488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        mfBuffer.writeFlattenable(mf);
18498b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org        descSize += mfBuffer.bytesWritten();
18508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
18518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
1852a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        /* Pre-blend is not currently applied to filtered text.
1853a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           The primary filter is blur, for which contrast makes no sense,
1854a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           and for which the destination guess error is more visible.
1855a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           Also, all existing users of blur have calibrated for linear. */
1856a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        rec.ignorePreBlend();
18578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (ra) {
18598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        raBuffer.writeFlattenable(ra);
18608b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org        descSize += raBuffer.bytesWritten();
18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
18628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
18638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
186410d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
1865c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
18668b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkWriteBuffer androidBuffer;
1867c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org    fPaintOptionsAndroid.flatten(androidBuffer);
18688b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    descSize += androidBuffer.bytesWritten();
1869c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org    entryCount += 1;
1870c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org#endif
1871c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org
187210d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    ///////////////////////////////////////////////////////////////////////////
187310d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    // Now that we're done tweaking the rec, call the PostMakeRec cleanup
187497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    SkScalerContext::PostMakeRec(*this, &rec);
1875fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
18768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    descSize += SkDescriptor::ComputeOverhead(entryCount);
18778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoDescriptor    ad(descSize);
18798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDescriptor*       desc = ad.getDesc();
18808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    desc->init();
18828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
18838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1884c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
1885c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org    add_flattenable(desc, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1886c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org#endif
1887c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org
18888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (pe) {
18898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
18908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mf) {
18928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
18938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (ra) {
18958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
18968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
18978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(descSize == desc->getLength());
18998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    desc->computeChecksum();
19008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
190117fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#ifdef TEST_DESC
190217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com    {
190317fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // Check that we completely write the bytes in desc (our key), and that
190417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // there are no uninitialized bytes. If there were, then we would get
190517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // false-misses (or worse, false-hits) in our fontcache.
190617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        //
190717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // We do this buy filling 2 others, one with 0s and the other with 1s
190817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        // and create those, and then check that all 3 are identical.
190917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkAutoDescriptor    ad1(descSize);
191017fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkAutoDescriptor    ad2(descSize);
191117fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkDescriptor*       desc1 = ad1.getDesc();
191217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkDescriptor*       desc2 = ad2.getDesc();
1913fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
191417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        memset(desc1, 0x00, descSize);
191517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        memset(desc2, 0xFF, descSize);
1916fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
191717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc1->init();
191817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc2->init();
191917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
192017fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1921fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1922c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
1923c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org        add_flattenable(desc1, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1924c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org        add_flattenable(desc2, kAndroidOpts_SkDescriptorTag, &androidBuffer);
1925c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org#endif
1926c7a20e40938ae031368e3a9e4df33ce90a765abacommit-bot@chromium.org
192717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        if (pe) {
192817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
192917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
193017fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        }
193117fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        if (mf) {
193217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
193317fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
193417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        }
193517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        if (ra) {
193617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
193717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com            add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
193817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        }
1939fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
194017fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkASSERT(descSize == desc1->getLength());
194117fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkASSERT(descSize == desc2->getLength());
194217fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc1->computeChecksum();
194317fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        desc2->computeChecksum();
194417fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkASSERT(!memcmp(desc, desc1, descSize));
194517fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com        SkASSERT(!memcmp(desc, desc2, descSize));
194617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com    }
194717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#endif
1948fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
194990808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    proc(fTypeface, desc, context);
19508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1952532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.comSkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
19532d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                   const SkMatrix* deviceMatrix,
19542d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                   bool ignoreGamma) const {
19558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache* cache;
19562d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma);
19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache;
19588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
196097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
196197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
196297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
196397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com//static
196497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comSkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
196597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1966a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
1967a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com                                                   rec.getPaintGamma(),
1968a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com                                                   rec.getDeviceGamma());
1969a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    return maskGamma.preBlend(rec.getLuminanceColor());
197097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com}
197197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
19722d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthsize_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
19732d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        SkScalar deviceGamma, int* width, int* height) {
19742d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
19752d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
19762d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   paintGamma,
19772d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   deviceGamma);
19782d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19792d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    maskGamma.getGammaTableDimensions(width, height);
19802d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    size_t size = (*width)*(*height)*sizeof(uint8_t);
19812d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19822d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    return size;
19832d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth}
19842d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19852d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthvoid SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
19862d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                      void* data) {
19872d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
19882d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
19892d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   paintGamma,
19902d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   deviceGamma);
19912d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    int width, height;
19922d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    maskGamma.getGammaTableDimensions(&width, &height);
19932d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    size_t size = width*height*sizeof(uint8_t);
19942d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const uint8_t* gammaTables = maskGamma.getGammaTables();
19952d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    memcpy(data, gammaTables, size);
19962d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth}
19972d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19982d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
19998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2003aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uintptr_t asint(const void* p) {
2004aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return reinterpret_cast<uintptr_t>(p);
2005aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
2006aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2007aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comunion Scalar32 {
2008aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkScalar    fScalar;
2009aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    uint32_t    f32;
2010aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com};
2011aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2012aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
2013aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
2014aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    Scalar32 tmp;
2015aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    tmp.fScalar = value;
2016aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    *ptr = tmp.f32;
2017aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return ptr + 1;
2018aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
2019aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2020aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic SkScalar read_scalar(const uint32_t*& ptr) {
2021aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
2022aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    Scalar32 tmp;
2023aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    tmp.f32 = *ptr++;
2024aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return tmp.fScalar;
2025aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
2026aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2027aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
2028aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(a == (uint8_t)a);
2029aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(b == (uint8_t)b);
2030aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(c == (uint8_t)c);
2031aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(d == (uint8_t)d);
2032aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return (a << 24) | (b << 16) | (c << 8) | d;
2033aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
2034aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
203585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#ifdef SK_DEBUG
203685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
203785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        SkASSERT(bitCount > 0 && bitCount <= 32);
203885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        uint32_t mask = ~0U;
203985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        mask >>= (32 - bitCount);
204085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        SkASSERT(0 == (value & ~mask));
204185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
204285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#else
204385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    #define ASSERT_FITS_IN(value, bitcount)
204485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#endif
204585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
2046aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comenum FlatFlags {
204797f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    kHasTypeface_FlatFlag                      = 0x01,
204897f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    kHasEffects_FlatFlag                       = 0x02,
204997f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    kHasNonDefaultPaintOptionsAndroid_FlatFlag = 0x04,
2050667b98d947892cec939669bccf204ab9ed565c4eskia.committer@gmail.com
205185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFlatFlagMask = 0x7,
205285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org};
205385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
205485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgenum BitsPerField {
205585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFlags_BPF  = 16,
205685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kHint_BPF   = 2,
205785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kAlign_BPF  = 2,
205885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFilter_BPF = 2,
205985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFlatFlags_BPF  = 3,
2060aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com};
2061aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
206285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic inline int BPF_Mask(int bits) {
206385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (1 << bits) - 1;
206485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
206585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
206685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
206785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org                                 unsigned filter, unsigned flatFlags) {
206885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(flags, kFlags_BPF);
206985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(hint, kHint_BPF);
207085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(align, kAlign_BPF);
207185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(filter, kFilter_BPF);
207285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
207385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
207485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
207585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // add more bits in the future.
207685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
207785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
207885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
207985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
208085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFlags(packed >> 16);
208185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
208285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
208385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFilterLevel((SkPaint::FilterLevel)((packed >> 10) & BPF_Mask(kFilter_BPF)));
208485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (FlatFlags)(packed & kFlatFlagMask);
208585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
208685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
208785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org// V22_COMPATIBILITY_CODE
208885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic FlatFlags unpack_paint_flags_v22(SkPaint* paint, uint32_t packed) {
208985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    enum {
209085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        kFilterBitmap_Flag    = 0x02,
209185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        kHighQualityFilterBitmap_Flag = 0x4000,
2092667b98d947892cec939669bccf204ab9ed565c4eskia.committer@gmail.com
209385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        kAll_Flags = kFilterBitmap_Flag | kHighQualityFilterBitmap_Flag
209485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    };
209585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
209685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // previously flags:16, textAlign:8, flatFlags:8
209785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // now flags:16, hinting:4, textAlign:4, flatFlags:8
209885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    unsigned flags = packed >> 16;
209985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    int filter = 0;
210085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    if (flags & kFilterBitmap_Flag) {
210185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        filter |= 1;
210285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
210385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    if (flags & kHighQualityFilterBitmap_Flag) {
210485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        filter |= 2;
210585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
210685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFilterLevel((SkPaint::FilterLevel)filter);
210785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    flags &= ~kAll_Flags;   // remove these (now dead) bit flags
210885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
210985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFlags(flags);
2110667b98d947892cec939669bccf204ab9ed565c4eskia.committer@gmail.com
211185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // hinting added later. 0 in this nibble means use the default.
211285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    uint32_t hinting = (packed >> 12) & 0xF;
211385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setHinting(0 == hinting ? SkPaint::kNormal_Hinting : static_cast<SkPaint::Hinting>(hinting-1));
211485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setTextAlign(static_cast<SkPaint::Align>((packed >> 8) & 0xF));
211585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (FlatFlags)(packed & kFlatFlagMask);
211685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
211785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
2118aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com// The size of a flat paint's POD fields
2119d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comstatic const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
21201f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        1 * sizeof(SkColor) +
21211f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        1 * sizeof(uint16_t) +
21221f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        6 * sizeof(uint8_t);
2123aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2124aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com/*  To save space/time, we analyze the paint, and write a truncated version of
2125aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    it if there are not tricky elements like shaders, etc.
2126aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com */
21278b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPaint::flatten(SkWriteBuffer& buffer) const {
2128aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    uint8_t flatFlags = 0;
2129aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (this->getTypeface()) {
2130aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        flatFlags |= kHasTypeface_FlatFlag;
2131aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
2132aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (asint(this->getPathEffect()) |
2133aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getShader()) |
2134aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getXfermode()) |
2135aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getMaskFilter()) |
2136aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getColorFilter()) |
2137aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getRasterizer()) |
213854e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        asint(this->getLooper()) |
2139b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com        asint(this->getAnnotation()) |
214054e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        asint(this->getImageFilter())) {
2141aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        flatFlags |= kHasEffects_FlatFlag;
2142aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
214380f3fcd2554c39987323946306ff32273164ea6acommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
214497f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    if (this->getPaintOptionsAndroid() != SkPaintOptionsAndroid()) {
214597f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org        flatFlags |= kHasNonDefaultPaintOptionsAndroid_FlatFlag;
214697f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    }
214797f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org#endif
2148c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com
21498b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
21508b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    uint32_t* ptr = buffer.reserve(kPODPaintSize);
21518b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
21528b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextSize());
21538b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextScaleX());
21548b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextSkewX());
21558b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getStrokeWidth());
21568b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getStrokeMiter());
21578b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    *ptr++ = this->getColor();
215885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
215985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
216085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org                              this->getFilterLevel(), flatFlags);
21618b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
21628b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org                    this->getStyle(), this->getTextEncoding());
2163aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2164aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    // now we're done with ptr and the (pre)reserved space. If we need to write
2165aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    // additional fields, use the buffer directly
2166aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasTypeface_FlatFlag) {
2167aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeTypeface(this->getTypeface());
2168aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
2169aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasEffects_FlatFlag) {
2170aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getPathEffect());
2171aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getShader());
2172aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getXfermode());
2173aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getMaskFilter());
2174aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getColorFilter());
2175aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getRasterizer());
2176aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getLooper());
217754e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        buffer.writeFlattenable(this->getImageFilter());
21780cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com
21790cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        if (fAnnotation) {
21800cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            buffer.writeBool(true);
21810cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            fAnnotation->writeToBuffer(buffer);
21820cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        } else {
21830cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            buffer.writeBool(false);
21840cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        }
2185aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
218680f3fcd2554c39987323946306ff32273164ea6acommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
218797f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
218897f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org        this->getPaintOptionsAndroid().flatten(buffer);
218997f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    }
219097f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org#endif
21918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21938b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPaint::unflatten(SkReadBuffer& buffer) {
21948b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
21958b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    const void* podData = buffer.skip(kPODPaintSize);
21968b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
21978b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
21988b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    // the order we read must match the order we wrote in flatten()
21998b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextSize(read_scalar(pod));
22008b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextScaleX(read_scalar(pod));
22018b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextSkewX(read_scalar(pod));
22028b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeWidth(read_scalar(pod));
22038b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeMiter(read_scalar(pod));
22048b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setColor(*pod++);
22058b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
220685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    unsigned flatFlags = 0;
22077ed173b1ebac84671fb0dc1b9bd323a5e6e63771commit-bot@chromium.org    if (buffer.isVersionLT(SkReadBuffer::kFilterLevelIsEnum_Version)) {
220885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        flatFlags = unpack_paint_flags_v22(this, *pod++);
220985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    } else {
221085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        flatFlags = unpack_paint_flags(this, *pod++);
221185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
22128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
221385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    uint32_t tmp = *pod++;
22148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
22158b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
22168b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
22178b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
2218aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2219aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasTypeface_FlatFlag) {
2220aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setTypeface(buffer.readTypeface());
2221aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    } else {
2222aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setTypeface(NULL);
2223aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
2224aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
2225aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasEffects_FlatFlag) {
2226353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
2227353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setShader(buffer.readShader()));
2228353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setXfermode(buffer.readXfermode()));
2229353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
2230353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
2231353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
2232353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
2233353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
2234fbc58a305518fe611113a51649bf557c991ac8cfskia.committer@gmail.com
22350cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        if (buffer.readBool()) {
2236d957984c1efbd18f3b2bbeca78d282837c5a2ae1commit-bot@chromium.org            this->setAnnotation(SkAnnotation::Create(buffer))->unref();
22370cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        }
2238aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    } else {
2239aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setPathEffect(NULL);
2240aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setShader(NULL);
2241aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setXfermode(NULL);
2242aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setMaskFilter(NULL);
2243aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setColorFilter(NULL);
2244aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setRasterizer(NULL);
2245aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setLooper(NULL);
224654e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        this->setImageFilter(NULL);
2247aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
224897f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org
224980f3fcd2554c39987323946306ff32273164ea6acommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
225097f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    this->setPaintOptionsAndroid(SkPaintOptionsAndroid());
225197f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org#endif
225297f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    if (flatFlags & kHasNonDefaultPaintOptionsAndroid_FlatFlag) {
225397f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org        SkPaintOptionsAndroid options;
225497f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org        options.unflatten(buffer);
225580f3fcd2554c39987323946306ff32273164ea6acommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
225697f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org        this->setPaintOptionsAndroid(options);
225797f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org#endif
225897f8167622473edf2e4262fa619883e616574c19commit-bot@chromium.org    }
22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
22628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
226382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkShader* SkPaint::setShader(SkShader* shader) {
2264f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(shader != fShader);
22658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fShader, shader);
2266aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kShader_DirtyBit, shader != NULL);
22678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return shader;
22688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
227082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
2271f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(filter != fColorFilter);
22728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fColorFilter, filter);
2273aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kColorFilter_DirtyBit, filter != NULL);
22748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
227782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
2278f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(mode != fXfermode);
22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fXfermode, mode);
2280aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, mode != NULL);
22818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return mode;
22828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22840baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.comSkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
2285d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    SkSafeUnref(fXfermode);
2286d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    fXfermode = SkXfermode::Create(mode);
2287f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC;
2288aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kXfermode_DirtyBit, fXfermode != NULL);
2289d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    return fXfermode;
2290d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com}
2291d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com
229282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
2293f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(effect != fPathEffect);
22948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fPathEffect, effect);
2295aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kPathEffect_DirtyBit, effect != NULL);
22968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return effect;
22978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
229982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
2300f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    GEN_ID_INC_EVAL(filter != fMaskFilter);
23018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMaskFilter, filter);
2302aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fDirtyBits = set_mask(fDirtyBits, kMaskFilter_DirtyBit, filter != NULL);
23038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
23048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
230682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
23078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23084bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.combool SkPaint::getFillPath(const SkPath& src, SkPath* dst,
23094bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com                          const SkRect* cullRect) const {
2310fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    SkStrokeRec rec(*this);
23118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2312fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    const SkPath* srcPtr = &src;
2313fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    SkPath tmpPath;
231472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
23154bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com    if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
2316fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        srcPtr = &tmpPath;
23178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2319fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    if (!rec.applyToPath(dst, *srcPtr)) {
2320fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        if (srcPtr == &tmpPath) {
2321fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // If path's were copy-on-write, this trick would not be needed.
2322fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // As it is, we want to save making a deep-copy from tmpPath -> dst
2323fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // since we know we're just going to delete tmpPath when we return,
2324fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // so the swap saves that copy.
2325fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            dst->swap(tmpPath);
2326fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        } else {
2327fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            *dst = *srcPtr;
2328d3521f1a8dc07fe84d6a8f2151b0c176ff1ec8careed@google.com        }
2329d3521f1a8dc07fe84d6a8f2151b0c176ff1ec8careed@google.com    }
2330fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    return !rec.isHairlineStyle();
23318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2333e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.comconst SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
2334a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com                                           SkRect* storage,
2335a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com                                           Style style) const {
23368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(storage);
23379efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2338e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    const SkRect* src = &origSrc;
2339e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com
23409efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    if (this->getLooper()) {
23419efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2342e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        this->getLooper()->computeFastBounds(*this, *src, storage);
23439efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        return *storage;
23449efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    }
23459efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2346e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    SkRect tmpSrc;
2347e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    if (this->getPathEffect()) {
2348e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2349e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        src = &tmpSrc;
2350e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    }
2351e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com
2352a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (kFill_Style != style) {
23539efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        // since we're stroked, outset the rect by the radius (and join type)
23549efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkScalar radius = SkScalarHalf(this->getStrokeWidth());
23559efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (0 == radius) {  // hairline
23569efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            radius = SK_Scalar1;
23579efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
23589efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            SkScalar scale = this->getStrokeMiter();
23599efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            if (scale > SK_Scalar1) {
23609efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com                radius = SkScalarMul(radius, scale);
23619efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            }
23628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2363e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        storage->set(src->fLeft - radius, src->fTop - radius,
2364e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com                     src->fRight + radius, src->fBottom + radius);
23659efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    } else {
2366e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        *storage = *src;
23678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23689efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
23699efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    if (this->getMaskFilter()) {
23709efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        this->getMaskFilter()->computeFastBounds(*storage, storage);
23719efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    }
23729efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2373336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (this->getImageFilter()) {
2374336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        this->getImageFilter()->computeFastBounds(*storage, storage);
2375336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
2376336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
2377d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    return *storage;
23788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23800f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
2381791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.comvoid SkPaint::toString(SkString* str) const {
2382791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2383791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2384791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkTypeface* typeface = this->getTypeface();
2385791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != typeface) {
2386791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkDynamicMemoryWStream ostream;
2387791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        typeface->serialize(&ostream);
2388791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAutoTUnref<SkData> data(ostream.copyToData());
2389791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2390791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkMemoryStream stream(data);
2391791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkFontDescriptor descriptor(&stream);
2392791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2393791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Font Family Name:</dt><dd>");
2394791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getFamilyName());
2395791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd><dt>Font Full Name:</dt><dd>");
2396791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getFullName());
2397791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd><dt>Font PS Name:</dt><dd>");
2398791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getPostscriptName());
2399791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd><dt>Font File Name:</dt><dd>");
2400791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getFontFileName());
2401791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2402791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2403791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2404791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextSize:</dt><dd>");
2405791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextSize());
2406791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2407791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2408791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextScaleX:</dt><dd>");
2409791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextScaleX());
2410791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2411791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2412791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextSkewX:</dt><dd>");
2413791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextSkewX());
2414791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2415791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2416791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkPathEffect* pathEffect = this->getPathEffect();
2417791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != pathEffect) {
2418791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>PathEffect:</dt><dd>");
2419791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2420791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2421791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2422791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkShader* shader = this->getShader();
2423791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != shader) {
2424791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Shader:</dt><dd>");
24251202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        shader->toString(str);
2426791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2427791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2428791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2429791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkXfermode* xfer = this->getXfermode();
2430791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != xfer) {
2431791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Xfermode:</dt><dd>");
24321202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        xfer->toString(str);
2433791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2434791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2435791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2436791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkMaskFilter* maskFilter = this->getMaskFilter();
2437791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != maskFilter) {
2438791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>MaskFilter:</dt><dd>");
24391202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        maskFilter->toString(str);
2440791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2441791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2442791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2443791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkColorFilter* colorFilter = this->getColorFilter();
2444791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != colorFilter) {
2445791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>ColorFilter:</dt><dd>");
24461202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        colorFilter->toString(str);
2447791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2448791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2449791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2450791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkRasterizer* rasterizer = this->getRasterizer();
2451791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != rasterizer) {
2452791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Rasterizer:</dt><dd>");
2453791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2454791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2455791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2456791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkDrawLooper* looper = this->getLooper();
2457791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != looper) {
2458791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>DrawLooper:</dt><dd>");
24591202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        looper->toString(str);
2460791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2461791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2462791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2463791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkImageFilter* imageFilter = this->getImageFilter();
2464791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != imageFilter) {
2465791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>ImageFilter:</dt><dd>");
2466791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2467791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2468791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2469791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkAnnotation* annotation = this->getAnnotation();
2470791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (NULL != annotation) {
2471791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Annotation:</dt><dd>");
2472791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2473791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2474791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2475791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Color:</dt><dd>0x");
2476791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkColor color = this->getColor();
2477791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendHex(color);
2478791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2479791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2480791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Stroke Width:</dt><dd>");
2481791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getStrokeWidth());
2482791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2483791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2484791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Stroke Miter:</dt><dd>");
2485791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getStrokeMiter());
2486791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2487791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2488791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Flags:</dt><dd>(");
2489791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (this->getFlags()) {
2490791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        bool needSeparator = false;
2491791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
2492791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
2493791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
2494791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
2495791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
2496791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
2497791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
2498791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
2499791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
2500791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isEmbeddedBitmapText(),
2501791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com                          "EmbeddedBitmapText", &needSeparator);
2502791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
2503791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
2504791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
2505791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com                          "GenA8FromLCD", &needSeparator);
2506791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    } else {
2507791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("None");
2508791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2509791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(")</dd>");
2510791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
25113e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    str->append("<dt>FilterLevel:</dt><dd>");
25123e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" };
25133e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    str->append(gFilterLevelStrings[this->getFilterLevel()]);
25143e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    str->append("</dd>");
25153e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com
2516791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextAlign:</dt><dd>");
2517791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
2518791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gTextAlignStrings[this->getTextAlign()]);
2519791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2520791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2521791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>CapType:</dt><dd>");
2522791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
2523791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gStrokeCapStrings[this->getStrokeCap()]);
2524791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2525791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2526791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>JoinType:</dt><dd>");
2527791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
2528791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gJoinStrings[this->getStrokeJoin()]);
2529791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2530791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2531791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Style:</dt><dd>");
2532791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
2533791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gStyleStrings[this->getStyle()]);
2534791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2535791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2536791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextEncoding:</dt><dd>");
2537791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
2538791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gTextEncodingStrings[this->getTextEncoding()]);
2539791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2540791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2541791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Hinting:</dt><dd>");
2542791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
2543791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gHintingStrings[this->getHinting()]);
2544791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2545791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2546791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd></dl></dl>");
2547791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com}
2548791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#endif
2549791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
25506fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
25518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25526fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool has_thick_frame(const SkPaint& paint) {
25536fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    return  paint.getStrokeWidth() > 0 &&
25546fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            paint.getStyle() != SkPaint::kFill_Style;
25558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
25568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
25588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    const SkPaint& paint,
2559166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com                                    bool applyStrokeAndPathEffects)
2560166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com                                    : fPaint(paint) {
25618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
25628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                                true);
25638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2564166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    fPaint.setLinearText(true);
25658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
25668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25676fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
25688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        applyStrokeAndPathEffects = false;
25696fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
25708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2571166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    // can't use our canonical size if we need to apply patheffects
2572166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    if (fPaint.getPathEffect() == NULL) {
25738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
25748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2575166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com        if (has_thick_frame(fPaint)) {
2576166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com            fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
2577166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com        }
25786fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
25798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fScale = SK_Scalar1;
25806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
258172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
25826fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!applyStrokeAndPathEffects) {
25838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setStyle(SkPaint::kFill_Style);
25848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setPathEffect(NULL);
25858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25872d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    fCache = fPaint.detachCache(NULL, NULL, false);
25888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint::Style  style = SkPaint::kFill_Style;
25908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect*   pe = NULL;
25918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25926fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!applyStrokeAndPathEffects) {
25938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        style = paint.getStyle();   // restore
25948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        pe = paint.getPathEffect();     // restore
25958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
25968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setStyle(style);
25978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setPathEffect(pe);
25988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setMaskFilter(paint.getMaskFilter());    // restore
25998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now compute fXOffset if needed
26018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar xOffset = 0;
26036fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
26048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int      count;
26056fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
26066fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                                         &count, NULL), fScale);
26076fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
26088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            width = SkScalarHalf(width);
26096fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
26108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        xOffset = -width;
26118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXPos = xOffset;
26138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPrevAdvance = 0;
26148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fText = text;
26168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStop = text + length;
26177b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com
261844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    fXYIndex = paint.isVerticalText() ? 1 : 0;
26198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkTextToPathIter::~SkTextToPathIter() {
26228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache::AttachCache(fCache);
26238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
26248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26257b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.combool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
26267b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    if (fText < fStop) {
26278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
26288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
263044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
26318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26326fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (glyph.fWidth) {
26337b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            if (path) {
26347b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com                *path = fCache->findPath(glyph);
26357b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            }
26367b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        } else {
26377b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            if (path) {
26387b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com                *path = NULL;
26396fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            }
26408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
26417b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (xpos) {
26427b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            *xpos = fXPos;
26437b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
26447b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        return true;
26458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26467b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    return false;
26478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2648dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com
2649dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com///////////////////////////////////////////////////////////////////////////////
2650dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com
2651dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.combool SkPaint::nothingToDraw() const {
2652733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com    if (fLooper) {
2653733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com        return false;
2654733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com    }
2655dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    SkXfermode::Mode mode;
2656dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    if (SkXfermode::AsMode(fXfermode, &mode)) {
2657dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com        switch (mode) {
2658dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kSrcOver_Mode:
2659dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kSrcATop_Mode:
2660dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDstOut_Mode:
2661dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDstOver_Mode:
2662dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kPlus_Mode:
2663dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com                return 0 == this->getAlpha();
2664dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDst_Mode:
2665dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com                return true;
2666dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            default:
2667dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com                break;
2668dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com        }
2669dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    }
2670dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    return false;
2671dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com}
2672aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2673aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orgvoid SkPaint::setBitfields(uint32_t bitfields) {
2674aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fBitfields = bitfields;
2675aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org}
2676aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2677aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orginline static unsigned popcount(uint8_t x) {
2678aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    // As in Hacker's delight, adapted for just 8 bits.
2679aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-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
2680aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-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
2681aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-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
2682aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    return x;
2683aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org}
2684aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2685aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orgvoid SkPaint::FlatteningTraits::Flatten(SkWriteBuffer& buffer, const SkPaint& paint) {
2686aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    const uint32_t dirty = paint.fDirtyBits;
2687aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
268845d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    // Each of the low 7 dirty bits corresponds to a 4-byte flat value,
268945d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    // plus one for the dirty bits and one for the bitfields
269045d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    const size_t flatBytes = 4 * (popcount(dirty & kPOD_DirtyBitMask) + 2);
2691aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    SkASSERT(flatBytes <= 32);
2692aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    uint32_t* u32 = buffer.reserve(flatBytes);
2693aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    *u32++ = dirty;
269445d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    *u32++ = paint.getBitfields();
269545d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    if (0 == dirty) {
2696aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        return;
2697aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    }
2698aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2699aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#define F(dst, field) if (dirty & k##field##_DirtyBit) *dst++ = paint.get##field()
2700aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(u32, Color);
2701aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    SkScalar* f32 = reinterpret_cast<SkScalar*>(u32);
2702aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, TextSize);
2703aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, TextScaleX);
2704aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, TextSkewX);
2705aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, StrokeWidth);
2706aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(f32, StrokeMiter);
2707aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#undef F
2708aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#define F(field) if (dirty & k##field##_DirtyBit) buffer.writeFlattenable(paint.get##field())
2709aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(PathEffect);
2710aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Shader);
2711aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Xfermode);
2712aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(MaskFilter);
2713aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(ColorFilter);
2714aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Rasterizer);
2715aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Looper);
2716aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(ImageFilter);
2717aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#undef F
2718aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & kTypeface_DirtyBit) buffer.writeTypeface(paint.getTypeface());
2719aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & kAnnotation_DirtyBit) paint.getAnnotation()->writeToBuffer(buffer);
2720aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
2721aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & kPaintOptionsAndroid_DirtyBit) paint.getPaintOptionsAndroid().flatten(buffer);
2722aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#endif
2723aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org}
2724aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2725aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.orgvoid SkPaint::FlatteningTraits::Unflatten(SkReadBuffer& buffer, SkPaint* paint) {
2726aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    const uint32_t dirty = buffer.readUInt();
272745d86e7072cda3b3108a84a033fba98072b12f85commit-bot@chromium.org    paint->setBitfields(buffer.readUInt());
2728aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty == 0) {
2729aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        return;
2730aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    }
2731aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#define F(field, reader) if (dirty & k##field##_DirtyBit) paint->set##field(buffer.reader())
2732aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org// Same function, except it unrefs the object newly set on the paint:
2733aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#define F_UNREF(field, reader)                      \
2734aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & k##field##_DirtyBit)                \
2735aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        paint->set##field(buffer.reader())->unref()
2736aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2737aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Color,       readUInt);
2738aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(TextSize,    readScalar);
2739aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(TextScaleX,  readScalar);
2740aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(TextSkewX,   readScalar);
2741aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(StrokeWidth, readScalar);
2742aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(StrokeMiter, readScalar);
2743aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(PathEffect,  readPathEffect);
2744aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(Shader,      readShader);
2745aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(Xfermode,    readXfermode);
2746aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(MaskFilter,  readMaskFilter);
2747aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(ColorFilter, readColorFilter);
2748aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(Rasterizer,  readRasterizer);
2749aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(Looper,      readDrawLooper);
2750aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F_UNREF(ImageFilter, readImageFilter);
2751aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    F(Typeface,    readTypeface);
2752aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#undef F
2753aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#undef F_UNREF
2754aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & kAnnotation_DirtyBit) {
2755d957984c1efbd18f3b2bbeca78d282837c5a2ae1commit-bot@chromium.org        paint->setAnnotation(SkAnnotation::Create(buffer))->unref();
2756aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    }
2757aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#ifdef SK_BUILD_FOR_ANDROID
2758aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    if (dirty & kPaintOptionsAndroid_DirtyBit) {
2759aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        SkPaintOptionsAndroid options;
2760aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        options.unflatten(buffer);
2761aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org        paint->setPaintOptionsAndroid(options);
2762aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    }
2763aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org#endif
2764aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    SkASSERT(dirty == paint->fDirtyBits);
2765aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org}
2766