11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
105c7fc8f96344cc7f780558c714d3e52f0669b0b8Fabrice Di Meglio#include <new>
115c7fc8f96344cc7f780558c714d3e52f0669b0b8Fabrice Di Meglio
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPaint.h"
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorFilter.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFontHost.h"
151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkImageFilter.h"
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h"
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathEffect.h"
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRasterizer.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkShader.h"
2040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkScalar.h"
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScalerContext.h"
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStroke.h"
2340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkTextFormatParams.h"
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTypeface.h"
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkXfermode.h"
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkAutoKern.h"
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkGlyphCache.h"
284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkPaintDefaults.h"
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// define this to get a printf for out-of-range parameter in setters
311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// e.g. setTextSize(-1)
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger//#define SK_REPORT_API_RANGE_CHECK
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
35725b3e03acb91dc69296554932624b36612bd189Billy Hewlett#include "SkLanguage.h"
3687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#define GEN_ID_INC                  fGenerationID++
3787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
3887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#else
3987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#define GEN_ID_INC
4087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#define GEN_ID_INC_EVAL(expression)
4187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
4287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
43c1c43a17e7f2a87951739691056728a80e9aef6bMike ReedSkPaint::SkPaint() {
44c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    // since we may have padding, we zero everything so that our memcmp() call
45c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    // in operator== will work correctly.
46c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    // with this, we can skip 0 and null individual initializations
47c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    sk_bzero(this, sizeof(*this));
48c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed
49c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed#if 0   // not needed with the bzero call above
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTypeface   = NULL;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTextSkewX  = 0;
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPathEffect  = NULL;
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fShader      = NULL;
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fXfermode    = NULL;
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fMaskFilter  = NULL;
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fColorFilter = NULL;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRasterizer  = NULL;
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLooper      = NULL;
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fImageFilter = NULL;
60c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    fWidth      = 0;
61c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed#endif
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fTextSize   = SkPaintDefaults_TextSize;
64c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    fTextScaleX = SK_Scalar1;
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fColor      = SK_ColorBLACK;
664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fMiterLimit = SkPaintDefaults_MiterLimit;
674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fFlags      = SkPaintDefaults_Flags;
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCapType    = kDefault_Cap;
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fJoinType   = kDefault_Join;
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTextAlign  = kLeft_Align;
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStyle      = kFill_Style;
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTextEncoding = kUTF8_TextEncoding;
734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fHinting    = SkPaintDefaults_Hinting;
741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
75725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    fLanguage = SkLanguage();
76212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett    fFontVariant = kDefault_Variant;
7795662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    fGenerationID = 0;
7887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkPaint::SkPaint(const SkPaint& src) {
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    memcpy(this, &src, sizeof(src));
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fTypeface);
8540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fPathEffect);
8640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fShader);
8740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fXfermode);
8840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fMaskFilter);
8940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fColorFilter);
9040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fRasterizer);
9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fLooper);
921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSafeRef(fImageFilter);
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkPaint::~SkPaint() {
9640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fTypeface);
9740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fPathEffect);
9840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fShader);
9940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fXfermode);
10040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fMaskFilter);
10140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fColorFilter);
10240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fRasterizer);
10340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fLooper);
1041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSafeUnref(fImageFilter);
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkPaint& SkPaint::operator=(const SkPaint& src) {
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(&src);
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fTypeface);
11140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fPathEffect);
11240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fShader);
11340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fXfermode);
11440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fMaskFilter);
11540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fColorFilter);
11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fRasterizer);
11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fLooper);
1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSafeRef(src.fImageFilter);
11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fTypeface);
12140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fPathEffect);
12240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fShader);
12340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fXfermode);
12440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fMaskFilter);
12540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fColorFilter);
12640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fRasterizer);
12740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fLooper);
1281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSafeUnref(fImageFilter);
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1319f523ea27ec892a176817dc3a46179c0a910beb4Chet Haase    uint32_t oldGenerationID = fGenerationID;
13287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    memcpy(this, &src, sizeof(src));
1341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1359f523ea27ec892a176817dc3a46179c0a910beb4Chet Haase    fGenerationID = oldGenerationID + 1;
13687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return *this;
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool operator==(const SkPaint& a, const SkPaint& b) {
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //assumes that fGenerationID is the last field in the struct
1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return !memcmp(&a, &b, SK_OFFSETOF(SkPaint, fGenerationID));
1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return !memcmp(&a, &b, sizeof(a));
1471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkPaint::reset() {
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint init;
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1549f523ea27ec892a176817dc3a46179c0a910beb4Chet Haase    uint32_t oldGenerationID = fGenerationID;
15587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *this = init;
1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1589f523ea27ec892a176817dc3a46179c0a910beb4Chet Haase    fGenerationID = oldGenerationID + 1;
15987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
16095662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase}
16195662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase
1621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
16395662ea6ee460cc84014c41a8c13e881cd8be8edChet Haaseuint32_t SkPaint::getGenerationID() const {
16495662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    return fGenerationID;
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
16687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerunsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
1701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAutoGlyphCache autoCache(*this, NULL);
1711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkGlyphCache* cache = autoCache.getCache();
1721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return cache->getBaseGlyphCount(text);
1731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setHinting(Hinting hintingLevel) {
17787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
17887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fHinting = hintingLevel;
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
18187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setFlags(uint32_t flags) {
18287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(fFlags != flags);
18387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fFlags = flags;
1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
18687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setAntiAlias(bool doAA) {
18787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doAA != isAntiAlias());
18887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
19187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setDither(bool doDither) {
19287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doDither != isDither());
19387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
19687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setSubpixelText(bool doSubpixel) {
19787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doSubpixel != isSubpixelText());
19887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
199af2616552738d653d5453915d3236e7154b868cdMike Reed}
200af2616552738d653d5453915d3236e7154b868cdMike Reed
20187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setLCDRenderText(bool doLCDRender) {
20287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doLCDRender != isLCDRenderText());
20387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
20487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger}
20587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
20687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
20787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doEmbeddedBitmapText != isEmbeddedBitmapText());
20887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
2092cf237c941bf5964f654d0ccdd639a26468e1d71Mike Reed}
2102cf237c941bf5964f654d0ccdd639a26468e1d71Mike Reed
21187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setAutohinted(bool useAutohinter) {
21287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(useAutohinter != isAutohinted());
21340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
21440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
21540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
21687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setLinearText(bool doLinearText) {
21787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doLinearText != isLinearText());
21887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkPaint::setVerticalText(bool doVertical) {
2221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GEN_ID_INC_EVAL(doVertical != isVerticalText());
2231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doVertical, kVerticalText_Flag));
2241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setUnderlineText(bool doUnderline) {
22787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doUnderline != isUnderlineText());
22887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
23187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrikeThruText(bool doStrikeThru) {
23287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doStrikeThru != isStrikeThruText());
23387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
23687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setFakeBoldText(bool doFakeBold) {
23787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doFakeBold != isFakeBoldText());
23887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
24187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setDevKernText(bool doDevKern) {
24287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doDevKern != isDevKernText());
24387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
24687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setFilterBitmap(bool doFilter) {
24787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doFilter != isFilterBitmap());
24887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
25187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStyle(Style style) {
25295662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)style < kStyleCount) {
25387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)style != fStyle);
25487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fStyle = style;
25587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
2561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
2571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
2581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
25905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
26287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setColor(SkColor color) {
26387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(color != fColor);
26487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fColor = color;
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
26787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setAlpha(U8CPU a) {
26887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
26987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                                  SkColorGetG(fColor), SkColorGetB(fColor)));
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
27287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
27387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setColor(SkColorSetARGB(a, r, g, b));
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
27687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrokeWidth(SkScalar width) {
27795662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if (width >= 0) {
27887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL(width != fWidth);
27987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fWidth = width;
28087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
2811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
2821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
2831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
28405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
28787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrokeMiter(SkScalar limit) {
28895662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if (limit >= 0) {
28987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL(limit != fMiterLimit);
29087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fMiterLimit = limit;
29187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
2921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
2931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
2941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
29505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
29887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrokeCap(Cap ct) {
29995662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)ct < kCapCount) {
30087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)ct != fCapType);
30187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fCapType = SkToU8(ct);
30287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
3051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
30695662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
30987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrokeJoin(Join jt) {
31095662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)jt < kJoinCount) {
31187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
31287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fJoinType = SkToU8(jt);
31387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
3161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
31795662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
32087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
32287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextAlign(Align align) {
32395662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)align < kAlignCount) {
32487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
32587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fTextAlign = SkToU8(align);
32687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
3291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
33095662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
33387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextSize(SkScalar ts) {
3341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (ts >= 0) {
33587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL(ts != fTextSize);
33687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fTextSize = ts;
33787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setTextSize() called with negative value\n");
3401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
34195662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
34487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextScaleX(SkScalar scaleX) {
34587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(scaleX != fTextScaleX);
34687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fTextScaleX = scaleX;
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
34987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextSkewX(SkScalar skewX) {
35087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(skewX != fTextSkewX);
35187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fTextSkewX = skewX;
3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
35487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextEncoding(TextEncoding encoding) {
35595662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)encoding <= kGlyphID_TextEncoding) {
35687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
35787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fTextEncoding = encoding;
35887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
3611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
36295662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3655c7fc8f96344cc7f780558c714d3e52f0669b0b8Fabrice Di Meglio#ifdef SK_BUILD_FOR_ANDROID
366725b3e03acb91dc69296554932624b36612bd189Billy Hewlettvoid SkPaint::setLanguage(const SkLanguage& language) {
367725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    if(fLanguage != language) {
368725b3e03acb91dc69296554932624b36612bd189Billy Hewlett        fLanguage = language;
3695c7fc8f96344cc7f780558c714d3e52f0669b0b8Fabrice Di Meglio        GEN_ID_INC;
3705c7fc8f96344cc7f780558c714d3e52f0669b0b8Fabrice Di Meglio    }
3715c7fc8f96344cc7f780558c714d3e52f0669b0b8Fabrice Di Meglio}
372212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett
373212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlettvoid SkPaint::setFontVariant(FontVariant fontVariant) {
374212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett    if ((unsigned)fontVariant <= kLast_Variant) {
375212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett        GEN_ID_INC_EVAL((unsigned)fontVariant != fFontVariant);
376212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett        fFontVariant = fontVariant;
377212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett    } else {
378212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett#ifdef SK_REPORT_API_RANGE_CHECK
379212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett        SkDebugf("SkPaint::setFontVariant(%d) out of range\n", fontVariant);
380212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett#endif
381212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett    }
382212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett}
383212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett
3845c7fc8f96344cc7f780558c714d3e52f0669b0b8Fabrice Di Meglio#endif
3855c7fc8f96344cc7f780558c714d3e52f0669b0b8Fabrice Di Meglio
38687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
38887b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkTypeface* SkPaint::setTypeface(SkTypeface* font) {
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fTypeface, font);
39087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC;
3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return font;
3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
39440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fRasterizer, r);
39687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC;
3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return r;
3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
40040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fLooper, looper);
40287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC;
4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return looper;
4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4061cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
4071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRefCnt_SafeAssign(fImageFilter, imageFilter);
4081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GEN_ID_INC;
4091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return imageFilter;
4101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGlyphCache.h"
4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkUtils.h"
4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
41740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void DetachDescProc(const SkDescriptor* desc, void* context) {
418fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
419fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy}
420fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy
4211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
422b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guyconst SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) {
423b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    SkGlyphCache* cache;
424b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    descriptorProc(NULL, DetachDescProc, &cache, true);
425b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy
426b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    const SkGlyph& glyph = cache->getUnicharMetrics(text);
427b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy
428b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    SkGlyphCache::AttachCache(cache);
429b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    return glyph;
430b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy}
431b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy
4321bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guyconst SkGlyph& SkPaint::getGlyphMetrics(uint16_t glyphId) {
4331bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    SkGlyphCache* cache;
4341bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    descriptorProc(NULL, DetachDescProc, &cache, true);
4351bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy
4361bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphId);
4371bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy
4381bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    SkGlyphCache::AttachCache(cache);
4391bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    return glyph;
4401bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy}
4411bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy
44290a1efbdde19ee56c33929592277871509c25893Romain Guyconst void* SkPaint::findImage(const SkGlyph& glyph) {
443fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    // See ::detachCache()
444fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    SkGlyphCache* cache;
445fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    descriptorProc(NULL, DetachDescProc, &cache, true);
44690a1efbdde19ee56c33929592277871509c25893Romain Guy
447fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    const void* image = cache->findImage(glyph);
448fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy
449fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    SkGlyphCache::AttachCache(cache);
450fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    return image;
45190a1efbdde19ee56c33929592277871509c25893Romain Guy}
452dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy
453dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guyint SkPaint::utfToGlyphs(const void* textData, TextEncoding encoding,
454dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy                         size_t byteLength, uint16_t glyphs[]) const {
455dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy
456dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy    SkAutoGlyphCache autoCache(*this, NULL);
457dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy    SkGlyphCache* cache = autoCache.getCache();
458dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy
459dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy    const char* text = (const char*) textData;
460dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy    const char* stop = text + byteLength;
461dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy    uint16_t* gptr = glyphs;
462dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy
463dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy    switch (encoding) {
464dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy        case SkPaint::kUTF8_TextEncoding:
465dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            while (text < stop) {
466dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy                *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
467dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            }
468dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            break;
469dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy        case SkPaint::kUTF16_TextEncoding: {
470dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            const uint16_t* text16 = (const uint16_t*)text;
471dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            const uint16_t* stop16 = (const uint16_t*)stop;
472dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            while (text16 < stop16) {
473dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
474dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            }
475dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            break;
476dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy        }
477dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy        default:
478dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy            SkDEBUGFAIL("unknown text encoding");
479dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy    }
480dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy    return gptr - glyphs;
481dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy}
482dc7d4843a1b47c431ec5b358e8d9807e309a735eRomain Guy
48387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
48490a1efbdde19ee56c33929592277871509c25893Romain Guy
4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint SkPaint::textToGlyphs(const void* textData, size_t byteLength,
4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                          uint16_t glyphs[]) const {
4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (byteLength == 0) {
4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
49040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(textData != NULL);
4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == glyphs) {
4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        switch (this->getTextEncoding()) {
4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kUTF8_TextEncoding:
4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return SkUTF8_CountUnichars((const char*)textData, byteLength);
4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kUTF16_TextEncoding:
4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return SkUTF16_CountUnichars((const uint16_t*)textData,
4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                         byteLength >> 1);
5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kGlyphID_TextEncoding:
5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return byteLength >> 1;
5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
5031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown text encoding");
5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
50740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // if we get here, we have a valid glyphs[] array, so time to fill it in
50940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // handle this encoding before the setup for the glyphcache
5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // we want to ignore the low bit of byteLength
5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        memcpy(glyphs, textData, byteLength >> 1 << 1);
5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return byteLength >> 1;
5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
51640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache autoCache(*this, NULL);
5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*    cache = autoCache.getCache();
5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textData;
5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* stop = text + byteLength;
5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint16_t*   gptr = glyphs;
5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (this->getTextEncoding()) {
5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkPaint::kUTF8_TextEncoding:
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkPaint::kUTF16_TextEncoding: {
5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const uint16_t* text16 = (const uint16_t*)text;
5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const uint16_t* stop16 = (const uint16_t*)stop;
5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text16 < stop16) {
5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
5391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown text encoding");
5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return gptr - glyphs;
5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
54475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reedbool SkPaint::containsText(const void* textData, size_t byteLength) const {
54575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    if (0 == byteLength) {
54675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        return true;
54775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    }
54840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
54975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    SkASSERT(textData != NULL);
55040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
55175c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    // handle this encoding before the setup for the glyphcache
55275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
55375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
55475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        size_t count = byteLength >> 1;
55575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        for (size_t i = 0; i < count; i++) {
55675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            if (0 == glyphID[i]) {
55775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                return false;
55875c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            }
55975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        }
56075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        return true;
56175c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    }
56240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
56375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    SkAutoGlyphCache autoCache(*this, NULL);
56475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    SkGlyphCache*    cache = autoCache.getCache();
56575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed
56675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    switch (this->getTextEncoding()) {
56775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        case SkPaint::kUTF8_TextEncoding: {
56875c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            const char* text = static_cast<const char*>(textData);
56975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            const char* stop = text + byteLength;
57075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            while (text < stop) {
57175c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
57275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                    return false;
57375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                }
57475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            }
57575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            break;
57675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        }
57775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        case SkPaint::kUTF16_TextEncoding: {
57875c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            const uint16_t* text = static_cast<const uint16_t*>(textData);
57975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            const uint16_t* stop = text + (byteLength >> 1);
58075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            while (text < stop) {
58175c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
58275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                    return false;
58375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                }
58475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            }
58575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            break;
58675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        }
58775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        default:
5881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown text encoding");
58975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            return false;
59075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    }
59175c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    return true;
59275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed}
59375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed
594091f227385b467090b5a7169a8e2faf19eca7105Mike Reedvoid SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
595091f227385b467090b5a7169a8e2faf19eca7105Mike Reed                               SkUnichar textData[]) const {
596091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    if (count <= 0) {
597091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        return;
598091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    }
599091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
600091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkASSERT(glyphs != NULL);
601091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkASSERT(textData != NULL);
602091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
603091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkAutoGlyphCache autoCache(*this, NULL);
604091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkGlyphCache*    cache = autoCache.getCache();
605091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
606091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    for (int index = 0; index < count; index++) {
607091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        textData[index] = cache->glyphToUnichar(glyphs[index]);
608091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    }
609091f227385b467090b5a7169a8e2faf19eca7105Mike Reed}
610091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
6110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
6120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
61340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
61440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                              const char** text) {
6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
61740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
62140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
62240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                              const char** text) {
6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
62540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
62940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
63040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
63340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
63740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
63840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
64140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
64540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
64640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
64940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
6520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr += 1;
6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDMetrics(glyphID);
6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
65740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
65840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
66140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
6630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr -= 1;
6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
6650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
6660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDMetrics(glyphID);
6670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
66940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
67040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                              const char** text) {
6710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
67340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
6750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
67740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
67840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                              const char** text) {
6790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
68140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
6830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
68540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
68640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
68940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
6910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
69340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
69440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
69740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
6990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
70140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
70240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
7030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
70540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
7070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
7080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr += 1;
7090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
7100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDAdvance(glyphID);
7110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
71340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
71440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
7150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
71740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
7190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr -= 1;
7200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
7210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
7220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDAdvance(glyphID);
7230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
72640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                bool needFullMetrics) const {
7270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static const SkMeasureCacheProc gMeasureCacheProcs[] = {
7280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf8_next,
7290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf16_next,
7300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_glyph_next,
73140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf8_prev,
7330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf16_prev,
7340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_glyph_prev,
73540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_utf8_next,
7370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_utf16_next,
7380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_glyph_next,
73940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_utf8_prev,
7410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_utf16_prev,
7420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_glyph_prev
7430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
74440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned index = this->getTextEncoding();
7460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
74740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (kBackward_TextBufferDirection == tbd) {
7480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index += 3;
74940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
75040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (!needFullMetrics && !this->isDevKernText()) {
7510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index += 6;
75240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
7530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
7550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return gMeasureCacheProcs[index];
7560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
7590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
76140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                        const char** text, SkFixed, SkFixed) {
7620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
76440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
7660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
76940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                    const char** text, SkFixed x, SkFixed y) {
7700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
77240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
7740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
77640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
77740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                        const char** text, SkFixed, SkFixed) {
7780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
78040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
7820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
78540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                     const char** text, SkFixed x, SkFixed y) {
7860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
78840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
7900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    x, y);
7910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
79340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
79440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                         const char** text, SkFixed, SkFixed) {
7950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
79740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
7990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
8000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr += 1;
8010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
8020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDMetrics(glyphID);
8030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
80640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                     const char** text, SkFixed x, SkFixed y) {
8070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
8080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
80940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
8110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
8120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr += 1;
8130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
8140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDMetrics(glyphID, x, y);
8150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
81740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkDrawCacheProc SkPaint::getDrawCacheProc() const {
8180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static const SkDrawCacheProc gDrawCacheProcs[] = {
8190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf8_00,
8200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf16_00,
8210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_glyph_00,
82240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf8_xy,
8240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf16_xy,
8250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_glyph_xy
8260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
82740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned index = this->getTextEncoding();
82940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fFlags & kSubpixelText_Flag) {
8300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index += 3;
83140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
83240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
8340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return gDrawCacheProcs[index];
8350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
8380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkAutoRestorePaintTextSizeAndFrame {
8400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
84140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint)
84240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            : fPaint((SkPaint*)paint) {
8430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fTextSize = paint->getTextSize();
8440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fStyle = paint->getStyle();
8450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setStyle(SkPaint::kFill_Style);
8460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
84740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
84840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    ~SkAutoRestorePaintTextSizeAndFrame() {
8490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setStyle(fStyle);
8500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setTextSize(fTextSize);
8510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
85240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
8540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint*        fPaint;
8550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        fTextSize;
8560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint::Style  fStyle;
8570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
8580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
85940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void set_bounds(const SkGlyph& g, SkRect* bounds) {
8600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->set(SkIntToScalar(g.fLeft),
8610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkIntToScalar(g.fTop),
8620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkIntToScalar(g.fLeft + g.fWidth),
8630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkIntToScalar(g.fTop + g.fHeight));
8640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
866e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed// 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
867e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed// we don't overflow along the way
868e63c5c9f6752244ca0f39075fa148a0281593831Mike Reedtypedef int64_t Sk48Dot16;
869e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed
870e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed#ifdef SK_SCALAR_IS_FLOAT
871e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
87240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return (float) (x * 1.5258789e-5);   // x * (1 / 65536.0f)
873e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    }
874e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed#else
875e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    static inline SkFixed Sk48Dot16ToScalar(Sk48Dot16 x) {
876e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed        // just return the low 32bits
877e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed        return static_cast<SkFixed>(x);
878e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    }
879e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed#endif
880e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed
8811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
882e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    SkScalar sx = Sk48Dot16ToScalar(dx);
8830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->join(SkIntToScalar(g.fLeft) + sx,
8840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                 SkIntToScalar(g.fTop),
8850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                 SkIntToScalar(g.fLeft + g.fWidth) + sx,
8860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                 SkIntToScalar(g.fTop + g.fHeight));
8870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
8901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar sy = Sk48Dot16ToScalar(dy);
8911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bounds->join(SkIntToScalar(g.fLeft),
8921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkIntToScalar(g.fTop) + sy,
8931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkIntToScalar(g.fLeft + g.fWidth),
8941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkIntToScalar(g.fTop + g.fHeight) + sy);
8951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
8961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
8981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
9001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkFixed advance(const SkGlyph& glyph, int xyIndex) {
9011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(0 == xyIndex || 1 == xyIndex);
9021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return (&glyph.fAdvanceX)[xyIndex];
9031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
9041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPaint::measure_text(SkGlyphCache* cache,
9060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                               const char* text, size_t byteLength,
90740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                               int* count, SkRect* bounds) const {
9080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(count);
90940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (byteLength == 0) {
9100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *count = 0;
91140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (bounds) {
9120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            bounds->setEmpty();
91340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
9140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
9150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMeasureCacheProc glyphCacheProc;
9180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
9190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                               NULL != bounds);
9200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int xyIndex;
9221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    JoinBoundsProc joinBoundsProc;
9231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (this->isVerticalText()) {
9241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        xyIndex = 1;
9251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        joinBoundsProc = join_bounds_y;
9261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
9271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        xyIndex = 0;
9281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        joinBoundsProc = join_bounds_x;
9291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
9301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
9310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int         n = 1;
9320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* stop = (const char*)text + byteLength;
9330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkGlyph* g = &glyphCacheProc(cache, &text);
934e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    // our accumulated fixed-point advances might overflow 16.16, so we use
935e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    // a 48.16 (64bit) accumulator, and then convert that to scalar at the
936e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    // very end.
9371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Sk48Dot16 x = advance(*g, xyIndex);
9380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoKern  autokern;
9400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
94140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == bounds) {
94240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->isDevKernText()) {
9430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int rsb;
9440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (; text < stop; n++) {
9450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rsb = g->fRsbDelta;
9460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                g = &glyphCacheProc(cache, &text);
9471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
9480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
94940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
9500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (; text < stop; n++) {
9511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += advance(glyphCacheProc(cache, &text), xyIndex);
9520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
9530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
95440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
9550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        set_bounds(*g, bounds);
95640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->isDevKernText()) {
9570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int rsb;
9580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (; text < stop; n++) {
9590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rsb = g->fRsbDelta;
9600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                g = &glyphCacheProc(cache, &text);
9610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
9621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                joinBoundsProc(*g, bounds, x);
9631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += advance(*g, xyIndex);
9640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
96540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
9660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (; text < stop; n++) {
9670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                g = &glyphCacheProc(cache, &text);
9681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                joinBoundsProc(*g, bounds, x);
9691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += advance(*g, xyIndex);
9700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
9710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
9720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text == stop);
9740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *count = n;
976e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    return Sk48Dot16ToScalar(x);
9770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPaint::measureText(const void* textData, size_t length,
98040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                              SkRect* bounds, SkScalar zoom) const {
9810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textData;
9820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL || length == 0);
9830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                            scale = 0;
9850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoRestorePaintTextSizeAndFrame  restore(this);
9860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
98740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isLinearText()) {
9880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scale = fTextSize / kCanonicalTextSizeForPaths;
9890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this gets restored by restore
9900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
9910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
99240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
99340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkMatrix zoomMatrix, *zoomPtr = NULL;
99440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (zoom) {
9950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        zoomMatrix.setScale(zoom, zoom);
9960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        zoomPtr = &zoomMatrix;
9970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache    autoCache(*this, zoomPtr);
10000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*       cache = autoCache.getCache();
10010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar width = 0;
100340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
100440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (length > 0) {
10050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int tempCount;
10060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        width = this->measure_text(cache, text, length, &tempCount, bounds);
100840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (scale) {
10090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = SkScalarMul(width, scale);
101040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (bounds) {
10110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
10120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bounds->fTop = SkScalarMul(bounds->fTop, scale);
10130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bounds->fRight = SkScalarMul(bounds->fRight, scale);
10140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
10150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
10160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
10170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return width;
10190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecttypedef bool (*SkTextBufferPred)(const char* text, const char* stop);
10220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
102340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic bool forward_textBufferPred(const char* text, const char* stop) {
10240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return text < stop;
10250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
102740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic bool backward_textBufferPred(const char* text, const char* stop) {
10280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return text > stop;
10290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
103240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                             const char** text, size_t length,
103340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                             const char** stop) {
103440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (SkPaint::kForward_TextBufferDirection == tbd) {
10350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *stop = *text + length;
10360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return forward_textBufferPred;
103740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
10380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // text should point to the end of the buffer, and stop to the beginning
10390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *stop = *text;
10400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *text += length;
10410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return backward_textBufferPred;
10420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectsize_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
10460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                          SkScalar* measuredWidth,
104740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                          TextBufferDirection tbd) const {
104840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (0 == length || 0 >= maxWidth) {
104940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (measuredWidth) {
10500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *measuredWidth = 0;
105140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
10520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
10530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == fTextSize) {
10561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (measuredWidth) {
10571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            *measuredWidth = 0;
10581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
10591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return length;
10601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
10611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(textD != NULL);
10630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textD;
10640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                            scale = 0;
10660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoRestorePaintTextSizeAndFrame  restore(this);
10670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
106840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isLinearText()) {
10690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scale = fTextSize / kCanonicalTextSizeForPaths;
10709b1cba8ccd7554cb30905711a426bd86ad8dd38cJean-Baptiste Queru        maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize);
10710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this gets restored by restore
10720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
10730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
107440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
10750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache    autoCache(*this, NULL);
10760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*       cache = autoCache.getCache();
10770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
10790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char*      stop;
10800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
10811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int        xyIndex = this->isVerticalText() ? 1 : 0;
1082e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    // use 64bits for our accumulator, to avoid overflowing 16.16
1083e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    Sk48Dot16        max = SkScalarToFixed(maxWidth);
1084e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    Sk48Dot16        width = 0;
10850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoKern  autokern;
10870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
108840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isDevKernText()) {
10890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int rsb = 0;
109040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        while (pred(text, stop)) {
10910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const char* curr = text;
10920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const SkGlyph& g = glyphCacheProc(cache, &text);
10931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
109440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if ((width += x) > max) {
10950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                width -= x;
10960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                text = curr;
10970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
10980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
10990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            rsb = g.fRsbDelta;
11000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
110140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
110240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        while (pred(text, stop)) {
11030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const char* curr = text;
11041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
110540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if ((width += x) > max) {
11060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                width -= x;
11070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                text = curr;
11080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
11090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
11100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
11110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
111240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
111340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (measuredWidth) {
1114e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed        SkScalar scalarWidth = Sk48Dot16ToScalar(width);
111540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (scale) {
11160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            scalarWidth = SkScalarMul(scalarWidth, scale);
111740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
11180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *measuredWidth = scalarWidth;
11190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
112040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // return the number of bytes measured
11220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (kForward_TextBufferDirection == tbd) ?
11230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                text - stop + length : stop - text + length;
11240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
11270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
112840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
11290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
11300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;   // don't detach the cache
11310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
113340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void FontMetricsDescProc(const SkDescriptor* desc, void* context) {
11340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
11350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
113740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
11380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                            scale = 0;
11390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoRestorePaintTextSizeAndFrame  restore(this);
11400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
114140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isLinearText()) {
11420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scale = fTextSize / kCanonicalTextSizeForPaths;
11430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this gets restored by restore
11440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
11450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
114640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
114740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkMatrix zoomMatrix, *zoomPtr = NULL;
114840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (zoom) {
11490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        zoomMatrix.setScale(zoom, zoom);
11500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        zoomPtr = &zoomMatrix;
11510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0
11540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache    autoCache(*this, zoomPtr);
11550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*       cache = autoCache.getCache();
11560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const FontMetrics&  my = cache->getFontMetricsY();
11570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
11580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    FontMetrics storage;
115940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == metrics) {
11600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics = &storage;
116140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
116240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics, true);
11640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
116540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (scale) {
11660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fTop = SkScalarMul(metrics->fTop, scale);
11670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
11680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
11690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
11700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
11710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return metrics->fDescent - metrics->fAscent + metrics->fLeading;
11730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
117540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
11760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
117740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
11780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->set(g.fLeft * scale,
11790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                g.fTop * scale,
11800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                (g.fLeft + g.fWidth) * scale,
11810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                (g.fTop + g.fHeight) * scale);
11820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
118440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerint SkPaint::getTextWidths(const void* textData, size_t byteLength,
118540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                           SkScalar widths[], SkRect bounds[]) const {
118640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (0 == byteLength) {
11870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
118840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
11890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(NULL != textData);
11910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
119240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == widths && NULL == bounds) {
11930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->countText(textData, byteLength);
119440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
11950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoRestorePaintTextSizeAndFrame  restore(this);
11970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                            scale = 0;
11980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
119940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isLinearText()) {
12000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scale = fTextSize / kCanonicalTextSizeForPaths;
12010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this gets restored by restore
12020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
12030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache    autoCache(*this, NULL);
12060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*       cache = autoCache.getCache();
12070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMeasureCacheProc  glyphCacheProc;
12080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
12090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                               NULL != bounds);
12100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textData;
12120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* stop = text + byteLength;
12130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int         count = 0;
12141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int   xyIndex = this->isVerticalText() ? 1 : 0;
12150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
121640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isDevKernText()) {
12170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // we adjust the widths returned here through auto-kerning
12180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkAutoKern  autokern;
12190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkFixed     prevWidth = 0;
12200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (scale) {
12220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
12230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkGlyph& g = glyphCacheProc(cache, &text);
12240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (widths) {
12250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkFixed  adjust = autokern.adjust(g);
12260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    if (count > 0) {
12280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        SkScalar w = SkFixedToScalar(prevWidth + adjust);
12290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        *widths++ = SkScalarMul(w, scale);
12300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    }
12311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    prevWidth = advance(g, xyIndex);
12320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bounds) {
12340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    set_bounds(g, bounds++, scale);
12350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++count;
12370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (count > 0 && widths) {
12390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
12400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
12420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
12430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkGlyph& g = glyphCacheProc(cache, &text);
12440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (widths) {
12450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkFixed  adjust = autokern.adjust(g);
12460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    if (count > 0) {
12480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        *widths++ = SkFixedToScalar(prevWidth + adjust);
12490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    }
12501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    prevWidth = advance(g, xyIndex);
12510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bounds) {
12530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    set_bounds(g, bounds++);
12540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++count;
12560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (count > 0 && widths) {
12580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *widths = SkFixedToScalar(prevWidth);
12590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {    // no devkern
12620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (scale) {
12630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
12640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkGlyph& g = glyphCacheProc(cache, &text);
12650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (widths) {
12661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
12670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                            scale);
12680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bounds) {
12700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    set_bounds(g, bounds++, scale);
12710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++count;
12730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
12750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
12760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkGlyph& g = glyphCacheProc(cache, &text);
12770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (widths) {
12781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    *widths++ = SkFixedToScalar(advance(g, xyIndex));
12790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bounds) {
12810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    set_bounds(g, bounds++);
12820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++count;
12840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text == stop);
12890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return count;
12900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
129240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
12930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDraw.h"
12950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
129640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkPaint::getTextPath(const void* textData, size_t length,
129740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                          SkScalar x, SkScalar y, SkPath* path) const {
129840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(length == 0 || textData != NULL);
129940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
13000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textData;
130140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (text == NULL || length == 0 || path == NULL) {
13020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
130340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
13040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTextToPathIter    iter(text, length, *this, false, true);
13060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMatrix            matrix;
13070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar            prevXPos = 0;
13080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    matrix.setScale(iter.getPathScale(), iter.getPathScale());
13100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    matrix.postTranslate(x, y);
13110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    path->reset();
13120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        xpos;
13140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkPath*   iterPath;
131540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    while ((iterPath = iter.next(&xpos)) != NULL) {
13160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        matrix.postTranslate(xpos - prevXPos, 0);
13170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        path->addPath(*iterPath, matrix);
13180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        prevXPos = xpos;
13190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
13200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
13210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void add_flattenable(SkDescriptor* desc, uint32_t tag,
13230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                            SkFlattenableWriteBuffer* buffer) {
13240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
13250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
13260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// SkFontHost can override this choice in FilterRec()
132840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkMask::Format computeMaskFormat(const SkPaint& paint) {
13290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t flags = paint.getFlags();
13300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1331c49fcf5e8bc1c84bcb0a51fe615caa7e72dd7dccMike Reed    // Antialiasing being disabled trumps all other settings.
1332137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    if (!(flags & SkPaint::kAntiAlias_Flag)) {
1333c49fcf5e8bc1c84bcb0a51fe615caa7e72dd7dccMike Reed        return SkMask::kBW_Format;
133405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
133505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1336137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    if (flags & SkPaint::kLCDRenderText_Flag) {
1337137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        return SkMask::kLCD16_Format;
1338137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    }
1339c49fcf5e8bc1c84bcb0a51fe615caa7e72dd7dccMike Reed
1340c49fcf5e8bc1c84bcb0a51fe615caa7e72dd7dccMike Reed    return SkMask::kA8_Format;
13410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
13420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13434bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed// if linear-text is on, then we force hinting to be off (since that's sort of
13444bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed// the point of linear-text.
13454bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reedstatic SkPaint::Hinting computeHinting(const SkPaint& paint) {
13464bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed    SkPaint::Hinting h = paint.getHinting();
13474bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed    if (paint.isLinearText()) {
13484bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed        h = SkPaint::kNo_Hinting;
13494bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed    }
13504bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed    return h;
13514bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed}
13524bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed
13531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// return true if the paint is just a single color (i.e. not a shader). If its
13541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// a shader, then we can't compute a const luminance for it :(
13551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool justAColor(const SkPaint& paint, SkColor* color) {
13561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (paint.getShader()) {
13571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
13581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkColor c = paint.getColor();
13601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (paint.getColorFilter()) {
13611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        c = paint.getColorFilter()->filterColor(c);
13621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (color) {
13641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *color = c;
13651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
13671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
13681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
13704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic SkColor computeLuminanceColor(const SkPaint& paint) {
13714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkColor c;
13724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (!justAColor(paint, &c)) {
13734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        c = SkColorSetRGB(0x7F, 0x80, 0x7F);
13744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
13754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return c;
13764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
13774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
13784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
13794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
13804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic U8CPU reduce_lumbits(U8CPU x) {
13814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    static const uint8_t gReduceBits[] = {
13824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        0x0, 0x55, 0xAA, 0xFF
13834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    };
13844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    assert_byte(x);
13854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return gReduceBits[x >> 6];
13864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
13874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
13884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic unsigned computeLuminance(SkColor c) {
13894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int r = SkColorGetR(c);
13904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int g = SkColorGetG(c);
13914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int b = SkColorGetB(c);
13924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // compute luminance
13934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // R=0.2126 G=0.7152 B=0.0722
13944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // scaling by 127 yields 27, 92, 9
13954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int luminance = r * 27 + g * 92 + b * 9;
13964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    luminance >>= 7;
13974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    assert_byte(luminance);
13984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return luminance;
13994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
14004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
14014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
14021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// returns 0..kLuminance_Max
14031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic unsigned computeLuminance(const SkPaint& paint) {
14041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkColor c;
14051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (justAColor(paint, &c)) {
14061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int r = SkColorGetR(c);
14071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int g = SkColorGetG(c);
14081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int b = SkColorGetB(c);
14091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // compute luminance
14101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // R=0.2126 G=0.7152 B=0.0722
14111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // scaling by 127 yields 27, 92, 9
14121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if 1
14131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int luminance = r * 27 + g * 92 + b * 9;
14141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        luminance >>= 15 - SkScalerContext::kLuminance_Bits;
14151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
14161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int luminance = r * 2 + g * 5 + b * 1;
14171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        luminance >>= 11 - SkScalerContext::kLuminance_Bits;
14181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
14191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkASSERT(luminance <= SkScalerContext::kLuminance_Max);
14201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return luminance;
14211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
14221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // if we're not a single color, return the middle of the luminance range
14231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkScalerContext::kLuminance_Max >> 1;
14241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
14254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
14261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// Beyond this size, LCD doesn't appreciably improve quality, but it always
14281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// cost more RAM and draws slower, so we set a cap.
14291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifndef SK_MAX_SIZE_FOR_LCDTEXT
14301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #define SK_MAX_SIZE_FOR_LCDTEXT    48
14311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
14321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool tooBigForLCD(const SkScalerContext::Rec& rec) {
14341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar area = SkScalarMul(rec.fPost2x2[0][0], rec.fPost2x2[1][1]) -
14351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    SkScalarMul(rec.fPost2x2[1][0], rec.fPost2x2[0][1]);
14361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar size = SkScalarMul(area, rec.fTextSize);
14371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkScalarAbs(size) > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
14381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
14391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
144040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/*
144140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger *  Return the scalar with only limited fractional precision. Used to consolidate matrices
144240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger *  that vary only slightly when we create our key into the font cache, since the font scaler
144340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger *  typically returns the same looking resuts for tiny changes in the matrix.
144440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */
144540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkScalar sk_relax(SkScalar x) {
144640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#ifdef SK_SCALAR_IS_FLOAT
144740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int n = sk_float_round2int(x * 1024);
144840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return n / 1024.0f;
144940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#else
145040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // round to the nearest 10 fractional bits
145140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return (x + (1 << 5)) & ~(1024 - 1);
145240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif
145340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
145440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1455af2616552738d653d5453915d3236e7154b868cdMike Reedvoid SkScalerContext::MakeRec(const SkPaint& paint,
145640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                              const SkMatrix* deviceMatrix, Rec* rec) {
14570199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger    SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
14580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
145979bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    SkTypeface* typeface = paint.getTypeface();
146079bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    rec->fOrigFontID = SkTypeface::UniqueID(typeface);
14610199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger    rec->fFontID = rec->fOrigFontID;
14620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec->fTextSize = paint.getTextSize();
14630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec->fPreScaleX = paint.getTextScaleX();
14640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec->fPreSkewX  = paint.getTextSkewX();
14650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
146640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (deviceMatrix) {
146740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
146840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
146940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
147040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
147140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
14720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
14730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
14740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
147540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint::Style  style = paint.getStyle();
14770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        strokeWidth = paint.getStrokeWidth();
147840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    unsigned flags = 0;
14801c980e0d7772f05f570ae0227d91635f017c2227Mike Reed
14811c980e0d7772f05f570ae0227d91635f017c2227Mike Reed#ifdef SK_USE_FREETYPE_EMBOLDEN
148279bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // It is possible that the SkTypeface used to draw glyphs has
148379bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // different properties than the SkTypeface set in the SkPaint.
148479bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // If we are asked to render bold text with a bold font, and are
148579bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // forced to fall back to a font with normal weight for some
148679bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // glyphs, we need to use fake bold to render those glyphs. In
148779bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // order to do that, we set SkScalerContext's "embolden" flag
148879bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // here if we are trying to draw bold text via any means, and
148979bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // ignore it at the glyph outline generation stage if the font
149079bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    // actually being used is already bold.
149179bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    if (paint.isFakeBoldText() || (typeface && typeface->isBold())) {
14921c980e0d7772f05f570ae0227d91635f017c2227Mike Reed        flags |= SkScalerContext::kEmbolden_Flag;
149379bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    }
14941c980e0d7772f05f570ae0227d91635f017c2227Mike Reed#else
149579bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease    if (paint.isFakeBoldText()) {
149640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
149740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                    kStdFakeBoldInterpKeys,
149840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                    kStdFakeBoldInterpValues,
149940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                    kStdFakeBoldInterpLength);
15000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
150140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
150240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (style == SkPaint::kFill_Style) {
15030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            style = SkPaint::kStrokeAndFill_Style;
15040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
150540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
15060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            strokeWidth += extra;
150740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
15080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
150979bf51281ffa537ddfbb54dededdad5aa9e466e8Victoria Lease#endif
15100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
151140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isDevKernText()) {
15120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        flags |= SkScalerContext::kDevKernText_Flag;
151340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
151440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
151540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (style != SkPaint::kFill_Style && strokeWidth > 0) {
15160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fFrameWidth = strokeWidth;
15170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fMiterLimit = paint.getStrokeMiter();
15180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
15190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
152040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (style == SkPaint::kStrokeAndFill_Style) {
15210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            flags |= SkScalerContext::kFrameAndFill_Flag;
152240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
152340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
15240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fFrameWidth = 0;
15250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fMiterLimit = 0;
15260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fStrokeJoin = 0;
15270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
15280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
15300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
15311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkMask::kLCD16_Format == rec->fMaskFormat ||
15321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkMask::kLCD32_Format == rec->fMaskFormat)
15331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    {
15340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder();
15350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        SkFontHost::LCDOrientation orient = SkFontHost::GetSubpixelOrientation();
15361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (SkFontHost::kNONE_LCDOrder == order || tooBigForLCD(*rec)) {
15370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            // eeek, can't support LCD
15380b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            rec->fMaskFormat = SkMask::kA8_Format;
15390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        } else {
15400b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            if (SkFontHost::kVertical_LCDOrientation == orient) {
15410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                flags |= SkScalerContext::kLCD_Vertical_Flag;
15420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            }
15430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            if (SkFontHost::kBGR_LCDOrder == order) {
15440b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                flags |= SkScalerContext::kLCD_BGROrder_Flag;
15450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            }
15460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        }
15470b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
15480b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
154940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isEmbeddedBitmapText()) {
15500b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
155140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
155240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isSubpixelText()) {
15530b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        flags |= SkScalerContext::kSubpixelPositioning_Flag;
155440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
155540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isAutohinted()) {
15560b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        flags |= SkScalerContext::kAutohinting_Flag;
155740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
15581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (paint.isVerticalText()) {
15591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        flags |= SkScalerContext::kVertical_Flag;
15601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
15614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
15624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        flags |= SkScalerContext::kGenA8FromLCD_Flag;
15634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
15640b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    rec->fFlags = SkToU16(flags);
15650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
15661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // these modify fFlags, so do them after assigning fFlags
15670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    rec->setHinting(computeHinting(paint));
15684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
15694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    rec->setLuminanceColor(computeLuminanceColor(paint));
15704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
15711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    rec->setLuminanceBits(computeLuminance(paint));
15724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
1573212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett#ifdef SK_BUILD_FOR_ANDROID
1574725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    rec->fLanguage = paint.getLanguage();
1575212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett    rec->fFontVariant = paint.getFontVariant();
1576212ef7a5d592a11522f73d858bf98f5201631b70Billy Hewlett#endif //SK_BUILD_FOR_ANDROID
1577af2616552738d653d5453915d3236e7154b868cdMike Reed
1578af2616552738d653d5453915d3236e7154b868cdMike Reed    /*  Allow the fonthost to modify our rec before we use it as a key into the
1579af2616552738d653d5453915d3236e7154b868cdMike Reed        cache. This way if we're asking for something that they will ignore,
1580af2616552738d653d5453915d3236e7154b868cdMike Reed        they can modify our rec up front, so we don't create duplicate cache
1581af2616552738d653d5453915d3236e7154b868cdMike Reed        entries.
1582af2616552738d653d5453915d3236e7154b868cdMike Reed     */
1583af2616552738d653d5453915d3236e7154b868cdMike Reed    SkFontHost::FilterRec(rec);
15841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // be sure to call PostMakeRec(rec) before you actually use it!
15864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
15874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
15884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/**
15894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger *  We ensure that the rec is self-consistent and efficient (where possible)
15904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */
15914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkScalerContext::PostMakeRec(SkScalerContext::Rec* rec) {
15924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
15934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    /**
15944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger     *  If we're asking for A8, we force the colorlum to be gray, since that
15954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger     *  that limits the number of unique entries, and the scaler will only
15964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger     *  look at the lum of one of them.
15974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger     */
15984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    switch (rec->fMaskFormat) {
15994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkMask::kLCD16_Format:
16004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkMask::kLCD32_Format: {
16014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
16024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // filter down the luminance color to a finite number of bits
16034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkColor c = rec->getLuminanceColor();
16044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            c = SkColorSetRGB(reduce_lumbits(SkColorGetR(c)),
16054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              reduce_lumbits(SkColorGetG(c)),
16064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              reduce_lumbits(SkColorGetB(c)));
16074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            rec->setLuminanceColor(c);
16084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
16094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
16104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
16114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkMask::kA8_Format: {
16124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
16134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // filter down the luminance to a single component, since A8 can't
16144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // use per-component information
16154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            unsigned lum = computeLuminance(rec->getLuminanceColor());
16164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // reduce to our finite number of bits
16174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            lum = reduce_lumbits(lum);
16184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            rec->setLuminanceColor(SkColorSetRGB(lum, lum, lum));
16194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
16204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
16214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
16224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkMask::kBW_Format:
16234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // No need to differentiate gamma if we're BW
16244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
16254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            rec->setLuminanceColor(0);
16264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
16274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            rec->setLuminanceBits(0);
16284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
16294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
16301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
16310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
16320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define MIN_SIZE_FOR_EFFECT_BUFFER  1024
16340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
163535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#ifdef SK_DEBUG
163635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    #define TEST_DESC
163735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#endif
163835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
16391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
16401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  ignoreGamma tells us that the caller just wants metrics that are unaffected
16411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  by gamma correction, so we jam the luminance field to 0 (most common value
16421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  for black text) in hopes that we get a cache hit easier. A better solution
16431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  would be for the fontcache lookup to know to ignore the luminance field
16441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  entirely, but not sure how to do that and keep it fast.
16451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
16460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
16470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                             void (*proc)(const SkDescriptor*, void*),
164840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                             void* context, bool ignoreGamma) const {
16490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalerContext::Rec    rec;
16500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
1652fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    if (ignoreGamma) {
16534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
16544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        rec.setLuminanceColor(0);
16554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
16561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rec.setLuminanceBits(0);
16574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
1658fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    }
16590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t          descSize = sizeof(rec);
16610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int             entryCount = 1;
16620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPathEffect*   pe = this->getPathEffect();
16630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMaskFilter*   mf = this->getMaskFilter();
16640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRasterizer*   ra = this->getRasterizer();
16650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFlattenableWriteBuffer    peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
16670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFlattenableWriteBuffer    mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
16680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFlattenableWriteBuffer    raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
16690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (pe) {
16710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        peBuffer.writeFlattenable(pe);
16720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        descSize += peBuffer.size();
16730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        entryCount += 1;
16740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
16750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // seems like we could support kLCD as well at this point...
16760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (mf) {
16780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        mfBuffer.writeFlattenable(mf);
16790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        descSize += mfBuffer.size();
16800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        entryCount += 1;
16810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
16820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (ra) {
16840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        raBuffer.writeFlattenable(ra);
16850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        descSize += raBuffer.size();
16860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        entryCount += 1;
16870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
16880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    ///////////////////////////////////////////////////////////////////////////
16914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // Now that we're done tweaking the rec, call the PostMakeRec cleanup
16924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkScalerContext::PostMakeRec(&rec);
16934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    descSize += SkDescriptor::ComputeOverhead(entryCount);
16950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoDescriptor    ad(descSize);
16970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDescriptor*       desc = ad.getDesc();
16980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    desc->init();
17000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
17010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
17020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (pe) {
17030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
17040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
17050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (mf) {
17060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
17070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
17080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (ra) {
17090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
17100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
17110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
17120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(descSize == desc->getLength());
17130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    desc->computeChecksum();
17140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
171535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#ifdef TEST_DESC
171635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    {
171735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // Check that we completely write the bytes in desc (our key), and that
171835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // there are no uninitialized bytes. If there were, then we would get
171935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // false-misses (or worse, false-hits) in our fontcache.
172035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        //
172135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // We do this buy filling 2 others, one with 0s and the other with 1s
172235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // and create those, and then check that all 3 are identical.
172335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkAutoDescriptor    ad1(descSize);
172435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkAutoDescriptor    ad2(descSize);
172535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkDescriptor*       desc1 = ad1.getDesc();
172635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkDescriptor*       desc2 = ad2.getDesc();
172735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
172835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        memset(desc1, 0x00, descSize);
172935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        memset(desc2, 0xFF, descSize);
173035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
173135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc1->init();
173235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc2->init();
173335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
173435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
173535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
173635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (pe) {
173735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
173835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
173935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
174035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (mf) {
174135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
174235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
174335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
174435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (ra) {
174535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
174635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
174735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
174835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
174935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkASSERT(descSize == desc1->getLength());
175035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkASSERT(descSize == desc2->getLength());
175135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc1->computeChecksum();
175235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc2->computeChecksum();
175335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkASSERT(!memcmp(desc, desc1, descSize));
175435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkASSERT(!memcmp(desc, desc2, descSize));
175535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
175635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#endif
175735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
17580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    proc(desc, context);
17590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
17600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
176140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const {
17620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache* cache;
17630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
17640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache;
17650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
17660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
17670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
17680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
17690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStream.h"
17700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
17715f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic uintptr_t asint(const void* p) {
17725f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    return reinterpret_cast<uintptr_t>(p);
17735f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed}
17745f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17755f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedunion Scalar32 {
17765f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkScalar    fScalar;
17775f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint32_t    f32;
17785f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed};
17795f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17805f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
17815f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
17825f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    Scalar32 tmp;
17835f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    tmp.fScalar = value;
17845f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    *ptr = tmp.f32;
17855f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    return ptr + 1;
17865f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed}
17875f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17885f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic SkScalar read_scalar(const uint32_t*& ptr) {
17895f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
17905f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    Scalar32 tmp;
17915f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    tmp.f32 = *ptr++;
17925f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    return tmp.fScalar;
17935f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed}
17945f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17955f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
17965f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(a == (uint8_t)a);
17975f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(b == (uint8_t)b);
17985f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(c == (uint8_t)c);
17995f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(d == (uint8_t)d);
18005f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    return (a << 24) | (b << 16) | (c << 8) | d;
18015f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed}
18025f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18035f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedenum FlatFlags {
18045f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    kHasTypeface_FlatFlag   = 0x01,
18055f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    kHasEffects_FlatFlag    = 0x02
18065f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed};
18075f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18085f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed// The size of a flat paint's POD fields
18095f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
18105f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed                                        1 * sizeof(SkColor) +
18115f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed                                        1 * sizeof(uint16_t) +
18125f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed                                        6 * sizeof(uint8_t);
18135f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18145f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed/*  To save space/time, we analyze the paint, and write a truncated version of
18155f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    it if there are not tricky elements like shaders, etc.
18165f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed */
18170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
18185f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint8_t flatFlags = 0;
18195f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (this->getTypeface()) {
18205f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        flatFlags |= kHasTypeface_FlatFlag;
18215f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
18225f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (asint(this->getPathEffect()) |
18235f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getShader()) |
18245f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getXfermode()) |
18255f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getMaskFilter()) |
18265f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getColorFilter()) |
18275f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getRasterizer()) |
18281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        asint(this->getLooper()) |
18291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        asint(this->getImageFilter())) {
18305f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        flatFlags |= kHasEffects_FlatFlag;
18315f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
183240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
18335f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
18345f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint32_t* ptr = buffer.reserve(kPODPaintSize);
18355f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18365f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getTextSize());
18375f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getTextScaleX());
18385f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getTextSkewX());
18395f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getStrokeWidth());
18405f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getStrokeMiter());
18415f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    *ptr++ = this->getColor();
18421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // previously flags:16, textAlign:8, flatFlags:8
18431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // now flags:16, hinting:4, textAlign:4, flatFlags:8
18441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *ptr++ = (this->getFlags() << 16) |
18451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             // hinting added later. 0 in this nibble means use the default.
18461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             ((this->getHinting()+1) << 12) |
18471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             (this->getTextAlign() << 8) |
18481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             flatFlags;
18495f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
18505f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed                    this->getStyle(), this->getTextEncoding());
18515f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
1852725b3e03acb91dc69296554932624b36612bd189Billy Hewlett#ifdef SK_BUILD_FOR_ANDROID
1853725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    buffer.writeInt(this->getFontVariant());
1854725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    const SkString& langTag = this->getLanguage().getTag();
1855725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    buffer.writeString(langTag.c_str(), langTag.size());
1856725b3e03acb91dc69296554932624b36612bd189Billy Hewlett#endif
1857725b3e03acb91dc69296554932624b36612bd189Billy Hewlett
18585f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    // now we're done with ptr and the (pre)reserved space. If we need to write
18595f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    // additional fields, use the buffer directly
18605f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (flatFlags & kHasTypeface_FlatFlag) {
18615f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeTypeface(this->getTypeface());
18625f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
18635f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (flatFlags & kHasEffects_FlatFlag) {
18645f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getPathEffect());
18655f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getShader());
18665f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getXfermode());
18675f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getMaskFilter());
18685f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getColorFilter());
18695f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getRasterizer());
18705f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getLooper());
18711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        buffer.writeFlattenable(this->getImageFilter());
18725f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
18730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
18740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
18750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
18765f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
18775f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    const void* podData = buffer.skip(kPODPaintSize);
18785f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
187940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
18805f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    // the order we read must match the order we wrote in flatten()
18815f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setTextSize(read_scalar(pod));
18825f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setTextScaleX(read_scalar(pod));
18835f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setTextSkewX(read_scalar(pod));
18845f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setStrokeWidth(read_scalar(pod));
188540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    this->setStrokeMiter(read_scalar(pod));
18865f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setColor(*pod++);
18875f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // previously flags:16, textAlign:8, flatFlags:8
18891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // now flags:16, hinting:4, textAlign:4, flatFlags:8
18905f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint32_t tmp = *pod++;
18915f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setFlags(tmp >> 16);
18921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (buffer.getPictureVersion() == PICTURE_VERSION_ICS) {
18944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
18954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        this->setHinting(SkPaintDefaults_Hinting);
18964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    } else {
18974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // hinting added later. 0 in this nibble means use the default.
18984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        uint32_t hinting = (tmp >> 12) & 0xF;
18994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        this->setHinting(0 == hinting ? kNormal_Hinting : static_cast<Hinting>(hinting-1));
19001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
19014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
19024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
19031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
19045f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint8_t flatFlags = tmp & 0xFF;
19055f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
19065f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    tmp = *pod++;
19075f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
19085f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
19095f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
19105f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
19115f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
1912725b3e03acb91dc69296554932624b36612bd189Billy Hewlett#ifdef SK_BUILD_FOR_ANDROID
1913725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    this->setFontVariant(SkPaint::FontVariant(buffer.readInt()));
1914725b3e03acb91dc69296554932624b36612bd189Billy Hewlett    this->setLanguage(SkLanguage(buffer.readString()));
1915725b3e03acb91dc69296554932624b36612bd189Billy Hewlett#endif
1916725b3e03acb91dc69296554932624b36612bd189Billy Hewlett
19175f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (flatFlags & kHasTypeface_FlatFlag) {
19185f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setTypeface(buffer.readTypeface());
19195f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    } else {
19205f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setTypeface(NULL);
19215f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
19225f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
19235f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (flatFlags & kHasEffects_FlatFlag) {
192440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setPathEffect((SkPathEffect*) buffer.readFlattenable()));
192540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setShader((SkShader*) buffer.readFlattenable()));
192640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setXfermode((SkXfermode*) buffer.readFlattenable()));
192740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable()));
192840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setColorFilter((SkColorFilter*) buffer.readFlattenable()));
192940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setRasterizer((SkRasterizer*) buffer.readFlattenable()));
193040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setLooper((SkDrawLooper*) buffer.readFlattenable()));
19314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (buffer.getPictureVersion() != PICTURE_VERSION_ICS)
19324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkSafeUnref(this->setImageFilter((SkImageFilter*) buffer.readFlattenable()));
19334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        else
19344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            this->setImageFilter(NULL);
19355f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    } else {
19365f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setPathEffect(NULL);
19375f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setShader(NULL);
19385f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setXfermode(NULL);
19395f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setMaskFilter(NULL);
19405f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setColorFilter(NULL);
19415f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setRasterizer(NULL);
19425f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setLooper(NULL);
19431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        this->setImageFilter(NULL);
19445f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
19450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
19470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
19480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
194987b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkShader* SkPaint::setShader(SkShader* shader) {
195087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(shader != fShader);
19510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fShader, shader);
19520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return shader;
19530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
195587b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
195687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(filter != fColorFilter);
19570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fColorFilter, filter);
19580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return filter;
19590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
196187b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
196287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(mode != fXfermode);
19630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fXfermode, mode);
19640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return mode;
19650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
196703f42ddd729377f21719a140c027a1f8cc5c2152Mike ReedSkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
196803f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed    SkSafeUnref(fXfermode);
196903f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed    fXfermode = SkXfermode::Create(mode);
197087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC;
197103f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed    return fXfermode;
197203f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed}
197303f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed
197487b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
197587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(effect != fPathEffect);
19760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fPathEffect, effect);
19770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return effect;
19780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
198087b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
198187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(filter != fMaskFilter);
19820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fMaskFilter, filter);
19830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return filter;
19840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
198640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
19870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
198840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerbool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
19890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPath          effectPath, strokePath;
19900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkPath*   path = &src;
19910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
19920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar width = this->getStrokeWidth();
199340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
19940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (this->getStyle()) {
199540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        case SkPaint::kFill_Style:
19960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = -1; // mark it as no-stroke
199740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            break;
199840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        case SkPaint::kStrokeAndFill_Style:
199940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (width == 0) {
200040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                width = -1; // mark it as no-stroke
200140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
200240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            break;
200340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        case SkPaint::kStroke_Style:
200440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            break;
200540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        default:
20061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown paint style");
20070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
20080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
200940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->getPathEffect()) {
20100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
201140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->getStyle() == SkPaint::kStrokeAndFill_Style) {
20120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = -1; // mark it as no-stroke
201340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
20140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
201540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->getPathEffect()->filterPath(&effectPath, src, &width)) {
20160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            path = &effectPath;
201740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
201840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
20190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // restore the width if we earlier had to lie, and if we're still set to no-stroke
20200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
20210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // and we want to respect that (i.e. don't overwrite their setting for width)
202240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) {
20230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = this->getStrokeWidth();
202440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (width == 0) {
20250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                width = -1;
202640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
20270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
20280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
202940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
203040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (width > 0 && !path->isEmpty()) {
20310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkStroke stroker(*this, width);
20320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        stroker.strokePath(*path, &strokePath);
20330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        path = &strokePath;
20340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
20350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
203640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (path == &src) {
20370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst = src;
203840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
20390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(path == &effectPath || path == &strokePath);
20400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dst->swap(*(SkPath*)path);
20410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
20420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return width != 0;  // return true if we're filled, or false if we're hairline (width == 0)
20440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
20450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2046717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenbergerconst SkRect& SkPaint::doComputeFastBounds(const SkRect& src,
2047717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                                                 SkRect* storage) const {
20480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(storage);
2049717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2050717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    if (this->getLooper()) {
2051717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2052717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        this->getLooper()->computeFastBounds(*this, src, storage);
2053717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        return *storage;
2054717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    }
2055717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2056717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    if (this->getStyle() != SkPaint::kFill_Style) {
2057717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        // since we're stroked, outset the rect by the radius (and join type)
2058717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        SkScalar radius = SkScalarHalf(this->getStrokeWidth());
2059717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        if (0 == radius) {  // hairline
2060717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            radius = SK_Scalar1;
2061717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
2062717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            SkScalar scale = this->getStrokeMiter();
2063717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            if (scale > SK_Scalar1) {
2064717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                radius = SkScalarMul(radius, scale);
2065717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            }
20660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2067717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        storage->set(src.fLeft - radius, src.fTop - radius,
2068717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                     src.fRight + radius, src.fBottom + radius);
2069717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    } else {
2070717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        *storage = src;
20710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2072717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2073717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    // check the mask filter
2074717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    if (this->getMaskFilter()) {
2075717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        this->getMaskFilter()->computeFastBounds(*storage, storage);
2076717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    }
2077717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
207835d15937afb7f4b3472e43ea784b02485ec910fbMike Reed    return *storage;
20790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
20800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
208140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
20820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
208340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic bool has_thick_frame(const SkPaint& paint) {
208440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return  paint.getStrokeWidth() > 0 &&
208540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            paint.getStyle() != SkPaint::kFill_Style;
20860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
20870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
20890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    const SkPaint& paint,
20900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    bool applyStrokeAndPathEffects,
209140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                    bool forceLinearTextOn) : fPaint(paint) {
20920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
20930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                true);
20940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
209540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (forceLinearTextOn) {
20960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint.setLinearText(true);
209740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
20980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
20990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
210040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
21010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        applyStrokeAndPathEffects = false;
210240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
21030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // can't use our canonical size if we need to apply patheffects/strokes
2105b9e9dcfa17a61a0cc2c192daae78d0af2927736aDerek Sollenberger    if (fPaint.getPathEffect() == NULL) {
21060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
21070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2108b9e9dcfa17a61a0cc2c192daae78d0af2927736aDerek Sollenberger        if (has_thick_frame(fPaint)) {
2109b9e9dcfa17a61a0cc2c192daae78d0af2927736aDerek Sollenberger            fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
2110b9e9dcfa17a61a0cc2c192daae78d0af2927736aDerek Sollenberger        }
211140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
21120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fScale = SK_Scalar1;
211340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
211440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
211540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (!applyStrokeAndPathEffects) {
21160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint.setStyle(SkPaint::kFill_Style);
21170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint.setPathEffect(NULL);
21180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
21190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCache = fPaint.detachCache(NULL);
21210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint::Style  style = SkPaint::kFill_Style;
21230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPathEffect*   pe = NULL;
21240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
212540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (!applyStrokeAndPathEffects) {
21260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        style = paint.getStyle();   // restore
21270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        pe = paint.getPathEffect();     // restore
21280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
21290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPaint.setStyle(style);
21300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPaint.setPathEffect(pe);
21310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPaint.setMaskFilter(paint.getMaskFilter());    // restore
21320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // now compute fXOffset if needed
21340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar xOffset = 0;
213640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
21370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int      count;
213840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
213940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                         &count, NULL), fScale);
214040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
21410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = SkScalarHalf(width);
214240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
21430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        xOffset = -width;
21440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
21450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fXPos = xOffset;
21460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPrevAdvance = 0;
21470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fText = text;
21490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStop = text + length;
21501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fXYIndex = paint.isVerticalText() ? 1 : 0;
21520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
21530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
215440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkTextToPathIter::~SkTextToPathIter() {
21550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache::AttachCache(fCache);
21560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
21570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
215840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerconst SkPath* SkTextToPathIter::next(SkScalar* xpos) {
215940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    while (fText < fStop) {
21600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
21610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
21620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
21631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
21640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
216540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (glyph.fWidth) {
216640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (xpos) {
21670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *xpos = fXPos;
216840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
21690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return fCache->findPath(glyph);
21700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
21710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
21720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return NULL;
21730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2174717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2175717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
2176717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
21771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkPaint::nothingToDraw() const {
21781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fLooper) {
21791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
21801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
21811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkXfermode::Mode mode;
21821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkXfermode::AsMode(fXfermode, &mode)) {
21831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (mode) {
21841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kSrcOver_Mode:
21851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kSrcATop_Mode:
21861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kDstOut_Mode:
21871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kDstOver_Mode:
21881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kPlus_Mode:
21891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                return 0 == this->getAlpha();
21901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kDst_Mode:
21911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                return true;
21921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            default:
21931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
21941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
21951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
21961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return false;
21971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
21981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger//////////// Move these to their own file soon.
22011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
22031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                const SkMatrix& ctm,
22041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                SkBitmap* result, SkIPoint* loc) {
22051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(proxy);
22061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(result);
22071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(loc);
22081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    /*
22091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     *  Give the proxy first shot at the filter. If it returns false, ask
22101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     *  the filter to do it.
22111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     */
22121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return proxy->filterImage(this, src, ctm, result, loc) ||
22131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger           this->onFilterImage(proxy, src, ctm, result, loc);
22141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
22151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
22171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 SkIRect* dst) {
22181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(&src);
22191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(dst);
22201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return this->onFilterBounds(src, ctm, dst);
22211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
22221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
22241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  SkBitmap*, SkIPoint*) {
22251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return false;
22261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
22271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
22291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   SkIRect* dst) {
22301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *dst = src;
22311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
22321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
22331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::asABlur(SkSize* sigma) const {
22351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return false;
22361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
22371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkImageFilter::asAnErode(SkISize* radius) const {
22394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return false;
22404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
22414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
22424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkImageFilter::asADilate(SkISize* radius) const {
22434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return false;
22444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
22454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
22464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger//////
22474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2248717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenbergerbool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) {
2249717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    SkCanvas canvas;
2250717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2251717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    this->init(&canvas);
2252717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    for (;;) {
2253717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        SkPaint p(paint);
2254717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        if (this->next(&canvas, &p)) {
2255717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            p.setLooper(NULL);
2256717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            if (!p.canComputeFastBounds()) {
2257717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                return false;
2258717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            }
2259717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        } else {
2260717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            break;
2261717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        }
2262717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    }
2263717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    return true;
2264717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger}
2265717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2266717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenbergervoid SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
2267717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                                     SkRect* dst) {
2268717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    SkCanvas canvas;
22694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2270717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    this->init(&canvas);
2271717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    for (bool firstTime = true;; firstTime = false) {
2272717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        SkPaint p(paint);
2273717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        if (this->next(&canvas, &p)) {
2274717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            SkRect r(src);
2275717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2276717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            p.setLooper(NULL);
2277717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            p.computeFastBounds(r, &r);
2278717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            canvas.getTotalMatrix().mapRect(&r);
2279717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2280717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            if (firstTime) {
2281717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                *dst = r;
2282717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            } else {
2283717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                dst->join(r);
2284717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            }
2285717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        } else {
2286717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            break;
2287717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        }
2288717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    }
2289717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger}
22901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2291