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"
11fb1fe4f51820731f557e765f8c71cba9a0d28048mtklein#include "SkChecksum.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
13791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkData.h"
14532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com#include "SkDeviceProperties.h"
15c4b84aef1adeb68bc853f35abb85b79fa1fcaac6rmistry#include "SkDraw.h"
16791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkFontDescriptor.h"
17791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkGlyphCache.h"
1815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com#include "SkImageFilter.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
2097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#include "SkMaskGamma.h"
218b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
228b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
23791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkPaintDefaults.h"
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathEffect.h"
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRasterizer.h"
2628be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkScalar.h"
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h"
28791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkShader.h"
29791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#include "SkStringUtils.h"
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStroke.h"
3128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org#include "SkTextFormatParams.h"
32e69137620ab0b5b40d230318c8e11b822f63cb9dreed@google.com#include "SkTextToPathIter.h"
33ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com#include "SkTLazy.h"
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTypeface.h"
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
36791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
37a3237875f807aed9608cb4a023bc044f32850727reed@google.com// define this to get a printf for out-of-range parameter in setters
38a3237875f807aed9608cb4a023bc044f32850727reed@google.com// e.g. setTextSize(-1)
39a3237875f807aed9608cb4a023bc044f32850727reed@google.com//#define SK_REPORT_API_RANGE_CHECK
40a3237875f807aed9608cb4a023bc044f32850727reed@google.com
41a3122b9b1ec66efef606d8797b7b16b6634e08d2reed@android.comSkPaint::SkPaint() {
42aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org    fTypeface    = NULL;
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPathEffect  = NULL;
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader      = NULL;
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXfermode    = NULL;
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fMaskFilter  = NULL;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColorFilter = NULL;
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRasterizer  = NULL;
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fLooper      = NULL;
5015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    fImageFilter = NULL;
51b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    fAnnotation  = NULL;
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fTextSize   = SkPaintDefaults_TextSize;
54f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fTextScaleX = SK_Scalar1;
55f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fTextSkewX  = 0;
56f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fColor      = SK_ColorBLACK;
57f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fWidth      = 0;
58f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fMiterLimit = SkPaintDefaults_MiterLimit;
59e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
60e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    // Zero all bitfields, then set some non-zero defaults.
61f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfieldsUInt           = 0;
62f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fFlags        = SkPaintDefaults_Flags;
63f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fCapType      = kDefault_Cap;
64f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fJoinType     = kDefault_Join;
65f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fTextAlign    = kLeft_Align;
66f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fStyle        = kFill_Style;
67f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fTextEncoding = kUTF8_TextEncoding;
68f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fHinting      = SkPaintDefaults_Hinting;
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
716fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint::SkPaint(const SkPaint& src) {
72e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define COPY(field) field = src.field
73e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define REF_COPY(field) field = SkSafeRef(src.field)
74e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
75e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fTypeface);
76e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fPathEffect);
77e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fShader);
78e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fXfermode);
79e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fMaskFilter);
80e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fColorFilter);
81e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fRasterizer);
82e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fLooper);
83e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fImageFilter);
84e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fAnnotation);
85e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
86e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSize);
87e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextScaleX);
88e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSkewX);
89e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fColor);
90e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fWidth);
91e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fMiterLimit);
92e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fBitfields);
9340078cb49e290e7fa6da1515c9d32a1d98e304a6djsollen@google.com
94e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef COPY
95e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef REF_COPY
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint::~SkPaint() {
9982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fTypeface);
10082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fPathEffect);
10182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fShader);
10282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fXfermode);
10382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fMaskFilter);
10482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fColorFilter);
10582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fRasterizer);
10682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fLooper);
10715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    SkSafeUnref(fImageFilter);
108b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    SkSafeUnref(fAnnotation);
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1116fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkPaint& SkPaint::operator=(const SkPaint& src) {
112f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org    if (this == &src) {
113f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org        return *this;
114f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org    }
115f239d918d8b40a079693fe5b1f172ddf25abd8c1commit-bot@chromium.org
116e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define COPY(field) field = src.field
117e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define REF_COPY(field) SkSafeUnref(field); field = SkSafeRef(src.field)
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
119e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fTypeface);
120e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fPathEffect);
121e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fShader);
122e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fXfermode);
123e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fMaskFilter);
124e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fColorFilter);
125e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fRasterizer);
126e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fLooper);
127e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fImageFilter);
128e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    REF_COPY(fAnnotation);
129e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
130e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSize);
131e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextScaleX);
132e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fTextSkewX);
133e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fColor);
134e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fWidth);
135e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fMiterLimit);
136e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org    COPY(fBitfields);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *this;
139e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org
140e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef COPY
141e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef REF_COPY
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
144b265741cc17f897b349caacdb890119e4111a415robertphillips@google.combool operator==(const SkPaint& a, const SkPaint& b) {
145e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#define EQUAL(field) (a.field == b.field)
146610a015fda84cd5d1e3f3f826bab393f1193bc0emtklein    return EQUAL(fTypeface)
147e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fPathEffect)
148e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fShader)
149e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fXfermode)
150e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fMaskFilter)
151e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fColorFilter)
152e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fRasterizer)
153e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fLooper)
154e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fImageFilter)
155e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fAnnotation)
156e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextSize)
157e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextScaleX)
158e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fTextSkewX)
159e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fColor)
160e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fWidth)
161e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        && EQUAL(fMiterLimit)
162f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        && EQUAL(fBitfieldsUInt)
163e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org        ;
164e8807f49ed24be3933acf84c9ffa840a03fa43dccommit-bot@chromium.org#undef EQUAL
165b265741cc17f897b349caacdb890119e4111a415robertphillips@google.com}
166b265741cc17f897b349caacdb890119e4111a415robertphillips@google.com
1676fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::reset() {
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint init;
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *this = init;
1704bd2bdbf04f21237337616aa931e34d7c8991edcdjsollen@google.com}
17160abb078e5597c9c6ceaba1ef495c4916ff4df0ddjsollen@google.com
172f803da12cff1d9b6148fea319220351efebfd1e0reedvoid SkPaint::setFilterQuality(SkFilterQuality quality) {
173f803da12cff1d9b6148fea319220351efebfd1e0reed    fBitfields.fFilterQuality = quality;
174c9683151367b2033a26b1e2ebe6b3902d2064bdbreed@google.com}
175c9683151367b2033a26b1e2ebe6b3902d2064bdbreed@google.com
176f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.comvoid SkPaint::setHinting(Hinting hintingLevel) {
177f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fHinting = hintingLevel;
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setFlags(uint32_t flags) {
181f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    fBitfields.fFlags = flags;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1846fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAntiAlias(bool doAA) {
185f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doAA, kAntiAlias_Flag));
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1886fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setDither(bool doDither) {
189f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doDither, kDither_Flag));
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1926fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setSubpixelText(bool doSubpixel) {
193f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doSubpixel, kSubpixelText_Flag));
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1966fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setLCDRenderText(bool doLCDRender) {
197f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doLCDRender, kLCDRenderText_Flag));
198309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org}
199309485b7b51f4cae4c0361ab4da00fe9cc89515cagl@chromium.org
2006fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
201f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
202e95c91e6d9201d50d0b84fbc3d2f53f92f753e0bagl@chromium.org}
203e95c91e6d9201d50d0b84fbc3d2f53f92f753e0bagl@chromium.org
2046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAutohinted(bool useAutohinter) {
205f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, useAutohinter, kAutoHinting_Flag));
206a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org}
207a2c71cbd51da8b7767d43fe8954e7a4c674b2005agl@chromium.org
2086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setLinearText(bool doLinearText) {
209f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doLinearText, kLinearText_Flag));
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
212830a23e39bb4a126e573940cd6e354732e295b10reed@google.comvoid SkPaint::setVerticalText(bool doVertical) {
213f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doVertical, kVerticalText_Flag));
214830a23e39bb4a126e573940cd6e354732e295b10reed@google.com}
215830a23e39bb4a126e573940cd6e354732e295b10reed@google.com
2166fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setUnderlineText(bool doUnderline) {
217f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doUnderline, kUnderlineText_Flag));
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2206fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrikeThruText(bool doStrikeThru) {
221f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doStrikeThru, kStrikeThruText_Flag));
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2246fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setFakeBoldText(bool doFakeBold) {
225f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doFakeBold, kFakeBoldText_Flag));
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2286fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setDevKernText(bool doDevKern) {
229f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doDevKern, kDevKernText_Flag));
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
232b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.orgvoid SkPaint::setDistanceFieldTextTEMP(bool doDistanceFieldText) {
233f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    this->setFlags(SkSetClearMask(fBitfields.fFlags, doDistanceFieldText, kDistanceFieldTextTEMP_Flag));
234b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.org}
235b97c3ffddf15ac65a0aae6823eb408b3b2772751commit-bot@chromium.org
2366fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStyle(Style style) {
2376fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)style < kStyleCount) {
238f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fStyle = style;
239f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
240a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
241a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
242a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
2436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setColor(SkColor color) {
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fColor = color;
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2506fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setAlpha(U8CPU a) {
251f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
252f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com                                  SkColorGetG(fColor), SkColorGetB(fColor)));
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2556fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
256f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    this->setColor(SkColorSetARGB(a, r, g, b));
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2596fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeWidth(SkScalar width) {
2606fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (width >= 0) {
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fWidth = width;
262f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
263a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
264a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
265a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
2666fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2696fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeMiter(SkScalar limit) {
2706fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (limit >= 0) {
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMiterLimit = limit;
272f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com    } else {
273a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
274a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
275a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
2766fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2796fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeCap(Cap ct) {
2806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)ct < kCapCount) {
281f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fCapType = SkToU8(ct);
2826fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
283a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
284a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
285a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
2866fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2896fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setStrokeJoin(Join jt) {
2906fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)jt < kJoinCount) {
291f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fJoinType = SkToU8(jt);
2926fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
293a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
294a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
295a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
2966fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2996fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextAlign(Align align) {
3026fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)align < kAlignCount) {
303f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fTextAlign = SkToU8(align);
3046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
305a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
306a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
307a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3086fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3116fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextSize(SkScalar ts) {
312c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    if (ts >= 0) {
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTextSize = ts;
3146fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
315a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
316a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextSize() called with negative value\n");
317a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3186fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3216fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextScaleX(SkScalar scaleX) {
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTextScaleX = scaleX;
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3256fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextSkewX(SkScalar skewX) {
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fTextSkewX = skewX;
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3296fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::setTextEncoding(TextEncoding encoding) {
3306fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if ((unsigned)encoding <= kGlyphID_TextEncoding) {
331f59eab269350f36a0c2bf98d1c2a9757c77fc473reed        fBitfields.fTextEncoding = encoding;
3326fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
333a3237875f807aed9608cb4a023bc044f32850727reed@google.com#ifdef SK_REPORT_API_RANGE_CHECK
334a3237875f807aed9608cb4a023bc044f32850727reed@google.com        SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
335a3237875f807aed9608cb4a023bc044f32850727reed@google.com#endif
3366fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3396fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3416fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkTypeface* SkPaint::setTypeface(SkTypeface* font) {
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fTypeface, font);
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return font;
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fRasterizer, r);
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return r;
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3516fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fLooper, looper);
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return looper;
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35615356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.comSkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
35715356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    SkRefCnt_SafeAssign(fImageFilter, imageFilter);
35815356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com    return imageFilter;
35915356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com}
36015356a68b2a87e3ab9fc49392d085a4201ffeb62reed@google.com
361b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.comSkAnnotation* SkPaint::setAnnotation(SkAnnotation* annotation) {
362b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    SkRefCnt_SafeAssign(fAnnotation, annotation);
363b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com    return annotation;
364b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com}
365b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
368ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comstatic SkScalar mag2(SkScalar x, SkScalar y) {
369ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return x * x + y * y;
370ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
371ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
372ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comstatic bool tooBig(const SkMatrix& m, SkScalar ma2max) {
373ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return  mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
374ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            ||
375ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
376ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
377ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
378ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.combool SkPaint::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM) {
379ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkASSERT(!ctm.hasPerspective());
380ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkASSERT(!textM.hasPerspective());
381ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
382ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkMatrix matrix;
383ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    matrix.setConcat(ctm, textM);
384ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return tooBig(matrix, MaxCacheSize2());
385ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
386ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
387ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
388ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com///////////////////////////////////////////////////////////////////////////////
389ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGlyphCache.h"
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
39390808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.comstatic void DetachDescProc(SkTypeface* typeface, const SkDescriptor* desc,
39490808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                           void* context) {
39590808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(typeface, desc);
396f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com}
397f5dbe2f00f853c6a1719924bdd0c33335a53423adjsollen@google.com
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkPaint::textToGlyphs(const void* textData, size_t byteLength,
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                          uint16_t glyphs[]) const {
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (byteLength == 0) {
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
40372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(textData != NULL);
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == glyphs) {
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        switch (this->getTextEncoding()) {
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kUTF8_TextEncoding:
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return SkUTF8_CountUnichars((const char*)textData, byteLength);
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kUTF16_TextEncoding:
4112cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkUTF16_CountUnichars((const uint16_t*)textData, SkToInt(byteLength >> 1));
41268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case kUTF32_TextEncoding:
4132cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkToInt(byteLength >> 2);
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case kGlyphID_TextEncoding:
4152cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org            return SkToInt(byteLength >> 1);
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
4170c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
42172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if we get here, we have a valid glyphs[] array, so time to fill it in
42372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // handle this encoding before the setup for the glyphcache
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we want to ignore the low bit of byteLength
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(glyphs, textData, byteLength >> 1 << 1);
4282cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org        return SkToInt(byteLength >> 1);
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
43072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
431532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*    cache = autoCache.getCache();
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = text + byteLength;
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t*   gptr = glyphs;
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (this->getTextEncoding()) {
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkPaint::kUTF8_TextEncoding:
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkPaint::kUTF16_TextEncoding: {
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint16_t* text16 = (const uint16_t*)text;
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const uint16_t* stop16 = (const uint16_t*)stop;
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text16 < stop16) {
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
45268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case kUTF32_TextEncoding: {
45368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* text32 = (const int32_t*)text;
45468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* stop32 = (const int32_t*)stop;
45568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            while (text32 < stop32) {
45668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                *gptr++ = cache->unicharToGlyph(*text32++);
45768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            }
45868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            break;
45968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        }
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
4610c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4632cfa3200fda29279eba1240170c7e873d12f9d48commit-bot@chromium.org    return SkToInt(gptr - glyphs);
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
466a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.combool SkPaint::containsText(const void* textData, size_t byteLength) const {
467a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    if (0 == byteLength) {
468a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        return true;
469a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
47072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
471a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    SkASSERT(textData != NULL);
47272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
473a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    // handle this encoding before the setup for the glyphcache
474a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
475a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
476a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        size_t count = byteLength >> 1;
477a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        for (size_t i = 0; i < count; i++) {
478a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            if (0 == glyphID[i]) {
479a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                return false;
480a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
481a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
482a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        return true;
483a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
48472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
485532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
486a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    SkGlyphCache*    cache = autoCache.getCache();
487a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com
488a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    switch (this->getTextEncoding()) {
489a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        case SkPaint::kUTF8_TextEncoding: {
490a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const char* text = static_cast<const char*>(textData);
491a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const char* stop = text + byteLength;
492a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            while (text < stop) {
493a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
494a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                    return false;
495a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                }
496a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
497a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            break;
498a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
499a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        case SkPaint::kUTF16_TextEncoding: {
500a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const uint16_t* text = static_cast<const uint16_t*>(textData);
501a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            const uint16_t* stop = text + (byteLength >> 1);
502a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            while (text < stop) {
503a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
504a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                    return false;
505a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com                }
506a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            }
507a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            break;
508a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        }
50968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        case SkPaint::kUTF32_TextEncoding: {
51068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* text = static_cast<const int32_t*>(textData);
51168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            const int32_t* stop = text + (byteLength >> 2);
51268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            while (text < stop) {
51368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                if (0 == cache->unicharToGlyph(*text++)) {
51468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                    return false;
51568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                }
51668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            }
51768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com            break;
51868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        }
519a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com        default:
5200c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unknown text encoding");
521a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com            return false;
522a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    }
523a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com    return true;
524a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com}
525a5dcaf6fd8115fb9c6028ca4e9848b968375abcdreed@android.com
5269d3a985aa3c82605346ed1518375a8c384b925e5reed@android.comvoid SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
5279d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com                               SkUnichar textData[]) const {
5289d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    if (count <= 0) {
5299d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com        return;
5309d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    }
5319d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
5329d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkASSERT(glyphs != NULL);
5339d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkASSERT(textData != NULL);
5349d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
535532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    SkAutoGlyphCache autoCache(*this, NULL, NULL);
5369d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    SkGlyphCache*    cache = autoCache.getCache();
5379d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
5389d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    for (int index = 0; index < count; index++) {
5399d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com        textData[index] = cache->glyphToUnichar(glyphs[index]);
5409d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com    }
5419d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com}
5429d3a985aa3c82605346ed1518375a8c384b925e5reed@android.com
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5456fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
5466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
54972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5536fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
5546fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
557fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_next(SkGlyphCache* cache,
56268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
56368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
56468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
56568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
56668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
56768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
56868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
56968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharMetrics(uni);
57068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
57168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
5726fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
5736fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
57672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID);
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5846fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
5856fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                              const char** text) {
5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
58872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5926fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
5936fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
59672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
60068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getAdvance_utf32_next(SkGlyphCache* cache,
60168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                               const char** text) {
60268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
60368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
604fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
60568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
60668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
60768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
60868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharAdvance(uni);
60968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
61068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
6116fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
6126fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                               const char** text) {
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
61572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDAdvance(glyphID);
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6239e96aa07dbf1210fd35ae8e0c54d4d9822544e89reedSkMeasureCacheProc SkPaint::getMeasureCacheProc(bool needFullMetrics) const {
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const SkMeasureCacheProc gMeasureCacheProcs[] = {
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_next,
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_next,
62768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_next,
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_next,
62972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf8_next,
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_utf16_next,
63268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getAdvance_utf32_next,
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getAdvance_glyph_next,
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
63572cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned index = this->getTextEncoding();
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6386fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!needFullMetrics && !this->isDevKernText()) {
6399e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed        index += 4;
6406fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return gMeasureCacheProcs[index];
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
6496fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                        const char** text, SkFixed, SkFixed) {
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
65272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
6576fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                    const char** text, SkFixed x, SkFixed y) {
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
66072cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
6656fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                        const char** text, SkFixed, SkFixed) {
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
66872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
6736fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                     const char** text, SkFixed x, SkFixed y) {
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
67672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    x, y);
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
68168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_00(SkGlyphCache* cache,
68268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                    const char** text, SkFixed, SkFixed) {
68368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
68468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
685fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
68668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
68768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkUnichar uni = *ptr++;
68868bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
68968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    return cache->getUnicharMetrics(uni);
69068bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
69168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
69268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.comstatic const SkGlyph& sk_getMetrics_utf32_xy(SkGlyphCache* cache,
69368bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com                                    const char** text, SkFixed x, SkFixed y) {
69468bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(cache != NULL);
69568bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    SkASSERT(text != NULL);
696fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
69768bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    const int32_t* ptr = *(const int32_t**)text;
698584f337832d585e23037e59517f7bcc420424692commit-bot@chromium.org    SkUnichar uni = *ptr++;
69968bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com    *text = (const char*)ptr;
7008d38d516c0f17d8d9f6b170055ac05ac181c0554sugoi@google.com    return cache->getUnicharMetrics(uni, x, y);
70168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com}
70268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com
7036fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
7046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                         const char** text, SkFixed, SkFixed) {
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
70772cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID);
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
7166fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                     const char** text, SkFixed x, SkFixed y) {
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(cache != NULL);
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL);
71972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const uint16_t* ptr = *(const uint16_t**)text;
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned glyphID = *ptr;
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ptr += 1;
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *text = (const char*)ptr;
7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache->getGlyphIDMetrics(glyphID, x, y);
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7276fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkDrawCacheProc SkPaint::getDrawCacheProc() const {
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const SkDrawCacheProc gDrawCacheProcs[] = {
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_00,
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_00,
73168bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_00,
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_00,
73372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf8_xy,
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_utf16_xy,
73668bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        sk_getMetrics_utf32_xy,
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_getMetrics_glyph_xy
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
73972cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned index = this->getTextEncoding();
741f59eab269350f36a0c2bf98d1c2a9757c77fc473reed    if (fBitfields.fFlags & kSubpixelText_Flag) {
74268bc6f7b4510813c1af886d0cdeea2f0f7a2a510reed@google.com        index += 4;
7436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
74472cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return gDrawCacheProcs[index];
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
751ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com#define TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE (   \
752ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kDevKernText_Flag          |       \
753ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kLinearText_Flag           |       \
754ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kLCDRenderText_Flag        |       \
755ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kEmbeddedBitmapText_Flag   |       \
756ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kAutoHinting_Flag          |       \
757ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkPaint::kGenA8FromLCD_Flag )
758ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
759ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comSkScalar SkPaint::setupForAsPaths() {
760ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    uint32_t flags = this->getFlags();
761ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // clear the flags we don't care about
762ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    flags &= ~TEXT_AS_PATHS_PAINT_FLAGS_TO_IGNORE;
763ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // set the flags we do care about
764ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    flags |= SkPaint::kSubpixelText_Flag;
7658f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
766ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setFlags(flags);
767ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setHinting(SkPaint::kNo_Hinting);
7688f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
769ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar textSize = fTextSize;
770ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    this->setTextSize(kCanonicalTextSizeForPaths);
771ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    return textSize / kCanonicalTextSizeForPaths;
772ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com}
773ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com
774ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comclass SkCanonicalizePaint {
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
776ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint(const SkPaint& paint) : fPaint(&paint), fScale(0) {
777c4b84aef1adeb68bc853f35abb85b79fa1fcaac6rmistry        if (paint.isLinearText() || SkDraw::ShouldDrawTextAsPaths(paint, SkMatrix::I())) {
778ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            SkPaint* p = fLazy.set(paint);
779ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            fScale = p->setupForAsPaths();
780ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com            fPaint = p;
781ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        }
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7836fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com
784ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& getPaint() const { return *fPaint; }
7858f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
786ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    /**
787ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     *  Returns 0 if the paint was unmodified, or the scale factor need to
788ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     *  the original textSize
789ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com     */
790ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar getScale() const { return fScale; }
79172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
793ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint*   fPaint;
794ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar         fScale;
795ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkTLazy<SkPaint> fLazy;
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7986fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic void set_bounds(const SkGlyph& g, SkRect* bounds) {
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->set(SkIntToScalar(g.fLeft),
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fTop),
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fLeft + g.fWidth),
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIntToScalar(g.fTop + g.fHeight));
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
80544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
806e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    SkScalar sx = Sk48Dot16ToScalar(dx);
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->join(SkIntToScalar(g.fLeft) + sx,
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fTop),
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fLeft + g.fWidth) + sx,
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 SkIntToScalar(g.fTop + g.fHeight));
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
81344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
81444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    SkScalar sy = Sk48Dot16ToScalar(dy);
81544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    bounds->join(SkIntToScalar(g.fLeft),
81644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fTop) + sy,
81744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fLeft + g.fWidth),
81844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                 SkIntToScalar(g.fTop + g.fHeight) + sy);
81944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com}
82044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
82144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comtypedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
82244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
82344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com// xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
82444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.comstatic SkFixed advance(const SkGlyph& glyph, int xyIndex) {
82544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    SkASSERT(0 == xyIndex || 1 == xyIndex);
82644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    return (&glyph.fAdvanceX)[xyIndex];
82744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com}
82844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkPaint::measure_text(SkGlyphCache* cache,
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               const char* text, size_t byteLength,
8316fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                               int* count, SkRect* bounds) const {
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count);
8336fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (byteLength == 0) {
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *count = 0;
8356fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (bounds) {
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            bounds->setEmpty();
8376fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8419e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed    SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(NULL != bounds);
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
84344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    int xyIndex;
84444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    JoinBoundsProc joinBoundsProc;
84544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    if (this->isVerticalText()) {
84644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        xyIndex = 1;
84744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        joinBoundsProc = join_bounds_y;
84844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    } else {
84944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        xyIndex = 0;
85044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        joinBoundsProc = join_bounds_x;
85144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    }
85244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int         n = 1;
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = (const char*)text + byteLength;
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkGlyph* g = &glyphCacheProc(cache, &text);
856e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // our accumulated fixed-point advances might overflow 16.16, so we use
857e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // a 48.16 (64bit) accumulator, and then convert that to scalar at the
858e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // very end.
85944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    Sk48Dot16 x = advance(*g, xyIndex);
8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoKern  autokern;
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8636fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == bounds) {
8646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (this->isDevKernText()) {
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rsb;
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rsb = g->fRsbDelta;
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
86944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8716fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
87344da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(glyphCacheProc(cache, &text), xyIndex);
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8766fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        set_bounds(*g, bounds);
8786fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (this->isDevKernText()) {
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rsb;
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rsb = g->fRsbDelta;
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
88444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                joinBoundsProc(*g, bounds, x);
88544da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(*g, xyIndex);
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8876fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (; text < stop; n++) {
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g = &glyphCacheProc(cache, &text);
89044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                joinBoundsProc(*g, bounds, x);
89144da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                x += advance(*g, xyIndex);
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text == stop);
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *count = n;
898e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    return Sk48Dot16ToScalar(x);
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
90199ae881a7f55a03c2b16fb5704e6e90ea86d965dreedSkScalar SkPaint::measureText(const void* textData, size_t length, SkRect* bounds) const {
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text != NULL || length == 0);
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
905ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
906ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
907ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
90872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
90999ae881a7f55a03c2b16fb5704e6e90ea86d965dreed    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar width = 0;
91372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9146fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (length > 0) {
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int tempCount;
9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
917ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        width = paint.measure_text(cache, text, length, &tempCount, bounds);
9186fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (scale) {
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            width = SkScalarMul(width, scale);
9206fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if (bounds) {
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fTop = SkScalarMul(bounds->fTop, scale);
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fRight = SkScalarMul(bounds->fRight, scale);
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
92746348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com    } else if (bounds) {
92846348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com        // ensure that even if we don't measure_text we still update the bounds
92946348e21732e64e1a4dcfb5d859e6edafba471ffdjsollen@google.com        bounds->setEmpty();
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return width;
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comsize_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
9359e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed                          SkScalar* measuredWidth) const {
9366fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (0 == length || 0 >= maxWidth) {
9376fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (measuredWidth) {
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *measuredWidth = 0;
9396fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
943c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    if (0 == fTextSize) {
944c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        if (measuredWidth) {
945c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com            *measuredWidth = 0;
946c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        }
947c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com        return length;
948c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com    }
949c6f2e7da31d60e48a420b6de520361d966ea278ddjsollen@google.com
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(textD != NULL);
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textD;
9529e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed    const char* stop = text + length;
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
954ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
955ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
956ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
958ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    // adjust max in case we changed the textSize in paint
959ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    if (scale) {
960ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com        maxWidth /= scale;
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
96272cf4927e503f49c4bd07369e85764ddde57071breed@google.com
963ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9669e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed    SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(false);
967ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const int        xyIndex = paint.isVerticalText() ? 1 : 0;
968e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    // use 64bits for our accumulator, to avoid overflowing 16.16
969e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    Sk48Dot16        max = SkScalarToFixed(maxWidth);
970e88f551b38c2893566b7016d906b1455e43542f5reed@android.com    Sk48Dot16        width = 0;
9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoKern  autokern;
9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9746fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (this->isDevKernText()) {
9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int rsb = 0;
9769e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed        while (text < stop) {
9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const char* curr = text;
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const SkGlyph& g = glyphCacheProc(cache, &text);
97944da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com            SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
9806fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if ((width += x) > max) {
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                width -= x;
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                text = curr;
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            rsb = g.fRsbDelta;
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9876fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
9889e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed        while (text < stop) {
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const char* curr = text;
99044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com            SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
9916fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            if ((width += x) > max) {
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                width -= x;
9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                text = curr;
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
99872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
9996fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (measuredWidth) {
1000e88f551b38c2893566b7016d906b1455e43542f5reed@android.com        SkScalar scalarWidth = Sk48Dot16ToScalar(width);
10016fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (scale) {
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            scalarWidth = SkScalarMul(scalarWidth, scale);
10036fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *measuredWidth = scalarWidth;
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
100672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // return the number of bytes measured
10089e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed    return text - stop + length;
10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10136fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
10140a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com    *(SkPaint::FontMetrics*)context = cache->getFontMetrics();
10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;   // don't detach the cache
10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
101890808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.comstatic void FontMetricsDescProc(SkTypeface* typeface, const SkDescriptor* desc,
101990808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com                                void* context) {
102090808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    SkGlyphCache::VisitCache(typeface, desc, FontMetricsCacheProc, context);
10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10236fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1024ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1025ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1026ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
10278f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com
10286fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    SkMatrix zoomMatrix, *zoomPtr = NULL;
10296fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (zoom) {
10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        zoomMatrix.setScale(zoom, zoom);
10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        zoomPtr = &zoomMatrix;
10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    FontMetrics storage;
10356fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == metrics) {
10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics = &storage;
10376fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
103872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
1039ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    paint.descriptorProc(NULL, zoomPtr, FontMetricsDescProc, metrics, true);
10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10416fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (scale) {
10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fTop = SkScalarMul(metrics->fTop, scale);
10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
10470a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fAvgCharWidth = SkScalarMul(metrics->fAvgCharWidth, scale);
10480a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXMin = SkScalarMul(metrics->fXMin, scale);
10490a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXMax = SkScalarMul(metrics->fXMax, scale);
10500a01f5a2c44f3d6a7fa2d3c837f46894d9b29e5dreed@google.com        metrics->fXHeight = SkScalarMul(metrics->fXHeight, scale);
10510bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org        metrics->fUnderlineThickness = SkScalarMul(metrics->fUnderlineThickness, scale);
10520bc406df48ac6f358ab8dcff08f71fe9c32b79decommit-bot@chromium.org        metrics->fUnderlinePosition = SkScalarMul(metrics->fUnderlinePosition, scale);
10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return metrics->fDescent - metrics->fAscent + metrics->fLeading;
10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10576fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10596fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds->set(g.fLeft * scale,
10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                g.fTop * scale,
10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (g.fLeft + g.fWidth) * scale,
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                (g.fTop + g.fHeight) * scale);
10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10666fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comint SkPaint::getTextWidths(const void* textData, size_t byteLength,
10676fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                           SkScalar widths[], SkRect bounds[]) const {
10686fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (0 == byteLength) {
10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return 0;
10706fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
107249f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(textData);
10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10746fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (NULL == widths && NULL == bounds) {
10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->countText(textData, byteLength);
10766fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1078ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkCanonicalizePaint canon(*this);
1079ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const SkPaint& paint = canon.getPaint();
1080ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkScalar scale = canon.getScale();
10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1082ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache*       cache = autoCache.getCache();
10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMeasureCacheProc  glyphCacheProc;
10859e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed    glyphCacheProc = paint.getMeasureCacheProc(NULL != bounds);
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* stop = text + byteLength;
10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int         count = 0;
1090ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com    const int   xyIndex = paint.isVerticalText() ? 1 : 0;
10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10926fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (this->isDevKernText()) {
10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // we adjust the widths returned here through auto-kerning
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoKern  autokern;
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkFixed     prevWidth = 0;
10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (scale) {
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkFixed  adjust = autokern.adjust(g);
11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if (count > 0) {
11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        SkScalar w = SkFixedToScalar(prevWidth + adjust);
11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        *widths++ = SkScalarMul(w, scale);
11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
110744da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    prevWidth = advance(g, xyIndex);
11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++, scale);
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count > 0 && widths) {
11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkFixed  adjust = autokern.adjust(g);
11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    if (count > 0) {
11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        *widths++ = SkFixedToScalar(prevWidth + adjust);
11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
112644da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    prevWidth = advance(g, xyIndex);
11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++);
11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count > 0 && widths) {
11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *widths = SkFixedToScalar(prevWidth);
11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // no devkern
11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (scale) {
11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
114244da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                            scale);
11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++, scale);
11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            while (text < stop) {
11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                const SkGlyph& g = glyphCacheProc(cache, &text);
11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (widths) {
115444da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com                    *widths++ = SkFixedToScalar(advance(g, xyIndex));
11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (bounds) {
11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    set_bounds(g, bounds++);
11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                ++count;
11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(text == stop);
11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return count;
11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11686fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h"
11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11726fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comvoid SkPaint::getTextPath(const void* textData, size_t length,
11736fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                          SkScalar x, SkScalar y, SkPath* path) const {
11746fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    SkASSERT(length == 0 || textData != NULL);
11756fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com
11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const char* text = (const char*)textData;
11776fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (text == NULL || length == 0 || path == NULL) {
11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
11796fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1181166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    SkTextToPathIter    iter(text, length, *this, false);
11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkMatrix            matrix;
11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar            prevXPos = 0;
11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.setScale(iter.getPathScale(), iter.getPathScale());
11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    matrix.postTranslate(x, y);
11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    path->reset();
11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar        xpos;
11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkPath*   iterPath;
11917b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    while (iter.next(&iterPath, &xpos)) {
11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        matrix.postTranslate(xpos - prevXPos, 0);
11937b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (iterPath) {
11947b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            path->addPath(*iterPath, matrix);
11957b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prevXPos = xpos;
11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1200ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.comvoid SkPaint::getPosTextPath(const void* textData, size_t length,
1201ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com                             const SkPoint pos[], SkPath* path) const {
1202ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkASSERT(length == 0 || textData != NULL);
1203ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1204ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    const char* text = (const char*)textData;
1205ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    if (text == NULL || length == 0 || path == NULL) {
1206ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        return;
1207ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    }
1208ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1209ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkTextToPathIter    iter(text, length, *this, false);
1210ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkMatrix            matrix;
1211ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    SkPoint             prevPos;
1212ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    prevPos.set(0, 0);
1213ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1214ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1215ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    path->reset();
1216ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
1217ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    unsigned int    i = 0;
1218ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    const SkPath*   iterPath;
12197b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    while (iter.next(&iterPath, NULL)) {
1220ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        matrix.postTranslate(pos[i].fX - prevPos.fX, pos[i].fY - prevPos.fY);
12217b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (iterPath) {
12227b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            path->addPath(*iterPath, matrix);
12237b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
1224ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        prevPos = pos[i];
1225ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com        i++;
1226ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com    }
1227ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com}
1228ca0062ee5e74eddff886ada2a200d25946ea52cfreed@google.com
12298893e5f030cb2f6c3bdf698c1767a244ae098a5creedSkRect SkPaint::getFontBounds() const {
12308893e5f030cb2f6c3bdf698c1767a244ae098a5creed    SkMatrix m;
12318893e5f030cb2f6c3bdf698c1767a244ae098a5creed    m.setScale(fTextSize * fTextScaleX, fTextSize);
12328893e5f030cb2f6c3bdf698c1767a244ae098a5creed    m.postSkew(fTextSkewX, 0);
12338893e5f030cb2f6c3bdf698c1767a244ae098a5creed
12348893e5f030cb2f6c3bdf698c1767a244ae098a5creed    SkTypeface* typeface = this->getTypeface();
12358893e5f030cb2f6c3bdf698c1767a244ae098a5creed    if (NULL == typeface) {
12368893e5f030cb2f6c3bdf698c1767a244ae098a5creed        typeface = SkTypeface::GetDefaultTypeface();
12378893e5f030cb2f6c3bdf698c1767a244ae098a5creed    }
12388893e5f030cb2f6c3bdf698c1767a244ae098a5creed
12398893e5f030cb2f6c3bdf698c1767a244ae098a5creed    SkRect bounds;
12408893e5f030cb2f6c3bdf698c1767a244ae098a5creed    m.mapRect(&bounds, typeface->getBounds());
12418893e5f030cb2f6c3bdf698c1767a244ae098a5creed    return bounds;
12428893e5f030cb2f6c3bdf698c1767a244ae098a5creed}
12438893e5f030cb2f6c3bdf698c1767a244ae098a5creed
12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void add_flattenable(SkDescriptor* desc, uint32_t tag,
12458b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org                            SkWriteBuffer* buffer) {
12468b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    buffer->writeToMemory(desc->addEntry(tag, buffer->bytesWritten(), NULL));
12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12496fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic SkMask::Format computeMaskFormat(const SkPaint& paint) {
12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t flags = paint.getFlags();
12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1252b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org    // Antialiasing being disabled trumps all other settings.
125365dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    if (!(flags & SkPaint::kAntiAlias_Flag)) {
1254b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org        return SkMask::kBW_Format;
1255f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com    }
1256f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com
125765dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    if (flags & SkPaint::kLCDRenderText_Flag) {
1258f67e4cf4c18cd228738a11372859ee0280bce1d7reed@google.com        return SkMask::kLCD16_Format;
125965dd8f83106ceb11fbff330bed3037557db974cfreed@google.com    }
1260b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org
1261b4234a226612cf7f99a47d9c633233c1a488d6edagl@chromium.org    return SkMask::kA8_Format;
12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12641cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com// if linear-text is on, then we force hinting to be off (since that's sort of
12651cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com// the point of linear-text.
12661cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.comstatic SkPaint::Hinting computeHinting(const SkPaint& paint) {
12671cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    SkPaint::Hinting h = paint.getHinting();
12681cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    if (paint.isLinearText()) {
12691cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com        h = SkPaint::kNo_Hinting;
12701cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    }
12711cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com    return h;
12721cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com}
12731cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com
12741f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com// return true if the paint is just a single color (i.e. not a shader). If its
12751f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com// a shader, then we can't compute a const luminance for it :(
12761f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.comstatic bool justAColor(const SkPaint& paint, SkColor* color) {
12778367b8cb7a6b2f163ee41365323cb219b7049b15reed    SkColor c = paint.getColor();
12788367b8cb7a6b2f163ee41365323cb219b7049b15reed
12798367b8cb7a6b2f163ee41365323cb219b7049b15reed    SkShader* shader = paint.getShader();
12808367b8cb7a6b2f163ee41365323cb219b7049b15reed    if (shader && !shader->asLuminanceColor(&c)) {
12811f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        return false;
12821f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
12831f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    if (paint.getColorFilter()) {
12841f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        c = paint.getColorFilter()->filterColor(c);
12851f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
12861f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    if (color) {
12871f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com        *color = c;
12881f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    }
12891f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com    return true;
12901f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com}
12911f6b4ae0f723317d01b158ce1498dabf4d93a67breed@google.com
12929e36c1a9306f052331550dab4728b9875127bfb5joshualittSkColor SkPaint::computeLuminanceColor() const {
1293ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    SkColor c;
12949e36c1a9306f052331550dab4728b9875127bfb5joshualitt    if (!justAColor(*this, &c)) {
1295ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com        c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1296ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    }
1297ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com    return c;
1298ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com}
1299813d38b7a07957f2990ccca52ddab55fe0b1c632reed@google.com
1300dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com#define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
1301dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com
13024f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com// Beyond this size, LCD doesn't appreciably improve quality, but it always
13034f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com// cost more RAM and draws slower, so we set a cap.
1304c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com#ifndef SK_MAX_SIZE_FOR_LCDTEXT
1305c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com    #define SK_MAX_SIZE_FOR_LCDTEXT    48
1306c27b74174e6a734db3cf1b5a5354eab8f3d27c1creed@google.com#endif
13074f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com
1308b3da83a07fd6081fd703a370ce135837f55de010reedconst SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT;
1309b3da83a07fd6081fd703a370ce135837f55de010reed
13104942e7550ec80796132ab1ce2cc935a5dd1b464creedstatic bool too_big_for_lcd(const SkScalerContext::Rec& rec, bool checkPost2x2) {
1311b3da83a07fd6081fd703a370ce135837f55de010reed    if (checkPost2x2) {
1312b3da83a07fd6081fd703a370ce135837f55de010reed        SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
1313b3da83a07fd6081fd703a370ce135837f55de010reed                        rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
13144942e7550ec80796132ab1ce2cc935a5dd1b464creed        area *= rec.fTextSize * rec.fTextSize;
13154942e7550ec80796132ab1ce2cc935a5dd1b464creed        return area > gMaxSize2ForLCDText;
13164942e7550ec80796132ab1ce2cc935a5dd1b464creed    } else {
13174942e7550ec80796132ab1ce2cc935a5dd1b464creed        return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT;
1318b3da83a07fd6081fd703a370ce135837f55de010reed    }
13194f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com}
13204f79b9be9ea5e8998b3692c1030ae2c90a796e9dreed@google.com
132172cf4927e503f49c4bd07369e85764ddde57071breed@google.com/*
132272cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  Return the scalar with only limited fractional precision. Used to consolidate matrices
132372cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  that vary only slightly when we create our key into the font cache, since the font scaler
132472cf4927e503f49c4bd07369e85764ddde57071breed@google.com *  typically returns the same looking resuts for tiny changes in the matrix.
132572cf4927e503f49c4bd07369e85764ddde57071breed@google.com */
1326f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comstatic SkScalar sk_relax(SkScalar x) {
1327f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int n = sk_float_round2int(x * 1024);
1328f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    return n / 1024.0f;
1329f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
1330f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
133136a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.comvoid SkScalerContext::MakeRec(const SkPaint& paint,
1332532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              const SkDeviceProperties* deviceProperties,
1333532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              const SkMatrix* deviceMatrix,
1334532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com                              Rec* rec) {
13358d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com    SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1337cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    SkTypeface* typeface = paint.getTypeface();
1338cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    if (NULL == typeface) {
1339cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com        typeface = SkTypeface::GetDefaultTypeface();
1340cb1bbb375aa4fdd099dc60302ca1712f04607782bungeman@google.com    }
1341ec730b9cafaa3b2a4df7e7ceb3ab50601796fbe5bungeman    rec->fFontID = typeface->uniqueID();
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fTextSize = paint.getTextSize();
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fPreScaleX = paint.getTextScaleX();
13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec->fPreSkewX  = paint.getTextSkewX();
13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1346b3da83a07fd6081fd703a370ce135837f55de010reed    bool checkPost2x2 = false;
1347b3da83a07fd6081fd703a370ce135837f55de010reed
13486fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (deviceMatrix) {
1349b3da83a07fd6081fd703a370ce135837f55de010reed        const SkMatrix::TypeMask mask = deviceMatrix->getType();
1350b3da83a07fd6081fd703a370ce135837f55de010reed        if (mask & SkMatrix::kScale_Mask) {
1351b3da83a07fd6081fd703a370ce135837f55de010reed            rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1352b3da83a07fd6081fd703a370ce135837f55de010reed            rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
1353b3da83a07fd6081fd703a370ce135837f55de010reed            checkPost2x2 = true;
1354b3da83a07fd6081fd703a370ce135837f55de010reed        } else {
1355b3da83a07fd6081fd703a370ce135837f55de010reed            rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1356b3da83a07fd6081fd703a370ce135837f55de010reed        }
1357b3da83a07fd6081fd703a370ce135837f55de010reed        if (mask & SkMatrix::kAffine_Mask) {
1358b3da83a07fd6081fd703a370ce135837f55de010reed            rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1359b3da83a07fd6081fd703a370ce135837f55de010reed            rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1360b3da83a07fd6081fd703a370ce135837f55de010reed            checkPost2x2 = true;
1361b3da83a07fd6081fd703a370ce135837f55de010reed        } else {
1362b3da83a07fd6081fd703a370ce135837f55de010reed            rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1363b3da83a07fd6081fd703a370ce135837f55de010reed        }
13646fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
136872cf4927e503f49c4bd07369e85764ddde57071breed@google.com
13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint::Style  style = paint.getStyle();
13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar        strokeWidth = paint.getStrokeWidth();
137172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
1372ffe49f5380dd5062073efeda70f2f91682c828careed@google.com    unsigned flags = 0;
13734526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org
13746fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isFakeBoldText()) {
13754526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#ifdef SK_USE_FREETYPE_EMBOLDEN
13764526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org        flags |= SkScalerContext::kEmbolden_Flag;
13774526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#else
137828be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org        SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
137928be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpKeys,
138028be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpValues,
138128be72b63e457c680c192a34fb9f58e1c693363fvandebo@chromium.org                                                    kStdFakeBoldInterpLength);
13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
138372cf4927e503f49c4bd07369e85764ddde57071breed@google.com
13846fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (style == SkPaint::kFill_Style) {
13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            style = SkPaint::kStrokeAndFill_Style;
13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
13876fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        } else {
13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            strokeWidth += extra;
13896fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
13904526a847da6dc738dc73103ec4d47cc0dbdec478senorblanco@chromium.org#endif
13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13936fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isDevKernText()) {
13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        flags |= SkScalerContext::kDevKernText_Flag;
13956fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
139672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
13976fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (style != SkPaint::kFill_Style && strokeWidth > 0) {
13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fFrameWidth = strokeWidth;
13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fMiterLimit = paint.getStrokeMiter();
14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14026fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (style == SkPaint::kStrokeAndFill_Style) {
14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            flags |= SkScalerContext::kFrameAndFill_Flag;
14046fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
14056fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fFrameWidth = 0;
14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fMiterLimit = 0;
14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec->fStrokeJoin = 0;
14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
141102b5331078861b02b61e9a93f845617a7c900409reed@google.com    rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
141202b5331078861b02b61e9a93f845617a7c900409reed@google.com
1413d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed    if (SkMask::kLCD16_Format == rec->fMaskFormat) {
14144942e7550ec80796132ab1ce2cc935a5dd1b464creed        if (too_big_for_lcd(*rec, checkPost2x2)) {
141502b5331078861b02b61e9a93f845617a7c900409reed@google.com            rec->fMaskFormat = SkMask::kA8_Format;
14164a8126e7f81384526629b1e21bf89b632ea13cd9reed            flags |= SkScalerContext::kGenA8FromLCD_Flag;
141702b5331078861b02b61e9a93f845617a7c900409reed@google.com        } else {
14184a8126e7f81384526629b1e21bf89b632ea13cd9reed            SkPixelGeometry geometry = deviceProperties
1419b2d77e4d7458145ef4825c28323d9fbbb6b003acreed                                     ? deviceProperties->pixelGeometry()
14204a8126e7f81384526629b1e21bf89b632ea13cd9reed                                     : SkSurfacePropsDefaultPixelGeometry();
14214a8126e7f81384526629b1e21bf89b632ea13cd9reed            switch (geometry) {
14224a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kUnknown_SkPixelGeometry:
14234a8126e7f81384526629b1e21bf89b632ea13cd9reed                    // eeek, can't support LCD
14244a8126e7f81384526629b1e21bf89b632ea13cd9reed                    rec->fMaskFormat = SkMask::kA8_Format;
14254a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kGenA8FromLCD_Flag;
14264a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
14274a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kRGB_H_SkPixelGeometry:
14284a8126e7f81384526629b1e21bf89b632ea13cd9reed                    // our default, do nothing.
14294a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
14304a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kBGR_H_SkPixelGeometry:
14314a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
14324a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
14334a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kRGB_V_SkPixelGeometry:
14344a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kLCD_Vertical_Flag;
14354a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
14364a8126e7f81384526629b1e21bf89b632ea13cd9reed                case kBGR_V_SkPixelGeometry:
14374a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kLCD_Vertical_Flag;
14384a8126e7f81384526629b1e21bf89b632ea13cd9reed                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
14394a8126e7f81384526629b1e21bf89b632ea13cd9reed                    break;
144002b5331078861b02b61e9a93f845617a7c900409reed@google.com            }
144102b5331078861b02b61e9a93f845617a7c900409reed@google.com        }
144202b5331078861b02b61e9a93f845617a7c900409reed@google.com    }
144302b5331078861b02b61e9a93f845617a7c900409reed@google.com
14446fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isEmbeddedBitmapText()) {
144502b5331078861b02b61e9a93f845617a7c900409reed@google.com        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
14466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
14476fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isSubpixelText()) {
144802b5331078861b02b61e9a93f845617a7c900409reed@google.com        flags |= SkScalerContext::kSubpixelPositioning_Flag;
14496fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
14506fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.isAutohinted()) {
1451f6f56878bc96386882721b15ba610984185d3dc9bungeman@google.com        flags |= SkScalerContext::kForceAutohinting_Flag;
14526fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
1453830a23e39bb4a126e573940cd6e354732e295b10reed@google.com    if (paint.isVerticalText()) {
1454830a23e39bb4a126e573940cd6e354732e295b10reed@google.com        flags |= SkScalerContext::kVertical_Flag;
1455830a23e39bb4a126e573940cd6e354732e295b10reed@google.com    }
14568351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
14578351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com        flags |= SkScalerContext::kGenA8FromLCD_Flag;
14588351aabbfe82a76a698fa2bde00d33c1174518cdreed@google.com    }
145902b5331078861b02b61e9a93f845617a7c900409reed@google.com    rec->fFlags = SkToU16(flags);
146036a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com
1461ffe49f5380dd5062073efeda70f2f91682c828careed@google.com    // these modify fFlags, so do them after assigning fFlags
14629d7576724cf9602ff778b18126e0fef0ab3d3bf2reed@google.com    rec->setHinting(computeHinting(paint));
146397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
14649e36c1a9306f052331550dab4728b9875127bfb5joshualitt    rec->setLuminanceColor(paint.computeLuminanceColor());
1465532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1466532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    if (NULL == deviceProperties) {
1467532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        rec->setDeviceGamma(SK_GAMMA_EXPONENT);
1468532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        rec->setPaintGamma(SK_GAMMA_EXPONENT);
1469532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    } else {
1470b2d77e4d7458145ef4825c28323d9fbbb6b003acreed        rec->setDeviceGamma(deviceProperties->gamma());
1471532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1472532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //For now always set the paint gamma equal to the device gamma.
1473532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //The math in SkMaskGamma can handle them being different,
1474532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //but it requires superluminous masks when
1475532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com        //Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
1476b2d77e4d7458145ef4825c28323d9fbbb6b003acreed        rec->setPaintGamma(deviceProperties->gamma());
1477532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    }
1478532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
1479532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com#ifdef SK_GAMMA_CONTRAST
1480532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    rec->setContrast(SK_GAMMA_CONTRAST);
1481ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com#else
1482532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com    /**
1483532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
1484532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * With lower values small text appears washed out (though correctly so).
1485532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * With higher values lcd fringing is worse and the smoothing effect of
1486532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     * partial coverage is diminished.
1487532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com     */
14884b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org    rec->setContrast(0.5f);
1489ce6dbb6b4ce3f36e0a2245b215dc48b68df35c41reed@google.com#endif
1490532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com
14912bf82d843d8896dd10bb86adc1e974c6d52324e6bungeman@google.com    rec->fReservedAlign = 0;
1492fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
149336a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com    /*  Allow the fonthost to modify our rec before we use it as a key into the
149436a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        cache. This way if we're asking for something that they will ignore,
149536a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        they can modify our rec up front, so we don't create duplicate cache
149636a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com        entries.
149736a4c2aa2dc2363dc093089b732346459ddc3b65reed@android.com     */
1498fed86bdb8b9f037439bbfa7cdbd53a581dbc5985reed@google.com    typeface->onFilterRec(rec);
14993e8ae5b457558435218a864dd0e852f83abfe802reed@google.com
150010d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    // be sure to call PostMakeRec(rec) before you actually use it!
150110d2d4d1062ef56526f187e6716c5e747689b598reed@google.com}
150210d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
150310d2d4d1062ef56526f187e6716c5e747689b598reed@google.com/**
150497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
150597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
150697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * to hold it until the returned pointer is refed or forgotten.
150710d2d4d1062ef56526f187e6716c5e747689b598reed@google.com */
150897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comSK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
150910d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
1510ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.comstatic SkMaskGamma* gLinearMaskGamma = NULL;
1511b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkMaskGamma* gMaskGamma = NULL;
1512b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gContrast = SK_ScalarMin;
1513b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gPaintGamma = SK_ScalarMin;
1514b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.comstatic SkScalar gDeviceGamma = SK_ScalarMin;
151597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
151697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * The caller must hold the gMaskGammaCacheMutex and continue to hold it until
151797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * the returned SkMaskGamma pointer is refed or forgotten.
151897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
1519a76de72a6036da0a6b051b14411b80941971f881bungeman@google.comstatic const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
1520b83f6c3cbdabc14d8290b00d9f38ba59bf6719a1mtklein    gMaskGammaCacheMutex.assertHeld();
1521ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
1522ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com        if (NULL == gLinearMaskGamma) {
1523ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com            gLinearMaskGamma = SkNEW(SkMaskGamma);
1524ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com        }
1525a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        return *gLinearMaskGamma;
1526ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    }
152797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
152897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        SkSafeUnref(gMaskGamma);
1529b1a72cb90a9b515978bc9abda1f267f31a544e08bungeman@google.com        gMaskGamma = SkNEW_ARGS(SkMaskGamma, (contrast, paintGamma, deviceGamma));
153097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gContrast = contrast;
153197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gPaintGamma = paintGamma;
153297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com        gDeviceGamma = deviceGamma;
153397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    }
1534a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    return *gMaskGamma;
153597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com}
153697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
1537b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com/*static*/ void SkPaint::Term() {
1538b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1539b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com
1540ae30f5601940c78f4537ee48a6316cfac6740712bungeman@google.com    SkSafeUnref(gLinearMaskGamma);
15415987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com    gLinearMaskGamma = NULL;
1542b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkSafeUnref(gMaskGamma);
15435987f58036574ccf23049b5fe71f29a441d0641dcaryclark@google.com    gMaskGamma = NULL;
1544b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gContrast = SK_ScalarMin;)
1545b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gPaintGamma = SK_ScalarMin;)
1546b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com    SkDEBUGCODE(gDeviceGamma = SK_ScalarMin;)
1547b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com}
1548b24b4fa12be03807a0c3c710ec5ad102f3a8e145bungeman@google.com
154997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
155097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com *  We ensure that the rec is self-consistent and efficient (where possible)
155197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
15528d38d516c0f17d8d9f6b170055ac05ac181c0554sugoi@google.comvoid SkScalerContext::PostMakeRec(const SkPaint&, SkScalerContext::Rec* rec) {
155310d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    /**
155410d2d4d1062ef56526f187e6716c5e747689b598reed@google.com     *  If we're asking for A8, we force the colorlum to be gray, since that
155597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com     *  limits the number of unique entries, and the scaler will only look at
155697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com     *  the lum of one of them.
155710d2d4d1062ef56526f187e6716c5e747689b598reed@google.com     */
1558dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com    switch (rec->fMaskFormat) {
1559d54d3fc82456f8789b3e4dff40faeb7b670bcf4breed        case SkMask::kLCD16_Format: {
1560dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // filter down the luminance color to a finite number of bits
156197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            SkColor color = rec->getLuminanceColor();
1562b5715a1c8003e4a8af2301ab44aeef043547808ereed@google.com            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1563dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
1564dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        }
1565dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kA8_Format: {
1566dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // filter down the luminance to a single component, since A8 can't
1567dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // use per-component information
156897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            SkColor color = rec->getLuminanceColor();
1569dc1cf66483e93c2d12d938bc1ce3b8c60cc68da5jvanverth            U8CPU lum = SkComputeLuminance(SkColorGetR(color),
1570dc1cf66483e93c2d12d938bc1ce3b8c60cc68da5jvanverth                                           SkColorGetG(color),
1571dc1cf66483e93c2d12d938bc1ce3b8c60cc68da5jvanverth                                           SkColorGetB(color));
1572dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // reduce to our finite number of bits
157397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com            color = SkColorSetRGB(lum, lum, lum);
1574b5715a1c8003e4a8af2301ab44aeef043547808ereed@google.com            rec->setLuminanceColor(SkMaskGamma::CanonicalColor(color));
1575dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
1576dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        }
1577dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com        case SkMask::kBW_Format:
1578dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            // No need to differentiate gamma if we're BW
1579532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.com            rec->ignorePreBlend();
1580dd43df99b16b67f7b00457b7fff4b2539da40702reed@google.com            break;
15813e8ae5b457558435218a864dd0e852f83abfe802reed@google.com    }
15828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
15838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MIN_SIZE_FOR_EFFECT_BUFFER  1024
15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#ifdef SK_DEBUG
158717fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com    #define TEST_DESC
158817fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#endif
158917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com
1590fd45079314b739979492601fc7a242aff24c58a3joshualittstatic void write_out_descriptor(SkDescriptor* desc, const SkScalerContext::Rec& rec,
1591fd45079314b739979492601fc7a242aff24c58a3joshualitt                                 const SkPathEffect* pe, SkWriteBuffer* peBuffer,
1592fd45079314b739979492601fc7a242aff24c58a3joshualitt                                 const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
1593fd45079314b739979492601fc7a242aff24c58a3joshualitt                                 const SkRasterizer* ra, SkWriteBuffer* raBuffer,
1594fd45079314b739979492601fc7a242aff24c58a3joshualitt                                 size_t descSize) {
1595fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc->init();
1596fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1598fd45079314b739979492601fc7a242aff24c58a3joshualitt    if (pe) {
1599fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc, kPathEffect_SkDescriptorTag, peBuffer);
1600fd45079314b739979492601fc7a242aff24c58a3joshualitt    }
1601fd45079314b739979492601fc7a242aff24c58a3joshualitt    if (mf) {
1602fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc, kMaskFilter_SkDescriptorTag, mfBuffer);
1603fd45079314b739979492601fc7a242aff24c58a3joshualitt    }
1604fd45079314b739979492601fc7a242aff24c58a3joshualitt    if (ra) {
1605fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc, kRasterizer_SkDescriptorTag, raBuffer);
160657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    }
16078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1608fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc->computeChecksum();
1609fd45079314b739979492601fc7a242aff24c58a3joshualitt}
1610fd45079314b739979492601fc7a242aff24c58a3joshualitt
1611fd45079314b739979492601fc7a242aff24c58a3joshualittstatic size_t fill_out_rec(const SkPaint& paint, SkScalerContext::Rec* rec,
1612fd45079314b739979492601fc7a242aff24c58a3joshualitt                           const SkDeviceProperties* deviceProperties,
1613fd45079314b739979492601fc7a242aff24c58a3joshualitt                           const SkMatrix* deviceMatrix, bool ignoreGamma,
1614fd45079314b739979492601fc7a242aff24c58a3joshualitt                           const SkPathEffect* pe, SkWriteBuffer* peBuffer,
1615fd45079314b739979492601fc7a242aff24c58a3joshualitt                           const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
1616fd45079314b739979492601fc7a242aff24c58a3joshualitt                           const SkRasterizer* ra, SkWriteBuffer* raBuffer) {
1617fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkScalerContext::MakeRec(paint, deviceProperties, deviceMatrix, rec);
1618fd45079314b739979492601fc7a242aff24c58a3joshualitt    if (ignoreGamma) {
1619fd45079314b739979492601fc7a242aff24c58a3joshualitt        rec->ignorePreBlend();
1620fd45079314b739979492601fc7a242aff24c58a3joshualitt    }
16218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1622fd45079314b739979492601fc7a242aff24c58a3joshualitt    int entryCount = 1;
1623fd45079314b739979492601fc7a242aff24c58a3joshualitt    size_t descSize = sizeof(*rec);
16248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (pe) {
1626fd45079314b739979492601fc7a242aff24c58a3joshualitt        peBuffer->writeFlattenable(pe);
1627fd45079314b739979492601fc7a242aff24c58a3joshualitt        descSize += peBuffer->bytesWritten();
16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
1629fd45079314b739979492601fc7a242aff24c58a3joshualitt        rec->fMaskFormat = SkMask::kA8_Format;  // force antialiasing when we do the scan conversion
16308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // seems like we could support kLCD as well at this point...
16318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mf) {
1633fd45079314b739979492601fc7a242aff24c58a3joshualitt        mfBuffer->writeFlattenable(mf);
1634fd45079314b739979492601fc7a242aff24c58a3joshualitt        descSize += mfBuffer->bytesWritten();
16358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
1636fd45079314b739979492601fc7a242aff24c58a3joshualitt        rec->fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
1637a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com        /* Pre-blend is not currently applied to filtered text.
1638a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           The primary filter is blur, for which contrast makes no sense,
1639a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           and for which the destination guess error is more visible.
1640a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com           Also, all existing users of blur have calibrated for linear. */
1641fd45079314b739979492601fc7a242aff24c58a3joshualitt        rec->ignorePreBlend();
16428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (ra) {
1644fd45079314b739979492601fc7a242aff24c58a3joshualitt        raBuffer->writeFlattenable(ra);
1645fd45079314b739979492601fc7a242aff24c58a3joshualitt        descSize += raBuffer->bytesWritten();
16468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        entryCount += 1;
1647fd45079314b739979492601fc7a242aff24c58a3joshualitt        rec->fMaskFormat = SkMask::kA8_Format;  // force antialiasing when we do the scan conversion
16488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
164910d2d4d1062ef56526f187e6716c5e747689b598reed@google.com
165010d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    ///////////////////////////////////////////////////////////////////////////
165110d2d4d1062ef56526f187e6716c5e747689b598reed@google.com    // Now that we're done tweaking the rec, call the PostMakeRec cleanup
1652fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkScalerContext::PostMakeRec(paint, rec);
1653fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
16548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    descSize += SkDescriptor::ComputeOverhead(entryCount);
1655fd45079314b739979492601fc7a242aff24c58a3joshualitt    return descSize;
1656fd45079314b739979492601fc7a242aff24c58a3joshualitt}
16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1658fd45079314b739979492601fc7a242aff24c58a3joshualitt#ifdef TEST_DESC
1659fd45079314b739979492601fc7a242aff24c58a3joshualittstatic void test_desc(const SkScalerContext::Rec& rec,
1660fd45079314b739979492601fc7a242aff24c58a3joshualitt                      const SkPathEffect* pe, SkWriteBuffer* peBuffer,
1661fd45079314b739979492601fc7a242aff24c58a3joshualitt                      const SkMaskFilter* mf, SkWriteBuffer* mfBuffer,
1662fd45079314b739979492601fc7a242aff24c58a3joshualitt                      const SkRasterizer* ra, SkWriteBuffer* raBuffer,
1663fd45079314b739979492601fc7a242aff24c58a3joshualitt                      const SkDescriptor* desc, size_t descSize) {
1664fd45079314b739979492601fc7a242aff24c58a3joshualitt    // Check that we completely write the bytes in desc (our key), and that
1665fd45079314b739979492601fc7a242aff24c58a3joshualitt    // there are no uninitialized bytes. If there were, then we would get
1666fd45079314b739979492601fc7a242aff24c58a3joshualitt    // false-misses (or worse, false-hits) in our fontcache.
1667fd45079314b739979492601fc7a242aff24c58a3joshualitt    //
1668fd45079314b739979492601fc7a242aff24c58a3joshualitt    // We do this buy filling 2 others, one with 0s and the other with 1s
1669fd45079314b739979492601fc7a242aff24c58a3joshualitt    // and create those, and then check that all 3 are identical.
1670fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkAutoDescriptor    ad1(descSize);
1671fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkAutoDescriptor    ad2(descSize);
1672fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkDescriptor*       desc1 = ad1.getDesc();
1673fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkDescriptor*       desc2 = ad2.getDesc();
1674fd45079314b739979492601fc7a242aff24c58a3joshualitt
1675fd45079314b739979492601fc7a242aff24c58a3joshualitt    memset(desc1, 0x00, descSize);
1676fd45079314b739979492601fc7a242aff24c58a3joshualitt    memset(desc2, 0xFF, descSize);
1677fd45079314b739979492601fc7a242aff24c58a3joshualitt
1678fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc1->init();
1679fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc2->init();
1680fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1681fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
16828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (pe) {
1684fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc1, kPathEffect_SkDescriptorTag, peBuffer);
1685fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc2, kPathEffect_SkDescriptorTag, peBuffer);
16868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mf) {
1688fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc1, kMaskFilter_SkDescriptorTag, mfBuffer);
1689fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc2, kMaskFilter_SkDescriptorTag, mfBuffer);
16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (ra) {
1692fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc1, kRasterizer_SkDescriptorTag, raBuffer);
1693fd45079314b739979492601fc7a242aff24c58a3joshualitt        add_flattenable(desc2, kRasterizer_SkDescriptorTag, raBuffer);
16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1696fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkASSERT(descSize == desc1->getLength());
1697fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkASSERT(descSize == desc2->getLength());
1698fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc1->computeChecksum();
1699fd45079314b739979492601fc7a242aff24c58a3joshualitt    desc2->computeChecksum();
1700fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkASSERT(!memcmp(desc, desc1, descSize));
1701fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkASSERT(!memcmp(desc, desc2, descSize));
1702fd45079314b739979492601fc7a242aff24c58a3joshualitt}
1703fd45079314b739979492601fc7a242aff24c58a3joshualitt#endif
1704fd45079314b739979492601fc7a242aff24c58a3joshualitt
1705fd45079314b739979492601fc7a242aff24c58a3joshualitt/* see the note on ignoreGamma on descriptorProc */
17062b6acb4ed52483bc2a89dbbaa6f0db4fdb217cd3joshualittvoid SkPaint::getScalerContextDescriptor(SkAutoDescriptor* ad,
17072b6acb4ed52483bc2a89dbbaa6f0db4fdb217cd3joshualitt                                         const SkDeviceProperties* deviceProperties,
17082b6acb4ed52483bc2a89dbbaa6f0db4fdb217cd3joshualitt                                         const SkMatrix* deviceMatrix, bool ignoreGamma) const {
1709fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkScalerContext::Rec    rec;
1710fd45079314b739979492601fc7a242aff24c58a3joshualitt
1711fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkPathEffect*   pe = this->getPathEffect();
1712fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkMaskFilter*   mf = this->getMaskFilter();
1713fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkRasterizer*   ra = this->getRasterizer();
1714fd45079314b739979492601fc7a242aff24c58a3joshualitt
1715fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkWriteBuffer   peBuffer, mfBuffer, raBuffer;
1716fd45079314b739979492601fc7a242aff24c58a3joshualitt    size_t descSize = fill_out_rec(*this, &rec, deviceProperties, deviceMatrix, ignoreGamma,
1717fd45079314b739979492601fc7a242aff24c58a3joshualitt                                   pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
1718fd45079314b739979492601fc7a242aff24c58a3joshualitt
17192b6acb4ed52483bc2a89dbbaa6f0db4fdb217cd3joshualitt    ad->reset(descSize);
17202b6acb4ed52483bc2a89dbbaa6f0db4fdb217cd3joshualitt    SkDescriptor* desc = ad->getDesc();
1721fd45079314b739979492601fc7a242aff24c58a3joshualitt
1722fd45079314b739979492601fc7a242aff24c58a3joshualitt    write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
1723fd45079314b739979492601fc7a242aff24c58a3joshualitt
17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(descSize == desc->getLength());
17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
172617fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#ifdef TEST_DESC
1727fd45079314b739979492601fc7a242aff24c58a3joshualitt    test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
1728fd45079314b739979492601fc7a242aff24c58a3joshualitt#endif
1729fd45079314b739979492601fc7a242aff24c58a3joshualitt}
1730fd45079314b739979492601fc7a242aff24c58a3joshualitt
1731fd45079314b739979492601fc7a242aff24c58a3joshualitt/*
1732fd45079314b739979492601fc7a242aff24c58a3joshualitt *  ignoreGamma tells us that the caller just wants metrics that are unaffected
1733fd45079314b739979492601fc7a242aff24c58a3joshualitt *  by gamma correction, so we set the rec to ignore preblend: i.e. gamma = 1,
1734fd45079314b739979492601fc7a242aff24c58a3joshualitt *  contrast = 0, luminanceColor = transparent black.
1735fd45079314b739979492601fc7a242aff24c58a3joshualitt */
1736fd45079314b739979492601fc7a242aff24c58a3joshualittvoid SkPaint::descriptorProc(const SkDeviceProperties* deviceProperties,
1737fd45079314b739979492601fc7a242aff24c58a3joshualitt                             const SkMatrix* deviceMatrix,
1738fd45079314b739979492601fc7a242aff24c58a3joshualitt                             void (*proc)(SkTypeface*, const SkDescriptor*, void*),
1739fd45079314b739979492601fc7a242aff24c58a3joshualitt                             void* context, bool ignoreGamma) const {
1740fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkScalerContext::Rec    rec;
1741fd45079314b739979492601fc7a242aff24c58a3joshualitt
1742fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkPathEffect*   pe = this->getPathEffect();
1743fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkMaskFilter*   mf = this->getMaskFilter();
1744fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkRasterizer*   ra = this->getRasterizer();
1745fd45079314b739979492601fc7a242aff24c58a3joshualitt
1746fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkWriteBuffer   peBuffer, mfBuffer, raBuffer;
1747fd45079314b739979492601fc7a242aff24c58a3joshualitt    size_t descSize = fill_out_rec(*this, &rec, deviceProperties, deviceMatrix, ignoreGamma,
1748fd45079314b739979492601fc7a242aff24c58a3joshualitt                                   pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer);
1749fd45079314b739979492601fc7a242aff24c58a3joshualitt
1750fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkAutoDescriptor    ad(descSize);
1751fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkDescriptor*       desc = ad.getDesc();
1752fd45079314b739979492601fc7a242aff24c58a3joshualitt
1753fd45079314b739979492601fc7a242aff24c58a3joshualitt    write_out_descriptor(desc, rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, descSize);
1754fd45079314b739979492601fc7a242aff24c58a3joshualitt
1755fd45079314b739979492601fc7a242aff24c58a3joshualitt    SkASSERT(descSize == desc->getLength());
1756fd45079314b739979492601fc7a242aff24c58a3joshualitt
1757fd45079314b739979492601fc7a242aff24c58a3joshualitt#ifdef TEST_DESC
1758fd45079314b739979492601fc7a242aff24c58a3joshualitt    test_desc(rec, pe, &peBuffer, mf, &mfBuffer, ra, &raBuffer, desc, descSize);
175917fb387a56f8fcfcb9ccf585e2c53ee8e709028dreed@google.com#endif
1760fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
176190808e87c21e93b8e670360655e0b0eb12cb2f87reed@google.com    proc(fTypeface, desc, context);
17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1764532470f34dbe9fc0b8b71e3917eca8894feaf336bungeman@google.comSkGlyphCache* SkPaint::detachCache(const SkDeviceProperties* deviceProperties,
17652d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                   const SkMatrix* deviceMatrix,
17662d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                   bool ignoreGamma) const {
17678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache* cache;
17682d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    this->descriptorProc(deviceProperties, deviceMatrix, DetachDescProc, &cache, ignoreGamma);
17698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return cache;
17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
177297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/**
177397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
177497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com */
177597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com//static
177697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.comSkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContext::Rec& rec) {
177797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
1778a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    const SkMaskGamma& maskGamma = cachedMaskGamma(rec.getContrast(),
1779a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com                                                   rec.getPaintGamma(),
1780a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com                                                   rec.getDeviceGamma());
1781a76de72a6036da0a6b051b14411b80941971f881bungeman@google.com    return maskGamma.preBlend(rec.getLuminanceColor());
178297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com}
178397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
17842d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthsize_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
17852d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                        SkScalar deviceGamma, int* width, int* height) {
17862d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
17872d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
17882d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   paintGamma,
17892d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   deviceGamma);
17902d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
17912d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    maskGamma.getGammaTableDimensions(width, height);
17922d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    size_t size = (*width)*(*height)*sizeof(uint8_t);
17932d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
17942d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    return size;
17952d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth}
17962d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
17972d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverthvoid SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
17982d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                      void* data) {
17992d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
18002d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const SkMaskGamma& maskGamma = cachedMaskGamma(contrast,
18012d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   paintGamma,
18022d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth                                                   deviceGamma);
18032d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    int width, height;
18042d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    maskGamma.getGammaTableDimensions(&width, &height);
18052d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    size_t size = width*height*sizeof(uint8_t);
18062d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    const uint8_t* gammaTables = maskGamma.getGammaTables();
18072d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    memcpy(data, gammaTables, size);
18082d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth}
18092d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
18102d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth
18118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
18128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStream.h"
18148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1815aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uintptr_t asint(const void* p) {
1816aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return reinterpret_cast<uintptr_t>(p);
1817aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
1818aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1819aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comunion Scalar32 {
1820aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkScalar    fScalar;
1821aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    uint32_t    f32;
1822aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com};
1823aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1824aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1825aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1826aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    Scalar32 tmp;
1827aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    tmp.fScalar = value;
1828aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    *ptr = tmp.f32;
1829aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return ptr + 1;
1830aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
1831aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1832aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic SkScalar read_scalar(const uint32_t*& ptr) {
1833aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1834aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    Scalar32 tmp;
1835aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    tmp.f32 = *ptr++;
1836aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return tmp.fScalar;
1837aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
1838aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1839aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comstatic uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1840aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(a == (uint8_t)a);
1841aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(b == (uint8_t)b);
1842aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(c == (uint8_t)c);
1843aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    SkASSERT(d == (uint8_t)d);
1844aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    return (a << 24) | (b << 16) | (c << 8) | d;
1845aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com}
1846aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
184785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#ifdef SK_DEBUG
184885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    static void ASSERT_FITS_IN(uint32_t value, int bitCount) {
184985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        SkASSERT(bitCount > 0 && bitCount <= 32);
185085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        uint32_t mask = ~0U;
185185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        mask >>= (32 - bitCount);
185285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org        SkASSERT(0 == (value & ~mask));
185385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    }
185485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#else
185585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    #define ASSERT_FITS_IN(value, bitcount)
185685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org#endif
185785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
1858aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.comenum FlatFlags {
185988fd0fbcccea615f2d2cd61a121ac9e3185adfe4mtklein    kHasTypeface_FlatFlag = 0x1,
186088fd0fbcccea615f2d2cd61a121ac9e3185adfe4mtklein    kHasEffects_FlatFlag  = 0x2,
1861667b98d947892cec939669bccf204ab9ed565c4eskia.committer@gmail.com
186288fd0fbcccea615f2d2cd61a121ac9e3185adfe4mtklein    kFlatFlagMask         = 0x3,
186385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org};
186485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
186585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgenum BitsPerField {
186685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFlags_BPF  = 16,
186785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kHint_BPF   = 2,
186885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kAlign_BPF  = 2,
186985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFilter_BPF = 2,
187085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    kFlatFlags_BPF  = 3,
1871aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com};
1872aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
187385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic inline int BPF_Mask(int bits) {
187485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (1 << bits) - 1;
187585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
187685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
187785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
187885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org                                 unsigned filter, unsigned flatFlags) {
187985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(flags, kFlags_BPF);
188085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(hint, kHint_BPF);
188185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(align, kAlign_BPF);
188285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(filter, kFilter_BPF);
188385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    ASSERT_FITS_IN(flatFlags, kFlatFlags_BPF);
188485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
188585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // left-align the fields of "known" size, and right-align the last (flatFlags) so it can easly
188685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    // add more bits in the future.
188785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (flags << 16) | (hint << 14) | (align << 12) | (filter << 10) | flatFlags;
188885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
188985faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
189085faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.orgstatic FlatFlags unpack_paint_flags(SkPaint* paint, uint32_t packed) {
189185faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setFlags(packed >> 16);
189285faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setHinting((SkPaint::Hinting)((packed >> 14) & BPF_Mask(kHint_BPF)));
189385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    paint->setTextAlign((SkPaint::Align)((packed >> 12) & BPF_Mask(kAlign_BPF)));
189493a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed    paint->setFilterQuality((SkFilterQuality)((packed >> 10) & BPF_Mask(kFilter_BPF)));
189585faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    return (FlatFlags)(packed & kFlatFlagMask);
189685faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org}
189785faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
1898aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com// The size of a flat paint's POD fields
1899d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.comstatic const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
19001f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        1 * sizeof(SkColor) +
19011f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        1 * sizeof(uint16_t) +
19021f1543f012b8834ea760175a023eb127bde2b895reed@google.com                                        6 * sizeof(uint8_t);
1903aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1904aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com/*  To save space/time, we analyze the paint, and write a truncated version of
1905aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    it if there are not tricky elements like shaders, etc.
1906aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com */
19078b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPaint::flatten(SkWriteBuffer& buffer) const {
1908aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    uint8_t flatFlags = 0;
1909aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (this->getTypeface()) {
1910aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        flatFlags |= kHasTypeface_FlatFlag;
1911aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
1912aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (asint(this->getPathEffect()) |
1913aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getShader()) |
1914aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getXfermode()) |
1915aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getMaskFilter()) |
1916aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getColorFilter()) |
1917aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        asint(this->getRasterizer()) |
191854e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        asint(this->getLooper()) |
1919b0a34d80c5c7b06db8083a547f8e499781a9c169reed@google.com        asint(this->getAnnotation()) |
192054e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        asint(this->getImageFilter())) {
1921aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        flatFlags |= kHasEffects_FlatFlag;
1922aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
1923c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com
19248b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
19258b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    uint32_t* ptr = buffer.reserve(kPODPaintSize);
19268b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
19278b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextSize());
19288b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextScaleX());
19298b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getTextSkewX());
19308b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getStrokeWidth());
19318b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    ptr = write_scalar(ptr, this->getStrokeMiter());
19328b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    *ptr++ = this->getColor();
193385faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org
193485faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    *ptr++ = pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(),
193593a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed                              this->getFilterQuality(), flatFlags);
19368b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
19378b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org                    this->getStyle(), this->getTextEncoding());
1938aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1939aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    // now we're done with ptr and the (pre)reserved space. If we need to write
1940aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    // additional fields, use the buffer directly
1941aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasTypeface_FlatFlag) {
1942aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeTypeface(this->getTypeface());
1943aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
1944aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasEffects_FlatFlag) {
1945aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getPathEffect());
1946aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getShader());
1947aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getXfermode());
1948aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getMaskFilter());
1949aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getColorFilter());
1950aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getRasterizer());
1951aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        buffer.writeFlattenable(this->getLooper());
195254e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        buffer.writeFlattenable(this->getImageFilter());
19530cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com
19540cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        if (fAnnotation) {
19550cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            buffer.writeBool(true);
19560cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            fAnnotation->writeToBuffer(buffer);
19570cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        } else {
19580cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com            buffer.writeBool(false);
19590cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        }
1960aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
19618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
19628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19638b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPaint::unflatten(SkReadBuffer& buffer) {
19648b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
19658b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    const void* podData = buffer.skip(kPODPaintSize);
19668b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
19678b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
19688b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    // the order we read must match the order we wrote in flatten()
19698b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextSize(read_scalar(pod));
19708b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextScaleX(read_scalar(pod));
19718b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextSkewX(read_scalar(pod));
19728b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeWidth(read_scalar(pod));
19738b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeMiter(read_scalar(pod));
19748b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setColor(*pod++);
19758b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
197688fd0fbcccea615f2d2cd61a121ac9e3185adfe4mtklein    unsigned flatFlags = unpack_paint_flags(this, *pod++);
19778b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
197885faf50875fcf6008880a98aaa05d12ae8dad343commit-bot@chromium.org    uint32_t tmp = *pod++;
19798b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
19808b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
19818b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
19828b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
1983aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1984aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasTypeface_FlatFlag) {
1985aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setTypeface(buffer.readTypeface());
1986aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    } else {
1987aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setTypeface(NULL);
1988aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
1989aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com
1990aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    if (flatFlags & kHasEffects_FlatFlag) {
1991353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setPathEffect(buffer.readPathEffect()));
1992353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setShader(buffer.readShader()));
1993353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setXfermode(buffer.readXfermode()));
1994353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setMaskFilter(buffer.readMaskFilter()));
1995353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setColorFilter(buffer.readColorFilter()));
1996353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setRasterizer(buffer.readRasterizer()));
1997353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setLooper(buffer.readDrawLooper()));
1998353482251e61971a8cf3a60bbb6910f482be634freed@google.com        SkSafeUnref(this->setImageFilter(buffer.readImageFilter()));
1999fbc58a305518fe611113a51649bf557c991ac8cfskia.committer@gmail.com
20000cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        if (buffer.readBool()) {
2001d957984c1efbd18f3b2bbeca78d282837c5a2ae1commit-bot@chromium.org            this->setAnnotation(SkAnnotation::Create(buffer))->unref();
20020cd2ac6c721120a2628524dad91798aa3e7ec41dreed@google.com        }
2003aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    } else {
2004aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setPathEffect(NULL);
2005aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setShader(NULL);
2006aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setXfermode(NULL);
2007aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setMaskFilter(NULL);
2008aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setColorFilter(NULL);
2009aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setRasterizer(NULL);
2010aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com        this->setLooper(NULL);
201154e01b2ab985e7a7d38109812069d056d128bfa1senorblanco@chromium.org        this->setImageFilter(NULL);
2012aefd2bc75738963b9b6579897be32bfbc8fb00afreed@android.com    }
20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
20168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
201782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkShader* SkPaint::setShader(SkShader* shader) {
20188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fShader, shader);
20198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return shader;
20208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
202282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
20238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fColorFilter, filter);
20248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
20258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
202782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
20288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fXfermode, mode);
20298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return mode;
20308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20320baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.comSkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
2033d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    SkSafeUnref(fXfermode);
2034d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    fXfermode = SkXfermode::Create(mode);
2035d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com    return fXfermode;
2036d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com}
2037d66eef71012bdbc14834c12c8af1c946fe0d8499reed@android.com
203882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
20398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fPathEffect, effect);
20408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return effect;
20418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
204382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
20448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt_SafeAssign(fMaskFilter, filter);
20458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return filter;
20468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
204882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
20498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
205005d9044de4f1c6e791df66a425638752daac4c6breedbool SkPaint::getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
205105d9044de4f1c6e791df66a425638752daac4c6breed                          SkScalar resScale) const {
205205d9044de4f1c6e791df66a425638752daac4c6breed    SkStrokeRec rec(*this, resScale);
20538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2054fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    const SkPath* srcPtr = &src;
2055fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    SkPath tmpPath;
205672cf4927e503f49c4bd07369e85764ddde57071breed@google.com
20574bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com    if (fPathEffect && fPathEffect->filterPath(&tmpPath, src, &rec, cullRect)) {
2058fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        srcPtr = &tmpPath;
20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2061fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    if (!rec.applyToPath(dst, *srcPtr)) {
2062fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        if (srcPtr == &tmpPath) {
2063fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // If path's were copy-on-write, this trick would not be needed.
2064fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // As it is, we want to save making a deep-copy from tmpPath -> dst
2065fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // since we know we're just going to delete tmpPath when we return,
2066fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            // so the swap saves that copy.
2067fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            dst->swap(tmpPath);
2068fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com        } else {
2069fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com            *dst = *srcPtr;
2070d3521f1a8dc07fe84d6a8f2151b0c176ff1ec8careed@google.com        }
2071d3521f1a8dc07fe84d6a8f2151b0c176ff1ec8careed@google.com    }
2072fd4be26c4202ae91f0f7cf2c03e44b5169d885ebreed@google.com    return !rec.isHairlineStyle();
20738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
20748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2075e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.comconst SkRect& SkPaint::doComputeFastBounds(const SkRect& origSrc,
2076a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com                                           SkRect* storage,
2077a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com                                           Style style) const {
20788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(storage);
20799efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2080e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    const SkRect* src = &origSrc;
2081e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com
20829efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    if (this->getLooper()) {
20839efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2084e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        this->getLooper()->computeFastBounds(*this, *src, storage);
20859efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        return *storage;
20869efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    }
20879efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2088e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    SkRect tmpSrc;
2089e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    if (this->getPathEffect()) {
2090e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        this->getPathEffect()->computeFastBounds(&tmpSrc, origSrc);
2091e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        src = &tmpSrc;
2092e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com    }
2093e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com
2094a584aed5f709ff9655fd3326e23cd6f602ac7ae4reed@google.com    if (kFill_Style != style) {
20959efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        // since we're stroked, outset the rect by the radius (and join type)
20969efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        SkScalar radius = SkScalarHalf(this->getStrokeWidth());
20979efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        if (0 == radius) {  // hairline
20989efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            radius = SK_Scalar1;
20999efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
21009efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            SkScalar scale = this->getStrokeMiter();
21019efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            if (scale > SK_Scalar1) {
21029efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com                radius = SkScalarMul(radius, scale);
21039efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com            }
21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2105e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        storage->set(src->fLeft - radius, src->fTop - radius,
2106e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com                     src->fRight + radius, src->fBottom + radius);
21079efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    } else {
2108e4f10a70807166484e5a6303a5cd0034e5e87abareed@google.com        *storage = *src;
21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21109efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
21119efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    if (this->getMaskFilter()) {
21129efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com        this->getMaskFilter()->computeFastBounds(*storage, storage);
21139efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com    }
21149efd9a048aebaa6681afb76b18e1a7dd642078d3reed@google.com
2115336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (this->getImageFilter()) {
2116336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        this->getImageFilter()->computeFastBounds(*storage, storage);
2117336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
2118336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
2119d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    return *storage;
21208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
21218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21220f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
212383658305a1bda2d862f50145ecf5cb697b575e86reed
2124791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.comvoid SkPaint::toString(SkString* str) const {
2125791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dl><dt>SkPaint:</dt><dd><dl>");
2126791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2127791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkTypeface* typeface = this->getTypeface();
212849f085dddff10473b6ebf832a974288300224e60bsalomon    if (typeface) {
2129d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman        SkDynamicMemoryWStream ostream;
2130d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman        typeface->serialize(&ostream);
2131a1193e4b0e34a7e4e1bd33e9708d7341679f8321scroggo        SkAutoTDelete<SkStreamAsset> istream(ostream.detachAsStream());
2132d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman        SkFontDescriptor descriptor(istream);
2133791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2134791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Font Family Name:</dt><dd>");
2135791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getFamilyName());
2136791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd><dt>Font Full Name:</dt><dd>");
2137791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getFullName());
2138791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd><dt>Font PS Name:</dt><dd>");
2139791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append(descriptor.getPostscriptName());
2140791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2141791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2142791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2143791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextSize:</dt><dd>");
2144791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextSize());
2145791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2146791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2147791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextScaleX:</dt><dd>");
2148791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextScaleX());
2149791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2150791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2151791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextSkewX:</dt><dd>");
2152791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getTextSkewX());
2153791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2154791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2155791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkPathEffect* pathEffect = this->getPathEffect();
215649f085dddff10473b6ebf832a974288300224e60bsalomon    if (pathEffect) {
2157791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>PathEffect:</dt><dd>");
215842dbfa8651861f2f686879c996aab9f9f82277ddrobertphillips        pathEffect->toString(str);
2159791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2160791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2161791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2162791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkShader* shader = this->getShader();
216349f085dddff10473b6ebf832a974288300224e60bsalomon    if (shader) {
2164791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Shader:</dt><dd>");
21651202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        shader->toString(str);
2166791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2167791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2168791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2169791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkXfermode* xfer = this->getXfermode();
217049f085dddff10473b6ebf832a974288300224e60bsalomon    if (xfer) {
2171791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Xfermode:</dt><dd>");
21721202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        xfer->toString(str);
2173791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2174791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2175791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2176791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkMaskFilter* maskFilter = this->getMaskFilter();
217749f085dddff10473b6ebf832a974288300224e60bsalomon    if (maskFilter) {
2178791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>MaskFilter:</dt><dd>");
21791202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        maskFilter->toString(str);
2180791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2181791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2182791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2183791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkColorFilter* colorFilter = this->getColorFilter();
218449f085dddff10473b6ebf832a974288300224e60bsalomon    if (colorFilter) {
2185791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>ColorFilter:</dt><dd>");
21861202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        colorFilter->toString(str);
2187791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2188791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2189791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2190791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkRasterizer* rasterizer = this->getRasterizer();
219149f085dddff10473b6ebf832a974288300224e60bsalomon    if (rasterizer) {
2192791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Rasterizer:</dt><dd>");
2193791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2194791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2195791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2196791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkDrawLooper* looper = this->getLooper();
219749f085dddff10473b6ebf832a974288300224e60bsalomon    if (looper) {
2198791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>DrawLooper:</dt><dd>");
21991202c2ac563cdeb07406872825706b83e335c977robertphillips@google.com        looper->toString(str);
2200791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2201791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2202791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2203791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkImageFilter* imageFilter = this->getImageFilter();
220449f085dddff10473b6ebf832a974288300224e60bsalomon    if (imageFilter) {
2205791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>ImageFilter:</dt><dd>");
2206f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips        imageFilter->toString(str);
2207791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2208791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2209791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2210791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkAnnotation* annotation = this->getAnnotation();
221149f085dddff10473b6ebf832a974288300224e60bsalomon    if (annotation) {
2212791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("<dt>Annotation:</dt><dd>");
2213791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("</dd>");
2214791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2215791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2216791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Color:</dt><dd>0x");
2217791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    SkColor color = this->getColor();
2218791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendHex(color);
2219791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2220791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2221791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Stroke Width:</dt><dd>");
2222791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getStrokeWidth());
2223791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2224791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2225791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Stroke Miter:</dt><dd>");
2226791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->appendScalar(this->getStrokeMiter());
2227791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2228791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2229791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Flags:</dt><dd>(");
2230791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    if (this->getFlags()) {
2231791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        bool needSeparator = false;
2232791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isAntiAlias(), "AntiAlias", &needSeparator);
2233791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isDither(), "Dither", &needSeparator);
2234791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isUnderlineText(), "UnderlineText", &needSeparator);
2235791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isStrikeThruText(), "StrikeThruText", &needSeparator);
2236791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isFakeBoldText(), "FakeBoldText", &needSeparator);
2237791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isLinearText(), "LinearText", &needSeparator);
2238791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isSubpixelText(), "SubpixelText", &needSeparator);
2239791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isDevKernText(), "DevKernText", &needSeparator);
2240791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isLCDRenderText(), "LCDRenderText", &needSeparator);
2241791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isEmbeddedBitmapText(),
2242791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com                          "EmbeddedBitmapText", &needSeparator);
2243791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isAutohinted(), "Autohinted", &needSeparator);
2244791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, this->isVerticalText(), "VerticalText", &needSeparator);
2245791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        SkAddFlagToString(str, SkToBool(this->getFlags() & SkPaint::kGenA8FromLCD_Flag),
2246791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com                          "GenA8FromLCD", &needSeparator);
2247791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    } else {
2248791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com        str->append("None");
2249791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    }
2250791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(")</dd>");
2251791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
22523e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    str->append("<dt>FilterLevel:</dt><dd>");
225393a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed    static const char* gFilterQualityStrings[] = { "None", "Low", "Medium", "High" };
225493a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed    str->append(gFilterQualityStrings[this->getFilterQuality()]);
22553e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com    str->append("</dd>");
22563e7e992a8aa564e75bede2a1dc787142d2c2bab0robertphillips@google.com
2257791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextAlign:</dt><dd>");
2258791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gTextAlignStrings[SkPaint::kAlignCount] = { "Left", "Center", "Right" };
2259791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gTextAlignStrings[this->getTextAlign()]);
2260791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2261791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2262791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>CapType:</dt><dd>");
2263791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gStrokeCapStrings[SkPaint::kCapCount] = { "Butt", "Round", "Square" };
2264791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gStrokeCapStrings[this->getStrokeCap()]);
2265791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2266791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2267791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>JoinType:</dt><dd>");
2268791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gJoinStrings[SkPaint::kJoinCount] = { "Miter", "Round", "Bevel" };
2269791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gJoinStrings[this->getStrokeJoin()]);
2270791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2271791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2272791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Style:</dt><dd>");
2273791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gStyleStrings[SkPaint::kStyleCount] = { "Fill", "Stroke", "StrokeAndFill" };
2274791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gStyleStrings[this->getStyle()]);
2275791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2276791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2277791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>TextEncoding:</dt><dd>");
2278791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gTextEncodingStrings[] = { "UTF8", "UTF16", "UTF32", "GlyphID" };
2279791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gTextEncodingStrings[this->getTextEncoding()]);
2280791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2281791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2282791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("<dt>Hinting:</dt><dd>");
2283791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    static const char* gHintingStrings[] = { "None", "Slight", "Normal", "Full" };
2284791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append(gHintingStrings[this->getHinting()]);
2285791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd>");
2286791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
2287791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com    str->append("</dd></dl></dl>");
2288791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com}
2289791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com#endif
2290791f12e6cf558e0dd1689fbb0a6b5eddac9f42adrobertphillips@google.com
22916fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com///////////////////////////////////////////////////////////////////////////////
22928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22936fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comstatic bool has_thick_frame(const SkPaint& paint) {
22946fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    return  paint.getStrokeWidth() > 0 &&
22956fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            paint.getStyle() != SkPaint::kFill_Style;
22968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
22978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
22998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                    const SkPaint& paint,
2300166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com                                    bool applyStrokeAndPathEffects)
2301166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com                                    : fPaint(paint) {
23029e96aa07dbf1210fd35ae8e0c54d4d9822544e89reed    fGlyphCacheProc = paint.getMeasureCacheProc(true);
23038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2304166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    fPaint.setLinearText(true);
23058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
23068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23076fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
23088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        applyStrokeAndPathEffects = false;
23096fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
23108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2311166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    // can't use our canonical size if we need to apply patheffects
2312166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com    if (fPaint.getPathEffect() == NULL) {
23138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
23148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2315166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com        if (has_thick_frame(fPaint)) {
231680ea19ca4bdd68c1493666a5fe7e4ce9d43ded8breed            fPaint.setStrokeWidth(fPaint.getStrokeWidth() / fScale);
2317166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com        }
23186fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    } else {
23198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fScale = SK_Scalar1;
23206fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    }
232172cf4927e503f49c4bd07369e85764ddde57071breed@google.com
23226fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!applyStrokeAndPathEffects) {
23238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setStyle(SkPaint::kFill_Style);
23248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPaint.setPathEffect(NULL);
23258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23272d2a68c51b4a71bd60760510bf2b2e58bc9890b2jvanverth    fCache = fPaint.detachCache(NULL, NULL, false);
23288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPaint::Style  style = SkPaint::kFill_Style;
23308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPathEffect*   pe = NULL;
23318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23326fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (!applyStrokeAndPathEffects) {
23338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        style = paint.getStyle();   // restore
23348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        pe = paint.getPathEffect();     // restore
23358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setStyle(style);
23378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setPathEffect(pe);
23388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPaint.setMaskFilter(paint.getMaskFilter());    // restore
23398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now compute fXOffset if needed
23418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkScalar xOffset = 0;
23436fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com    if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
23448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int      count;
23456fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
23466fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com                                                         &count, NULL), fScale);
23476fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
23488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            width = SkScalarHalf(width);
23496fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        }
23508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        xOffset = -width;
23518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fXPos = xOffset;
23538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPrevAdvance = 0;
23548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fText = text;
23568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fStop = text + length;
23577b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com
235844da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com    fXYIndex = paint.isVerticalText() ? 1 : 0;
23598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23616fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.comSkTextToPathIter::~SkTextToPathIter() {
23628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkGlyphCache::AttachCache(fCache);
23638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
23648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23657b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.combool SkTextToPathIter::next(const SkPath** path, SkScalar* xpos) {
23667b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    if (fText < fStop) {
23678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
23688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
237044da42e92f46cae9e96003999f02db04b8b5ff2dreed@google.com        fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
23718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23726fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com        if (glyph.fWidth) {
23737b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            if (path) {
23747b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com                *path = fCache->findPath(glyph);
23757b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            }
23767b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        } else {
23777b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            if (path) {
23787b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com                *path = NULL;
23796fb7e2e153717b69831c34663cbb7bc26ac8eef9reed@google.com            }
23808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
23817b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        if (xpos) {
23827b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com            *xpos = fXPos;
23837b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        }
23847b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com        return true;
23858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
23867b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com    return false;
23878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2388dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com
2389dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com///////////////////////////////////////////////////////////////////////////////
2390dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com
2391f539b8cdee0204985edca028eec826ee94a0c472reed// return true if the filter exists, and may affect alpha
2392f539b8cdee0204985edca028eec826ee94a0c472reedstatic bool affects_alpha(const SkColorFilter* cf) {
2393f539b8cdee0204985edca028eec826ee94a0c472reed    return cf && !(cf->getFlags() & SkColorFilter::kAlphaUnchanged_Flag);
2394f539b8cdee0204985edca028eec826ee94a0c472reed}
2395f539b8cdee0204985edca028eec826ee94a0c472reed
2396f539b8cdee0204985edca028eec826ee94a0c472reed// return true if the filter exists, and may affect alpha
2397f539b8cdee0204985edca028eec826ee94a0c472reedstatic bool affects_alpha(const SkImageFilter* imf) {
2398f539b8cdee0204985edca028eec826ee94a0c472reed    // TODO: check if we should allow imagefilters to broadcast that they don't affect alpha
2399f539b8cdee0204985edca028eec826ee94a0c472reed    // ala colorfilters
2400f539b8cdee0204985edca028eec826ee94a0c472reed    return imf != NULL;
2401f539b8cdee0204985edca028eec826ee94a0c472reed}
2402f539b8cdee0204985edca028eec826ee94a0c472reed
2403dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.combool SkPaint::nothingToDraw() const {
2404733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com    if (fLooper) {
2405733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com        return false;
2406733e302b1c36a4310d91ea61ea127379f16d1318reed@google.com    }
2407dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    SkXfermode::Mode mode;
2408dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    if (SkXfermode::AsMode(fXfermode, &mode)) {
2409dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com        switch (mode) {
2410dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kSrcOver_Mode:
2411dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kSrcATop_Mode:
2412dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDstOut_Mode:
2413dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDstOver_Mode:
2414dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kPlus_Mode:
2415f539b8cdee0204985edca028eec826ee94a0c472reed                if (0 == this->getAlpha()) {
2416f539b8cdee0204985edca028eec826ee94a0c472reed                    return !affects_alpha(fColorFilter) && !affects_alpha(fImageFilter);
2417f539b8cdee0204985edca028eec826ee94a0c472reed                }
2418f539b8cdee0204985edca028eec826ee94a0c472reed                break;
2419dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            case SkXfermode::kDst_Mode:
2420dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com                return true;
2421dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com            default:
2422dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com                break;
2423dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com        }
2424dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    }
2425dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com    return false;
2426dcd0f3a980095b77ebe605b49777a4bd37ca7b0areed@google.com}
2427aca1c01f3b39a8159a0ca10ba740d9995027317bcommit-bot@chromium.org
2428fb1fe4f51820731f557e765f8c71cba9a0d28048mtkleinuint32_t SkPaint::getHash() const {
2429fb1fe4f51820731f557e765f8c71cba9a0d28048mtklein    // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields,
2430fb1fe4f51820731f557e765f8c71cba9a0d28048mtklein    // so fBitfields should be 10 pointers and 6 32-bit values from the start.
2431fb1fe4f51820731f557e765f8c71cba9a0d28048mtklein    SK_COMPILE_ASSERT(offsetof(SkPaint, fBitfields) == 10 * sizeof(void*) + 6 * sizeof(uint32_t),
2432fb1fe4f51820731f557e765f8c71cba9a0d28048mtklein                      SkPaint_notPackedTightly);
2433fb1fe4f51820731f557e765f8c71cba9a0d28048mtklein    return SkChecksum::Murmur3(reinterpret_cast<const uint32_t*>(this),
2434fb1fe4f51820731f557e765f8c71cba9a0d28048mtklein                               offsetof(SkPaint, fBitfields) + sizeof(fBitfields));
2435fb1fe4f51820731f557e765f8c71cba9a0d28048mtklein}
2436