SkPaint.cpp revision 4f1dae40e24d57d647db01443b8bf2410514b8b5
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
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPaint.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorFilter.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFontHost.h"
131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkImageFilter.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h"
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathEffect.h"
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRasterizer.h"
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkShader.h"
1840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkScalar.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScalerContext.h"
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStroke.h"
2140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkTextFormatParams.h"
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTypeface.h"
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkXfermode.h"
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkAutoKern.h"
251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkGlyphCache.h"
264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkPaintDefaults.h"
271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// define this to get a printf for out-of-range parameter in setters
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// e.g. setTextSize(-1)
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger//#define SK_REPORT_API_RANGE_CHECK
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
3387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#define GEN_ID_INC                  fGenerationID++
3487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
3587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#else
3687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#define GEN_ID_INC
3787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#define GEN_ID_INC_EVAL(expression)
3887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
3987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
40c1c43a17e7f2a87951739691056728a80e9aef6bMike ReedSkPaint::SkPaint() {
41c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    // since we may have padding, we zero everything so that our memcmp() call
42c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    // in operator== will work correctly.
43c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    // with this, we can skip 0 and null individual initializations
44c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    sk_bzero(this, sizeof(*this));
45c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed
46c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed#if 0   // not needed with the bzero call above
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTypeface   = NULL;
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTextSkewX  = 0;
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPathEffect  = NULL;
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fShader      = NULL;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fXfermode    = NULL;
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fMaskFilter  = NULL;
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fColorFilter = NULL;
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRasterizer  = NULL;
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLooper      = NULL;
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fImageFilter = NULL;
57c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    fWidth      = 0;
58c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed#endif
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fTextSize   = SkPaintDefaults_TextSize;
61c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed    fTextScaleX = SK_Scalar1;
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fColor      = SK_ColorBLACK;
634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fMiterLimit = SkPaintDefaults_MiterLimit;
644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fFlags      = SkPaintDefaults_Flags;
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCapType    = kDefault_Cap;
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fJoinType   = kDefault_Join;
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTextAlign  = kLeft_Align;
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStyle      = kFill_Style;
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTextEncoding = kUTF8_TextEncoding;
704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fHinting    = SkPaintDefaults_Hinting;
711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
7295662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    fGenerationID = 0;
7387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkPaint::SkPaint(const SkPaint& src) {
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    memcpy(this, &src, sizeof(src));
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fTypeface);
8040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fPathEffect);
8140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fShader);
8240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fXfermode);
8340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fMaskFilter);
8440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fColorFilter);
8540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fRasterizer);
8640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(fLooper);
871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSafeRef(fImageFilter);
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkPaint::~SkPaint() {
9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fTypeface);
9240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fPathEffect);
9340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fShader);
9440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fXfermode);
9540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fMaskFilter);
9640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fColorFilter);
9740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fRasterizer);
9840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fLooper);
991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSafeUnref(fImageFilter);
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkPaint& SkPaint::operator=(const SkPaint& src) {
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(&src);
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fTypeface);
10640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fPathEffect);
10740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fShader);
10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fXfermode);
10940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fMaskFilter);
11040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fColorFilter);
11140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fRasterizer);
11240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeRef(src.fLooper);
1131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSafeRef(src.fImageFilter);
11440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fTypeface);
11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fPathEffect);
11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fShader);
11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fXfermode);
11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fMaskFilter);
12040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fColorFilter);
12140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fRasterizer);
12240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkSafeUnref(fLooper);
1231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSafeUnref(fImageFilter);
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1269f523ea27ec892a176817dc3a46179c0a910beb4Chet Haase    uint32_t oldGenerationID = fGenerationID;
12787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    memcpy(this, &src, sizeof(src));
1291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1309f523ea27ec892a176817dc3a46179c0a910beb4Chet Haase    fGenerationID = oldGenerationID + 1;
13187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return *this;
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool operator==(const SkPaint& a, const SkPaint& b) {
1371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    //assumes that fGenerationID is the last field in the struct
1391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return !memcmp(&a, &b, SK_OFFSETOF(SkPaint, fGenerationID));
1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return !memcmp(&a, &b, sizeof(a));
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkPaint::reset() {
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint init;
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1499f523ea27ec892a176817dc3a46179c0a910beb4Chet Haase    uint32_t oldGenerationID = fGenerationID;
15087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *this = init;
1521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1539f523ea27ec892a176817dc3a46179c0a910beb4Chet Haase    fGenerationID = oldGenerationID + 1;
15487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
15595662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase}
15695662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase
1571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
15895662ea6ee460cc84014c41a8c13e881cd8be8edChet Haaseuint32_t SkPaint::getGenerationID() const {
15995662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    return fGenerationID;
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
16187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
1641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerunsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
1651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAutoGlyphCache autoCache(*this, NULL);
1661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkGlyphCache* cache = autoCache.getCache();
1671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return cache->getBaseGlyphCount(text);
1681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
1691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
1701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
17187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setHinting(Hinting hintingLevel) {
17287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
17387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fHinting = hintingLevel;
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
17687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setFlags(uint32_t flags) {
17787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(fFlags != flags);
17887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fFlags = flags;
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
18187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setAntiAlias(bool doAA) {
18287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doAA != isAntiAlias());
18387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
18687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setDither(bool doDither) {
18787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doDither != isDither());
18887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
19187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setSubpixelText(bool doSubpixel) {
19287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doSubpixel != isSubpixelText());
19387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
194af2616552738d653d5453915d3236e7154b868cdMike Reed}
195af2616552738d653d5453915d3236e7154b868cdMike Reed
19687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setLCDRenderText(bool doLCDRender) {
19787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doLCDRender != isLCDRenderText());
19887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
19987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger}
20087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger
20187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
20287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doEmbeddedBitmapText != isEmbeddedBitmapText());
20387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
2042cf237c941bf5964f654d0ccdd639a26468e1d71Mike Reed}
2052cf237c941bf5964f654d0ccdd639a26468e1d71Mike Reed
20687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setAutohinted(bool useAutohinter) {
20787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(useAutohinter != isAutohinted());
20840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
20940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
21040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
21187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setLinearText(bool doLinearText) {
21287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doLinearText != isLinearText());
21387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkPaint::setVerticalText(bool doVertical) {
2171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GEN_ID_INC_EVAL(doVertical != isVerticalText());
2181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doVertical, kVerticalText_Flag));
2191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
22187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setUnderlineText(bool doUnderline) {
22287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doUnderline != isUnderlineText());
22387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
22687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrikeThruText(bool doStrikeThru) {
22787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doStrikeThru != isStrikeThruText());
22887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
23187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setFakeBoldText(bool doFakeBold) {
23287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doFakeBold != isFakeBoldText());
23387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
23687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setDevKernText(bool doDevKern) {
23787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doDevKern != isDevKernText());
23887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
24187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setFilterBitmap(bool doFilter) {
24287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(doFilter != isFilterBitmap());
24387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
24687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStyle(Style style) {
24795662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)style < kStyleCount) {
24887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)style != fStyle);
24987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fStyle = style;
25087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
2511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
2521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
2531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
25405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
25787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setColor(SkColor color) {
25887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(color != fColor);
25987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fColor = color;
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
26287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setAlpha(U8CPU a) {
26387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
26487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger                                  SkColorGetG(fColor), SkColorGetB(fColor)));
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
26787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
26887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    this->setColor(SkColorSetARGB(a, r, g, b));
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
27187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrokeWidth(SkScalar width) {
27295662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if (width >= 0) {
27387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL(width != fWidth);
27487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fWidth = width;
27587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
2761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
2771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
2781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
27905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
28287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrokeMiter(SkScalar limit) {
28395662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if (limit >= 0) {
28487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL(limit != fMiterLimit);
28587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fMiterLimit = limit;
28687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
2871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
2881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
2891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
29005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
29387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrokeCap(Cap ct) {
29495662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)ct < kCapCount) {
29587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)ct != fCapType);
29687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fCapType = SkToU8(ct);
29787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
2981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
2991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
3001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
30195662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
30487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setStrokeJoin(Join jt) {
30595662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)jt < kJoinCount) {
30687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
30787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fJoinType = SkToU8(jt);
30887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
3111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
31295662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
31587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
31787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextAlign(Align align) {
31895662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)align < kAlignCount) {
31987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
32087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fTextAlign = SkToU8(align);
32187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
3241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
32595662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
32887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextSize(SkScalar ts) {
3291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (ts >= 0) {
33087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL(ts != fTextSize);
33187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fTextSize = ts;
33287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setTextSize() called with negative value\n");
3351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
33695662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
33987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextScaleX(SkScalar scaleX) {
34087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(scaleX != fTextScaleX);
34187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fTextScaleX = scaleX;
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
34487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextSkewX(SkScalar skewX) {
34587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(skewX != fTextSkewX);
34687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    fTextSkewX = skewX;
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
34987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergervoid SkPaint::setTextEncoding(TextEncoding encoding) {
35095662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    if ((unsigned)encoding <= kGlyphID_TextEncoding) {
35187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
35287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger        fTextEncoding = encoding;
35387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    } else {
3541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_REPORT_API_RANGE_CHECK
3551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
3561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
35795662ea6ee460cc84014c41a8c13e881cd8be8edChet Haase    }
3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
36087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
36287b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkTypeface* SkPaint::setTypeface(SkTypeface* font) {
3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fTypeface, font);
36487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC;
3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return font;
3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
36840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fRasterizer, r);
37087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC;
3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return r;
3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
37440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fLooper, looper);
37687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC;
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return looper;
3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3801cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkRefCnt_SafeAssign(fImageFilter, imageFilter);
3821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GEN_ID_INC;
3831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return imageFilter;
3841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGlyphCache.h"
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkUtils.h"
3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
39140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void DetachDescProc(const SkDescriptor* desc, void* context) {
392fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
393fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy}
394fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy
3951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
396b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guyconst SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) {
397b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    SkGlyphCache* cache;
398b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    descriptorProc(NULL, DetachDescProc, &cache, true);
399b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy
400b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    const SkGlyph& glyph = cache->getUnicharMetrics(text);
401b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy
402b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    SkGlyphCache::AttachCache(cache);
403b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy    return glyph;
404b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy}
405b0bc5be3bc222f6f6586f727e1260a7e39afd14dRomain Guy
4061bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guyconst SkGlyph& SkPaint::getGlyphMetrics(uint16_t glyphId) {
4071bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    SkGlyphCache* cache;
4081bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    descriptorProc(NULL, DetachDescProc, &cache, true);
4091bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy
4101bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphId);
4111bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy
4121bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    SkGlyphCache::AttachCache(cache);
4131bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy    return glyph;
4141bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy}
4151bb7fdb27396cf7069375b10e1f6d763ef4e0511Romain Guy
41690a1efbdde19ee56c33929592277871509c25893Romain Guyconst void* SkPaint::findImage(const SkGlyph& glyph) {
417fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    // See ::detachCache()
418fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    SkGlyphCache* cache;
419fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    descriptorProc(NULL, DetachDescProc, &cache, true);
42090a1efbdde19ee56c33929592277871509c25893Romain Guy
421fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    const void* image = cache->findImage(glyph);
422fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy
423fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    SkGlyphCache::AttachCache(cache);
424fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    return image;
42590a1efbdde19ee56c33929592277871509c25893Romain Guy}
42687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif
42790a1efbdde19ee56c33929592277871509c25893Romain Guy
4280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint SkPaint::textToGlyphs(const void* textData, size_t byteLength,
4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                          uint16_t glyphs[]) const {
4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (byteLength == 0) {
4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
43340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(textData != NULL);
4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == glyphs) {
4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        switch (this->getTextEncoding()) {
4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kUTF8_TextEncoding:
4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return SkUTF8_CountUnichars((const char*)textData, byteLength);
4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kUTF16_TextEncoding:
4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return SkUTF16_CountUnichars((const uint16_t*)textData,
4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                         byteLength >> 1);
4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kGlyphID_TextEncoding:
4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return byteLength >> 1;
4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
4461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown text encoding");
4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
45040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // if we get here, we have a valid glyphs[] array, so time to fill it in
45240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // handle this encoding before the setup for the glyphcache
4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // we want to ignore the low bit of byteLength
4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        memcpy(glyphs, textData, byteLength >> 1 << 1);
4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return byteLength >> 1;
4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
45940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache autoCache(*this, NULL);
4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*    cache = autoCache.getCache();
4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textData;
4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* stop = text + byteLength;
4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint16_t*   gptr = glyphs;
4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (this->getTextEncoding()) {
4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkPaint::kUTF8_TextEncoding:
4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkPaint::kUTF16_TextEncoding: {
4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const uint16_t* text16 = (const uint16_t*)text;
4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const uint16_t* stop16 = (const uint16_t*)stop;
4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text16 < stop16) {
4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
4821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown text encoding");
4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return gptr - glyphs;
4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
48775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reedbool SkPaint::containsText(const void* textData, size_t byteLength) const {
48875c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    if (0 == byteLength) {
48975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        return true;
49075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    }
49140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
49275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    SkASSERT(textData != NULL);
49340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
49475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    // handle this encoding before the setup for the glyphcache
49575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    if (this->getTextEncoding() == kGlyphID_TextEncoding) {
49675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
49775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        size_t count = byteLength >> 1;
49875c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        for (size_t i = 0; i < count; i++) {
49975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            if (0 == glyphID[i]) {
50075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                return false;
50175c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            }
50275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        }
50375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        return true;
50475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    }
50540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
50675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    SkAutoGlyphCache autoCache(*this, NULL);
50775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    SkGlyphCache*    cache = autoCache.getCache();
50875c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed
50975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    switch (this->getTextEncoding()) {
51075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        case SkPaint::kUTF8_TextEncoding: {
51175c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            const char* text = static_cast<const char*>(textData);
51275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            const char* stop = text + byteLength;
51375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            while (text < stop) {
51475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
51575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                    return false;
51675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                }
51775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            }
51875c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            break;
51975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        }
52075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        case SkPaint::kUTF16_TextEncoding: {
52175c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            const uint16_t* text = static_cast<const uint16_t*>(textData);
52275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            const uint16_t* stop = text + (byteLength >> 1);
52375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            while (text < stop) {
52475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
52575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                    return false;
52675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed                }
52775c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            }
52875c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            break;
52975c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        }
53075c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed        default:
5311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown text encoding");
53275c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed            return false;
53375c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    }
53475c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed    return true;
53575c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed}
53675c8af293816b94cd8fd9a3d9b3a4d6e052dedfeMike Reed
537091f227385b467090b5a7169a8e2faf19eca7105Mike Reedvoid SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
538091f227385b467090b5a7169a8e2faf19eca7105Mike Reed                               SkUnichar textData[]) const {
539091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    if (count <= 0) {
540091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        return;
541091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    }
542091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
543091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkASSERT(glyphs != NULL);
544091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkASSERT(textData != NULL);
545091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
546091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkAutoGlyphCache autoCache(*this, NULL);
547091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    SkGlyphCache*    cache = autoCache.getCache();
548091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
549091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    for (int index = 0; index < count; index++) {
550091f227385b467090b5a7169a8e2faf19eca7105Mike Reed        textData[index] = cache->glyphToUnichar(glyphs[index]);
551091f227385b467090b5a7169a8e2faf19eca7105Mike Reed    }
552091f227385b467090b5a7169a8e2faf19eca7105Mike Reed}
553091f227385b467090b5a7169a8e2faf19eca7105Mike Reed
5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
55640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
55740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                              const char** text) {
5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
5590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
56040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
56440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
56540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                              const char** text) {
5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
56840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
57240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
57340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
57640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
58040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
58140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
58440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
58840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
58940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
59240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr += 1;
5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
5970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDMetrics(glyphID);
5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
60040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
60140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
60440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
6060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr -= 1;
6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
6090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDMetrics(glyphID);
6100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
61240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
61340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                              const char** text) {
6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
61640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
62040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
62140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                              const char** text) {
6220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
62440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
6260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
62840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
62940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
63240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
63640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
63740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
64040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
64440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
64540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
64840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
6500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr += 1;
6520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDAdvance(glyphID);
6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
65640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
65740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                               const char** text) {
6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
66040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr -= 1;
6630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
6650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDAdvance(glyphID);
6660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
6670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
66940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                bool needFullMetrics) const {
6700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static const SkMeasureCacheProc gMeasureCacheProcs[] = {
6710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf8_next,
6720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf16_next,
6730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_glyph_next,
67440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf8_prev,
6760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf16_prev,
6770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_glyph_prev,
67840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_utf8_next,
6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_utf16_next,
6810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_glyph_next,
68240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_utf8_prev,
6840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_utf16_prev,
6850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getAdvance_glyph_prev
6860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
68740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned index = this->getTextEncoding();
6890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
69040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (kBackward_TextBufferDirection == tbd) {
6910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index += 3;
69240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
69340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (!needFullMetrics && !this->isDevKernText()) {
6940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index += 6;
69540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
6960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
6980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return gMeasureCacheProcs[index];
6990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
7020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
70440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                        const char** text, SkFixed, SkFixed) {
7050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
70740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
7090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
71240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                    const char** text, SkFixed x, SkFixed y) {
7130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
71540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
7170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
71940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
72040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                        const char** text, SkFixed, SkFixed) {
7210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
72340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
7250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
72840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                     const char** text, SkFixed x, SkFixed y) {
7290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
73140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
7330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    x, y);
7340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
73640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
73740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                         const char** text, SkFixed, SkFixed) {
7380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
74040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
7420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
7430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr += 1;
7440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
7450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDMetrics(glyphID);
7460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
74940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                     const char** text, SkFixed x, SkFixed y) {
7500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(cache != NULL);
7510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL);
75240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const uint16_t* ptr = *(const uint16_t**)text;
7540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned glyphID = *ptr;
7550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ptr += 1;
7560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *text = (const char*)ptr;
7570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache->getGlyphIDMetrics(glyphID, x, y);
7580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
76040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkDrawCacheProc SkPaint::getDrawCacheProc() const {
7610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static const SkDrawCacheProc gDrawCacheProcs[] = {
7620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf8_00,
7630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf16_00,
7640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_glyph_00,
76540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf8_xy,
7670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_utf16_xy,
7680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        sk_getMetrics_glyph_xy
7690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    };
77040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned index = this->getTextEncoding();
77240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fFlags & kSubpixelText_Flag) {
7730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index += 3;
77440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
77540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
7770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return gDrawCacheProcs[index];
7780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
7810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkAutoRestorePaintTextSizeAndFrame {
7830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
78440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint)
78540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            : fPaint((SkPaint*)paint) {
7860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fTextSize = paint->getTextSize();
7870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fStyle = paint->getStyle();
7880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setStyle(SkPaint::kFill_Style);
7890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
79040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
79140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    ~SkAutoRestorePaintTextSizeAndFrame() {
7920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setStyle(fStyle);
7930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint->setTextSize(fTextSize);
7940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
79540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
7970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint*        fPaint;
7980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        fTextSize;
7990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint::Style  fStyle;
8000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
8010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
80240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void set_bounds(const SkGlyph& g, SkRect* bounds) {
8030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->set(SkIntToScalar(g.fLeft),
8040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkIntToScalar(g.fTop),
8050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkIntToScalar(g.fLeft + g.fWidth),
8060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkIntToScalar(g.fTop + g.fHeight));
8070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
809e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed// 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
810e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed// we don't overflow along the way
811e63c5c9f6752244ca0f39075fa148a0281593831Mike Reedtypedef int64_t Sk48Dot16;
812e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed
813e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed#ifdef SK_SCALAR_IS_FLOAT
814e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
81540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return (float) (x * 1.5258789e-5);   // x * (1 / 65536.0f)
816e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    }
817e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed#else
818e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    static inline SkFixed Sk48Dot16ToScalar(Sk48Dot16 x) {
819e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed        // just return the low 32bits
820e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed        return static_cast<SkFixed>(x);
821e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    }
822e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed#endif
823e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed
8241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
825e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    SkScalar sx = Sk48Dot16ToScalar(dx);
8260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->join(SkIntToScalar(g.fLeft) + sx,
8270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                 SkIntToScalar(g.fTop),
8280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                 SkIntToScalar(g.fLeft + g.fWidth) + sx,
8290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                 SkIntToScalar(g.fTop + g.fHeight));
8300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
8331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar sy = Sk48Dot16ToScalar(dy);
8341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bounds->join(SkIntToScalar(g.fLeft),
8351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkIntToScalar(g.fTop) + sy,
8361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkIntToScalar(g.fLeft + g.fWidth),
8371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 SkIntToScalar(g.fTop + g.fHeight) + sy);
8381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
8391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
8411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
8431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkFixed advance(const SkGlyph& glyph, int xyIndex) {
8441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(0 == xyIndex || 1 == xyIndex);
8451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return (&glyph.fAdvanceX)[xyIndex];
8461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
8471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPaint::measure_text(SkGlyphCache* cache,
8490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                               const char* text, size_t byteLength,
85040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                               int* count, SkRect* bounds) const {
8510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(count);
85240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (byteLength == 0) {
8530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *count = 0;
85440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (bounds) {
8550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            bounds->setEmpty();
85640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
8570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
8580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
8590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMeasureCacheProc glyphCacheProc;
8610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
8620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                               NULL != bounds);
8630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int xyIndex;
8651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    JoinBoundsProc joinBoundsProc;
8661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (this->isVerticalText()) {
8671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        xyIndex = 1;
8681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        joinBoundsProc = join_bounds_y;
8691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
8701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        xyIndex = 0;
8711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        joinBoundsProc = join_bounds_x;
8721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
8731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int         n = 1;
8750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* stop = (const char*)text + byteLength;
8760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkGlyph* g = &glyphCacheProc(cache, &text);
877e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    // our accumulated fixed-point advances might overflow 16.16, so we use
878e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    // a 48.16 (64bit) accumulator, and then convert that to scalar at the
879e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    // very end.
8801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Sk48Dot16 x = advance(*g, xyIndex);
8810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoKern  autokern;
8830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
88440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == bounds) {
88540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->isDevKernText()) {
8860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int rsb;
8870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (; text < stop; n++) {
8880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rsb = g->fRsbDelta;
8890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                g = &glyphCacheProc(cache, &text);
8901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
8910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
89240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
8930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (; text < stop; n++) {
8941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += advance(glyphCacheProc(cache, &text), xyIndex);
8950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
89740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
8980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        set_bounds(*g, bounds);
89940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->isDevKernText()) {
9000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int rsb;
9010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (; text < stop; n++) {
9020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rsb = g->fRsbDelta;
9030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                g = &glyphCacheProc(cache, &text);
9040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
9051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                joinBoundsProc(*g, bounds, x);
9061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += advance(*g, xyIndex);
9070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
90840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
9090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (; text < stop; n++) {
9100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                g = &glyphCacheProc(cache, &text);
9111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                joinBoundsProc(*g, bounds, x);
9121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                x += advance(*g, xyIndex);
9130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
9140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
9150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text == stop);
9170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *count = n;
919e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    return Sk48Dot16ToScalar(x);
9200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPaint::measureText(const void* textData, size_t length,
92340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                              SkRect* bounds, SkScalar zoom) const {
9240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textData;
9250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text != NULL || length == 0);
9260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                            scale = 0;
9280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoRestorePaintTextSizeAndFrame  restore(this);
9290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
93040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isLinearText()) {
9310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scale = fTextSize / kCanonicalTextSizeForPaths;
9320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this gets restored by restore
9330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
9340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
93540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
93640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkMatrix zoomMatrix, *zoomPtr = NULL;
93740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (zoom) {
9380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        zoomMatrix.setScale(zoom, zoom);
9390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        zoomPtr = &zoomMatrix;
9400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache    autoCache(*this, zoomPtr);
9430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*       cache = autoCache.getCache();
9440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar width = 0;
94640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
94740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (length > 0) {
9480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int tempCount;
9490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        width = this->measure_text(cache, text, length, &tempCount, bounds);
95140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (scale) {
9520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = SkScalarMul(width, scale);
95340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (bounds) {
9540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
9550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bounds->fTop = SkScalarMul(bounds->fTop, scale);
9560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bounds->fRight = SkScalarMul(bounds->fRight, scale);
9570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
9580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
9590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
9600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return width;
9620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecttypedef bool (*SkTextBufferPred)(const char* text, const char* stop);
9650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
96640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic bool forward_textBufferPred(const char* text, const char* stop) {
9670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return text < stop;
9680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
97040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic bool backward_textBufferPred(const char* text, const char* stop) {
9710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return text > stop;
9720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
97540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                             const char** text, size_t length,
97640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                             const char** stop) {
97740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (SkPaint::kForward_TextBufferDirection == tbd) {
9780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *stop = *text + length;
9790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return forward_textBufferPred;
98040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
9810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // text should point to the end of the buffer, and stop to the beginning
9820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *stop = *text;
9830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *text += length;
9840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return backward_textBufferPred;
9850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectsize_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
9890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                          SkScalar* measuredWidth,
99040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                          TextBufferDirection tbd) const {
99140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (0 == length || 0 >= maxWidth) {
99240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (measuredWidth) {
9930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *measuredWidth = 0;
99440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
9950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
9960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == fTextSize) {
9991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (measuredWidth) {
10001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            *measuredWidth = 0;
10011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
10021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return length;
10031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
10041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
10050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(textD != NULL);
10060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textD;
10070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                            scale = 0;
10090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoRestorePaintTextSizeAndFrame  restore(this);
10100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
101140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isLinearText()) {
10120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scale = fTextSize / kCanonicalTextSizeForPaths;
10139b1cba8ccd7554cb30905711a426bd86ad8dd38cJean-Baptiste Queru        maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize);
10140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this gets restored by restore
10150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
10160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
101740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
10180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache    autoCache(*this, NULL);
10190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*       cache = autoCache.getCache();
10200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
10220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char*      stop;
10230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
10241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int        xyIndex = this->isVerticalText() ? 1 : 0;
1025e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    // use 64bits for our accumulator, to avoid overflowing 16.16
1026e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    Sk48Dot16        max = SkScalarToFixed(maxWidth);
1027e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed    Sk48Dot16        width = 0;
10280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoKern  autokern;
10300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
103140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isDevKernText()) {
10320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int rsb = 0;
103340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        while (pred(text, stop)) {
10340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const char* curr = text;
10350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const SkGlyph& g = glyphCacheProc(cache, &text);
10361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
103740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if ((width += x) > max) {
10380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                width -= x;
10390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                text = curr;
10400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
10410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
10420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            rsb = g.fRsbDelta;
10430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
104440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
104540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        while (pred(text, stop)) {
10460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const char* curr = text;
10471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
104840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if ((width += x) > max) {
10490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                width -= x;
10500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                text = curr;
10510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
10520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
10530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
10540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
105540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
105640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (measuredWidth) {
1057e63c5c9f6752244ca0f39075fa148a0281593831Mike Reed        SkScalar scalarWidth = Sk48Dot16ToScalar(width);
105840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (scale) {
10590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            scalarWidth = SkScalarMul(scalarWidth, scale);
106040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
10610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *measuredWidth = scalarWidth;
10620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
106340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
10640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // return the number of bytes measured
10650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (kForward_TextBufferDirection == tbd) ?
10660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                text - stop + length : stop - text + length;
10670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
10700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
107140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
10720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
10730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;   // don't detach the cache
10740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
107640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void FontMetricsDescProc(const SkDescriptor* desc, void* context) {
10770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
10780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
108040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
10810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                            scale = 0;
10820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoRestorePaintTextSizeAndFrame  restore(this);
10830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
108440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isLinearText()) {
10850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scale = fTextSize / kCanonicalTextSizeForPaths;
10860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this gets restored by restore
10870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
10880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
108940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
109040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkMatrix zoomMatrix, *zoomPtr = NULL;
109140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (zoom) {
10920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        zoomMatrix.setScale(zoom, zoom);
10930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        zoomPtr = &zoomMatrix;
10940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0
10970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache    autoCache(*this, zoomPtr);
10980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*       cache = autoCache.getCache();
10990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const FontMetrics&  my = cache->getFontMetricsY();
11000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
11010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    FontMetrics storage;
110240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == metrics) {
11030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics = &storage;
110440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
110540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics, true);
11070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
110840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (scale) {
11090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fTop = SkScalarMul(metrics->fTop, scale);
11100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
11110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
11120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
11130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
11140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return metrics->fDescent - metrics->fAscent + metrics->fLeading;
11160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
111840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
11190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
112040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
11210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->set(g.fLeft * scale,
11220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                g.fTop * scale,
11230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                (g.fLeft + g.fWidth) * scale,
11240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                (g.fTop + g.fHeight) * scale);
11250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
112740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerint SkPaint::getTextWidths(const void* textData, size_t byteLength,
112840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                           SkScalar widths[], SkRect bounds[]) const {
112940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (0 == byteLength) {
11300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
113140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
11320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(NULL != textData);
11340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
113540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (NULL == widths && NULL == bounds) {
11360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->countText(textData, byteLength);
113740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
11380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoRestorePaintTextSizeAndFrame  restore(this);
11400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar                            scale = 0;
11410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
114240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isLinearText()) {
11430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scale = fTextSize / kCanonicalTextSizeForPaths;
11440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this gets restored by restore
11450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
11460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoGlyphCache    autoCache(*this, NULL);
11490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache*       cache = autoCache.getCache();
11500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMeasureCacheProc  glyphCacheProc;
11510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
11520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                               NULL != bounds);
11530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textData;
11550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* stop = text + byteLength;
11560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int         count = 0;
11571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const int   xyIndex = this->isVerticalText() ? 1 : 0;
11580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
115940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->isDevKernText()) {
11600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // we adjust the widths returned here through auto-kerning
11610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkAutoKern  autokern;
11620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkFixed     prevWidth = 0;
11630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (scale) {
11650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
11660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkGlyph& g = glyphCacheProc(cache, &text);
11670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (widths) {
11680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkFixed  adjust = autokern.adjust(g);
11690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    if (count > 0) {
11710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        SkScalar w = SkFixedToScalar(prevWidth + adjust);
11720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        *widths++ = SkScalarMul(w, scale);
11730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    }
11741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    prevWidth = advance(g, xyIndex);
11750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
11760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bounds) {
11770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    set_bounds(g, bounds++, scale);
11780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
11790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++count;
11800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
11810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (count > 0 && widths) {
11820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
11830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
11840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
11850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
11860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkGlyph& g = glyphCacheProc(cache, &text);
11870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (widths) {
11880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkFixed  adjust = autokern.adjust(g);
11890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    if (count > 0) {
11910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        *widths++ = SkFixedToScalar(prevWidth + adjust);
11920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    }
11931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    prevWidth = advance(g, xyIndex);
11940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
11950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bounds) {
11960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    set_bounds(g, bounds++);
11970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
11980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++count;
11990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (count > 0 && widths) {
12010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *widths = SkFixedToScalar(prevWidth);
12020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {    // no devkern
12050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (scale) {
12060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
12070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkGlyph& g = glyphCacheProc(cache, &text);
12080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (widths) {
12091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
12100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                            scale);
12110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bounds) {
12130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    set_bounds(g, bounds++, scale);
12140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++count;
12160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
12180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (text < stop) {
12190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const SkGlyph& g = glyphCacheProc(cache, &text);
12200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (widths) {
12211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    *widths++ = SkFixedToScalar(advance(g, xyIndex));
12220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bounds) {
12240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    set_bounds(g, bounds++);
12250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
12260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++count;
12270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(text == stop);
12320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return count;
12330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
123540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
12360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDraw.h"
12380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
123940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkPaint::getTextPath(const void* textData, size_t length,
124040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                          SkScalar x, SkScalar y, SkPath* path) const {
124140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkASSERT(length == 0 || textData != NULL);
124240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* text = (const char*)textData;
124440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (text == NULL || length == 0 || path == NULL) {
12450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
124640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
12470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTextToPathIter    iter(text, length, *this, false, true);
12490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMatrix            matrix;
12500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar            prevXPos = 0;
12510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    matrix.setScale(iter.getPathScale(), iter.getPathScale());
12530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    matrix.postTranslate(x, y);
12540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    path->reset();
12550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        xpos;
12570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkPath*   iterPath;
125840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    while ((iterPath = iter.next(&xpos)) != NULL) {
12590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        matrix.postTranslate(xpos - prevXPos, 0);
12600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        path->addPath(*iterPath, matrix);
12610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        prevXPos = xpos;
12620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void add_flattenable(SkDescriptor* desc, uint32_t tag,
12660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                            SkFlattenableWriteBuffer* buffer) {
12670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
12680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// SkFontHost can override this choice in FilterRec()
127140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkMask::Format computeMaskFormat(const SkPaint& paint) {
12720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t flags = paint.getFlags();
12730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1274c49fcf5e8bc1c84bcb0a51fe615caa7e72dd7dccMike Reed    // Antialiasing being disabled trumps all other settings.
1275137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    if (!(flags & SkPaint::kAntiAlias_Flag)) {
1276c49fcf5e8bc1c84bcb0a51fe615caa7e72dd7dccMike Reed        return SkMask::kBW_Format;
127705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger    }
127805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger
1279137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    if (flags & SkPaint::kLCDRenderText_Flag) {
1280137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger        return SkMask::kLCD16_Format;
1281137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenberger    }
1282c49fcf5e8bc1c84bcb0a51fe615caa7e72dd7dccMike Reed
1283c49fcf5e8bc1c84bcb0a51fe615caa7e72dd7dccMike Reed    return SkMask::kA8_Format;
12840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12864bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed// if linear-text is on, then we force hinting to be off (since that's sort of
12874bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed// the point of linear-text.
12884bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reedstatic SkPaint::Hinting computeHinting(const SkPaint& paint) {
12894bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed    SkPaint::Hinting h = paint.getHinting();
12904bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed    if (paint.isLinearText()) {
12914bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed        h = SkPaint::kNo_Hinting;
12924bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed    }
12934bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed    return h;
12944bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed}
12954bf0086251c4e8ad9ef9067ffac7a3a97a09dd4aMike Reed
12961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// return true if the paint is just a single color (i.e. not a shader). If its
12971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// a shader, then we can't compute a const luminance for it :(
12981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool justAColor(const SkPaint& paint, SkColor* color) {
12991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (paint.getShader()) {
13001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
13011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkColor c = paint.getColor();
13031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (paint.getColorFilter()) {
13041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        c = paint.getColorFilter()->filterColor(c);
13051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (color) {
13071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        *color = c;
13081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
13101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
13111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
13134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic SkColor computeLuminanceColor(const SkPaint& paint) {
13144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkColor c;
13154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (!justAColor(paint, &c)) {
13164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        c = SkColorSetRGB(0x7F, 0x80, 0x7F);
13174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
13184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return c;
13194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
13204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
13214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define assert_byte(x)  SkASSERT(0 == ((x) >> 8))
13224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
13234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic U8CPU reduce_lumbits(U8CPU x) {
13244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    static const uint8_t gReduceBits[] = {
13254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        0x0, 0x55, 0xAA, 0xFF
13264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    };
13274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    assert_byte(x);
13284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return gReduceBits[x >> 6];
13294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
13304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
13314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic unsigned computeLuminance(SkColor c) {
13324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int r = SkColorGetR(c);
13334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int g = SkColorGetG(c);
13344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int b = SkColorGetB(c);
13354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // compute luminance
13364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // R=0.2126 G=0.7152 B=0.0722
13374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // scaling by 127 yields 27, 92, 9
13384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    int luminance = r * 27 + g * 92 + b * 9;
13394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    luminance >>= 7;
13404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    assert_byte(luminance);
13414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return luminance;
13424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
13434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
13444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
13451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// returns 0..kLuminance_Max
13461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic unsigned computeLuminance(const SkPaint& paint) {
13471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkColor c;
13481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (justAColor(paint, &c)) {
13491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int r = SkColorGetR(c);
13501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int g = SkColorGetG(c);
13511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int b = SkColorGetB(c);
13521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // compute luminance
13531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // R=0.2126 G=0.7152 B=0.0722
13541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // scaling by 127 yields 27, 92, 9
13551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if 1
13561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int luminance = r * 27 + g * 92 + b * 9;
13571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        luminance >>= 15 - SkScalerContext::kLuminance_Bits;
13581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
13591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        int luminance = r * 2 + g * 5 + b * 1;
13601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        luminance >>= 11 - SkScalerContext::kLuminance_Bits;
13611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
13621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkASSERT(luminance <= SkScalerContext::kLuminance_Max);
13631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return luminance;
13641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
13651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // if we're not a single color, return the middle of the luminance range
13661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkScalerContext::kLuminance_Max >> 1;
13671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
13684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
13691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// Beyond this size, LCD doesn't appreciably improve quality, but it always
13711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger// cost more RAM and draws slower, so we set a cap.
13721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifndef SK_MAX_SIZE_FOR_LCDTEXT
13731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #define SK_MAX_SIZE_FOR_LCDTEXT    48
13741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
13751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool tooBigForLCD(const SkScalerContext::Rec& rec) {
13771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar area = SkScalarMul(rec.fPost2x2[0][0], rec.fPost2x2[1][1]) -
13781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    SkScalarMul(rec.fPost2x2[1][0], rec.fPost2x2[0][1]);
13791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkScalar size = SkScalarMul(area, rec.fTextSize);
13801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return SkScalarAbs(size) > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
13811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
13821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
138340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/*
138440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger *  Return the scalar with only limited fractional precision. Used to consolidate matrices
138540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger *  that vary only slightly when we create our key into the font cache, since the font scaler
138640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger *  typically returns the same looking resuts for tiny changes in the matrix.
138740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */
138840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic SkScalar sk_relax(SkScalar x) {
138940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#ifdef SK_SCALAR_IS_FLOAT
139040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int n = sk_float_round2int(x * 1024);
139140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return n / 1024.0f;
139240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#else
139340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // round to the nearest 10 fractional bits
139440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return (x + (1 << 5)) & ~(1024 - 1);
139540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif
139640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
139740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1398af2616552738d653d5453915d3236e7154b868cdMike Reedvoid SkScalerContext::MakeRec(const SkPaint& paint,
139940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                              const SkMatrix* deviceMatrix, Rec* rec) {
14000199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger    SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
14010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14020199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger    rec->fOrigFontID = SkTypeface::UniqueID(paint.getTypeface());
14030199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger    rec->fFontID = rec->fOrigFontID;
14040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec->fTextSize = paint.getTextSize();
14050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec->fPreScaleX = paint.getTextScaleX();
14060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec->fPreSkewX  = paint.getTextSkewX();
14070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
140840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (deviceMatrix) {
140940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
141040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
141140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
141240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
141340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
14140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
14150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
14160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
141740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint::Style  style = paint.getStyle();
14190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        strokeWidth = paint.getStrokeWidth();
142040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    unsigned flags = 0;
14221c980e0d7772f05f570ae0227d91635f017c2227Mike Reed
142340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isFakeBoldText()) {
14241c980e0d7772f05f570ae0227d91635f017c2227Mike Reed#ifdef SK_USE_FREETYPE_EMBOLDEN
14251c980e0d7772f05f570ae0227d91635f017c2227Mike Reed        flags |= SkScalerContext::kEmbolden_Flag;
14261c980e0d7772f05f570ae0227d91635f017c2227Mike Reed#else
142740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
142840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                    kStdFakeBoldInterpKeys,
142940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                    kStdFakeBoldInterpValues,
143040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                    kStdFakeBoldInterpLength);
14310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
143240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
143340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (style == SkPaint::kFill_Style) {
14340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            style = SkPaint::kStrokeAndFill_Style;
14350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
143640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else {
14370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            strokeWidth += extra;
143840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
14391c980e0d7772f05f570ae0227d91635f017c2227Mike Reed#endif
14400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
14410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
144240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isDevKernText()) {
14430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        flags |= SkScalerContext::kDevKernText_Flag;
144440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
144540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
144640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (style != SkPaint::kFill_Style && strokeWidth > 0) {
14470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fFrameWidth = strokeWidth;
14480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fMiterLimit = paint.getStrokeMiter();
14490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
14500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
145140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (style == SkPaint::kStrokeAndFill_Style) {
14520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            flags |= SkScalerContext::kFrameAndFill_Flag;
145340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
145440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
14550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fFrameWidth = 0;
14560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fMiterLimit = 0;
14570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec->fStrokeJoin = 0;
14580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
14590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
14610b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
14621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkMask::kLCD16_Format == rec->fMaskFormat ||
14631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkMask::kLCD32_Format == rec->fMaskFormat)
14641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    {
14650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder();
14660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        SkFontHost::LCDOrientation orient = SkFontHost::GetSubpixelOrientation();
14671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (SkFontHost::kNONE_LCDOrder == order || tooBigForLCD(*rec)) {
14680b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            // eeek, can't support LCD
14690b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            rec->fMaskFormat = SkMask::kA8_Format;
14700b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        } else {
14710b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            if (SkFontHost::kVertical_LCDOrientation == orient) {
14720b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                flags |= SkScalerContext::kLCD_Vertical_Flag;
14730b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            }
14740b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            if (SkFontHost::kBGR_LCDOrder == order) {
14750b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger                flags |= SkScalerContext::kLCD_BGROrder_Flag;
14760b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            }
14770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        }
14780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    }
14790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
148040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isEmbeddedBitmapText()) {
14810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
148240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
148340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isSubpixelText()) {
14840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        flags |= SkScalerContext::kSubpixelPositioning_Flag;
148540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
148640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.isAutohinted()) {
14870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        flags |= SkScalerContext::kAutohinting_Flag;
148840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
14891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (paint.isVerticalText()) {
14901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        flags |= SkScalerContext::kVertical_Flag;
14911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
14924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
14934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        flags |= SkScalerContext::kGenA8FromLCD_Flag;
14944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
14950b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    rec->fFlags = SkToU16(flags);
14960b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger
14971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // these modify fFlags, so do them after assigning fFlags
14980b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    rec->setHinting(computeHinting(paint));
14994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
15004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    rec->setLuminanceColor(computeLuminanceColor(paint));
15014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
15021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    rec->setLuminanceBits(computeLuminance(paint));
15034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
1504af2616552738d653d5453915d3236e7154b868cdMike Reed
1505af2616552738d653d5453915d3236e7154b868cdMike Reed    /*  Allow the fonthost to modify our rec before we use it as a key into the
1506af2616552738d653d5453915d3236e7154b868cdMike Reed        cache. This way if we're asking for something that they will ignore,
1507af2616552738d653d5453915d3236e7154b868cdMike Reed        they can modify our rec up front, so we don't create duplicate cache
1508af2616552738d653d5453915d3236e7154b868cdMike Reed        entries.
1509af2616552738d653d5453915d3236e7154b868cdMike Reed     */
1510af2616552738d653d5453915d3236e7154b868cdMike Reed    SkFontHost::FilterRec(rec);
15111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
15124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // be sure to call PostMakeRec(rec) before you actually use it!
15134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
15144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
15154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/**
15164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger *  We ensure that the rec is self-consistent and efficient (where possible)
15174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */
15184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkScalerContext::PostMakeRec(SkScalerContext::Rec* rec) {
15194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
15204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    /**
15214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger     *  If we're asking for A8, we force the colorlum to be gray, since that
15224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger     *  that limits the number of unique entries, and the scaler will only
15234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger     *  look at the lum of one of them.
15244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger     */
15254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    switch (rec->fMaskFormat) {
15264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkMask::kLCD16_Format:
15274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkMask::kLCD32_Format: {
15284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
15294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // filter down the luminance color to a finite number of bits
15304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkColor c = rec->getLuminanceColor();
15314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            c = SkColorSetRGB(reduce_lumbits(SkColorGetR(c)),
15324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              reduce_lumbits(SkColorGetG(c)),
15334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                              reduce_lumbits(SkColorGetB(c)));
15344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            rec->setLuminanceColor(c);
15354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
15364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
15374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
15384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkMask::kA8_Format: {
15394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
15404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // filter down the luminance to a single component, since A8 can't
15414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // use per-component information
15424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            unsigned lum = computeLuminance(rec->getLuminanceColor());
15434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // reduce to our finite number of bits
15444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            lum = reduce_lumbits(lum);
15454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            rec->setLuminanceColor(SkColorSetRGB(lum, lum, lum));
15464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
15474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
15484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
15494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        case SkMask::kBW_Format:
15504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            // No need to differentiate gamma if we're BW
15514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
15524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            rec->setLuminanceColor(0);
15534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
15544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            rec->setLuminanceBits(0);
15554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
15564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            break;
15571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
15580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
15590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define MIN_SIZE_FOR_EFFECT_BUFFER  1024
15610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
156235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#ifdef SK_DEBUG
156335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    #define TEST_DESC
156435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#endif
156535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
15661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
15671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  ignoreGamma tells us that the caller just wants metrics that are unaffected
15681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  by gamma correction, so we jam the luminance field to 0 (most common value
15691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  for black text) in hopes that we get a cache hit easier. A better solution
15701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  would be for the fontcache lookup to know to ignore the luminance field
15711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *  entirely, but not sure how to do that and keep it fast.
15721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
15730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
15740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                             void (*proc)(const SkDescriptor*, void*),
157540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                             void* context, bool ignoreGamma) const {
15760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalerContext::Rec    rec;
15770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
1579fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    if (ignoreGamma) {
15804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_USE_COLOR_LUMINANCE
15814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        rec.setLuminanceColor(0);
15824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else
15831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rec.setLuminanceBits(0);
15844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
1585fda149e38309f3ee38b172a9997cfee5dbccc32aRomain Guy    }
15860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t          descSize = sizeof(rec);
15880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int             entryCount = 1;
15890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPathEffect*   pe = this->getPathEffect();
15900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkMaskFilter*   mf = this->getMaskFilter();
15910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRasterizer*   ra = this->getRasterizer();
15920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFlattenableWriteBuffer    peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
15940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFlattenableWriteBuffer    mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
15950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFlattenableWriteBuffer    raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
15960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
15970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (pe) {
15980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        peBuffer.writeFlattenable(pe);
15990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        descSize += peBuffer.size();
16000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        entryCount += 1;
16010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
16020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // seems like we could support kLCD as well at this point...
16030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (mf) {
16050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        mfBuffer.writeFlattenable(mf);
16060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        descSize += mfBuffer.size();
16070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        entryCount += 1;
16080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing with maskfilters
16090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (ra) {
16110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        raBuffer.writeFlattenable(ra);
16120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        descSize += raBuffer.size();
16130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        entryCount += 1;
16140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec.fMaskFormat = SkMask::kA8_Format;   // force antialiasing when we do the scan conversion
16150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    ///////////////////////////////////////////////////////////////////////////
16184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    // Now that we're done tweaking the rec, call the PostMakeRec cleanup
16194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkScalerContext::PostMakeRec(&rec);
16204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
16210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    descSize += SkDescriptor::ComputeOverhead(entryCount);
16220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoDescriptor    ad(descSize);
16240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDescriptor*       desc = ad.getDesc();
16250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    desc->init();
16270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
16280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (pe) {
16300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
16310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (mf) {
16330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
16340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (ra) {
16360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
16370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
16380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(descSize == desc->getLength());
16400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    desc->computeChecksum();
16410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
164235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#ifdef TEST_DESC
164335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    {
164435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // Check that we completely write the bytes in desc (our key), and that
164535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // there are no uninitialized bytes. If there were, then we would get
164635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // false-misses (or worse, false-hits) in our fontcache.
164735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        //
164835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // We do this buy filling 2 others, one with 0s and the other with 1s
164935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        // and create those, and then check that all 3 are identical.
165035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkAutoDescriptor    ad1(descSize);
165135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkAutoDescriptor    ad2(descSize);
165235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkDescriptor*       desc1 = ad1.getDesc();
165335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkDescriptor*       desc2 = ad2.getDesc();
165435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
165535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        memset(desc1, 0x00, descSize);
165635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        memset(desc2, 0xFF, descSize);
165735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
165835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc1->init();
165935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc2->init();
166035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
166135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
166235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
166335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (pe) {
166435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
166535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
166635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
166735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (mf) {
166835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
166935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
167035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
167135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (ra) {
167235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
167335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
167435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
167535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
167635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkASSERT(descSize == desc1->getLength());
167735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkASSERT(descSize == desc2->getLength());
167835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc1->computeChecksum();
167935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        desc2->computeChecksum();
168035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkASSERT(!memcmp(desc, desc1, descSize));
168135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkASSERT(!memcmp(desc, desc2, descSize));
168235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
168335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#endif
168435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
16850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    proc(desc, context);
16860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
16870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
168840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const {
16890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache* cache;
16900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
16910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return cache;
16920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
16930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
16950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStream.h"
16970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
16985f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic uintptr_t asint(const void* p) {
16995f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    return reinterpret_cast<uintptr_t>(p);
17005f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed}
17015f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17025f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedunion Scalar32 {
17035f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkScalar    fScalar;
17045f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint32_t    f32;
17055f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed};
17065f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17075f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
17085f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
17095f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    Scalar32 tmp;
17105f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    tmp.fScalar = value;
17115f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    *ptr = tmp.f32;
17125f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    return ptr + 1;
17135f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed}
17145f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17155f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic SkScalar read_scalar(const uint32_t*& ptr) {
17165f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
17175f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    Scalar32 tmp;
17185f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    tmp.f32 = *ptr++;
17195f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    return tmp.fScalar;
17205f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed}
17215f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17225f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
17235f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(a == (uint8_t)a);
17245f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(b == (uint8_t)b);
17255f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(c == (uint8_t)c);
17265f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(d == (uint8_t)d);
17275f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    return (a << 24) | (b << 16) | (c << 8) | d;
17285f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed}
17295f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17305f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedenum FlatFlags {
17315f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    kHasTypeface_FlatFlag   = 0x01,
17325f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    kHasEffects_FlatFlag    = 0x02
17335f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed};
17345f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17355f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed// The size of a flat paint's POD fields
17365f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reedstatic const uint32_t kPODPaintSize =   5 * sizeof(SkScalar) +
17375f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed                                        1 * sizeof(SkColor) +
17385f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed                                        1 * sizeof(uint16_t) +
17395f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed                                        6 * sizeof(uint8_t);
17405f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17415f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed/*  To save space/time, we analyze the paint, and write a truncated version of
17425f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    it if there are not tricky elements like shaders, etc.
17435f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed */
17440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
17455f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint8_t flatFlags = 0;
17465f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (this->getTypeface()) {
17475f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        flatFlags |= kHasTypeface_FlatFlag;
17485f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
17495f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (asint(this->getPathEffect()) |
17505f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getShader()) |
17515f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getXfermode()) |
17525f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getMaskFilter()) |
17535f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getColorFilter()) |
17545f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        asint(this->getRasterizer()) |
17551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        asint(this->getLooper()) |
17561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        asint(this->getImageFilter())) {
17575f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        flatFlags |= kHasEffects_FlatFlag;
17585f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
175940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
17605f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
17615f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint32_t* ptr = buffer.reserve(kPODPaintSize);
17625f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17635f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getTextSize());
17645f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getTextScaleX());
17655f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getTextSkewX());
17665f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getStrokeWidth());
17675f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    ptr = write_scalar(ptr, this->getStrokeMiter());
17685f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    *ptr++ = this->getColor();
17691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // previously flags:16, textAlign:8, flatFlags:8
17701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // now flags:16, hinting:4, textAlign:4, flatFlags:8
17711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *ptr++ = (this->getFlags() << 16) |
17721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             // hinting added later. 0 in this nibble means use the default.
17731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             ((this->getHinting()+1) << 12) |
17741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             (this->getTextAlign() << 8) |
17751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger             flatFlags;
17765f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
17775f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed                    this->getStyle(), this->getTextEncoding());
17785f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
17795f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    // now we're done with ptr and the (pre)reserved space. If we need to write
17805f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    // additional fields, use the buffer directly
17815f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (flatFlags & kHasTypeface_FlatFlag) {
17825f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeTypeface(this->getTypeface());
17835f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
17845f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (flatFlags & kHasEffects_FlatFlag) {
17855f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getPathEffect());
17865f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getShader());
17875f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getXfermode());
17885f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getMaskFilter());
17895f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getColorFilter());
17905f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getRasterizer());
17915f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        buffer.writeFlattenable(this->getLooper());
17921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        buffer.writeFlattenable(this->getImageFilter());
17935f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
17940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
17950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
17960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
17975f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
17985f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    const void* podData = buffer.skip(kPODPaintSize);
17995f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
180040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
18015f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    // the order we read must match the order we wrote in flatten()
18025f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setTextSize(read_scalar(pod));
18035f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setTextScaleX(read_scalar(pod));
18045f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setTextSkewX(read_scalar(pod));
18055f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setStrokeWidth(read_scalar(pod));
180640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    this->setStrokeMiter(read_scalar(pod));
18075f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setColor(*pod++);
18085f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // previously flags:16, textAlign:8, flatFlags:8
18101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // now flags:16, hinting:4, textAlign:4, flatFlags:8
18115f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint32_t tmp = *pod++;
18125f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setFlags(tmp >> 16);
18131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (buffer.getPictureVersion() == PICTURE_VERSION_ICS) {
18154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
18164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        this->setHinting(SkPaintDefaults_Hinting);
18174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    } else {
18184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // hinting added later. 0 in this nibble means use the default.
18194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        uint32_t hinting = (tmp >> 12) & 0xF;
18204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        this->setHinting(0 == hinting ? kNormal_Hinting : static_cast<Hinting>(hinting-1));
18211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
18234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
18241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
18255f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    uint8_t flatFlags = tmp & 0xFF;
18265f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18275f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    tmp = *pod++;
18285f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
18295f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
18305f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
18315f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
18325f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18335f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (flatFlags & kHasTypeface_FlatFlag) {
18345f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setTypeface(buffer.readTypeface());
18355f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    } else {
18365f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setTypeface(NULL);
18375f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
18385f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed
18395f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    if (flatFlags & kHasEffects_FlatFlag) {
184040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setPathEffect((SkPathEffect*) buffer.readFlattenable()));
184140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setShader((SkShader*) buffer.readFlattenable()));
184240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setXfermode((SkXfermode*) buffer.readFlattenable()));
184340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable()));
184440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setColorFilter((SkColorFilter*) buffer.readFlattenable()));
184540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setRasterizer((SkRasterizer*) buffer.readFlattenable()));
184640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkSafeUnref(this->setLooper((SkDrawLooper*) buffer.readFlattenable()));
18474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (buffer.getPictureVersion() != PICTURE_VERSION_ICS)
18484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            SkSafeUnref(this->setImageFilter((SkImageFilter*) buffer.readFlattenable()));
18494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        else
18504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            this->setImageFilter(NULL);
18515f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    } else {
18525f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setPathEffect(NULL);
18535f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setShader(NULL);
18545f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setXfermode(NULL);
18555f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setMaskFilter(NULL);
18565f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setColorFilter(NULL);
18575f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setRasterizer(NULL);
18585f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed        this->setLooper(NULL);
18591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        this->setImageFilter(NULL);
18605f6af4c62d33f128b6617fa4a038f309627a14d0Mike Reed    }
18610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
18620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
18630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
18640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
186587b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkShader* SkPaint::setShader(SkShader* shader) {
186687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(shader != fShader);
18670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fShader, shader);
18680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return shader;
18690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
18700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
187187b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
187287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(filter != fColorFilter);
18730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fColorFilter, filter);
18740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return filter;
18750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
18760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
187787b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
187887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(mode != fXfermode);
18790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fXfermode, mode);
18800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return mode;
18810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
18820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
188303f42ddd729377f21719a140c027a1f8cc5c2152Mike ReedSkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
188403f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed    SkSafeUnref(fXfermode);
188503f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed    fXfermode = SkXfermode::Create(mode);
188687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC;
188703f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed    return fXfermode;
188803f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed}
188903f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed
189087b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
189187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(effect != fPathEffect);
18920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fPathEffect, effect);
18930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return effect;
18940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
18950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
189687b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
189787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger    GEN_ID_INC_EVAL(filter != fMaskFilter);
18980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRefCnt_SafeAssign(fMaskFilter, filter);
18990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return filter;
19000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
190240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
19030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
190440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerbool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
19050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPath          effectPath, strokePath;
19060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkPath*   path = &src;
19070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
19080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar width = this->getStrokeWidth();
190940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
19100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (this->getStyle()) {
191140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        case SkPaint::kFill_Style:
19120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = -1; // mark it as no-stroke
191340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            break;
191440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        case SkPaint::kStrokeAndFill_Style:
191540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (width == 0) {
191640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                width = -1; // mark it as no-stroke
191740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
191840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            break;
191940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        case SkPaint::kStroke_Style:
192040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            break;
192140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        default:
19221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown paint style");
19230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
19240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
192540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (this->getPathEffect()) {
19260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
192740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->getStyle() == SkPaint::kStrokeAndFill_Style) {
19280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = -1; // mark it as no-stroke
192940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
19300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
193140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->getPathEffect()->filterPath(&effectPath, src, &width)) {
19320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            path = &effectPath;
193340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
193440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
19350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // restore the width if we earlier had to lie, and if we're still set to no-stroke
19360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
19370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // and we want to respect that (i.e. don't overwrite their setting for width)
193840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) {
19390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = this->getStrokeWidth();
194040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (width == 0) {
19410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                width = -1;
194240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
19430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
19440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
194540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
194640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (width > 0 && !path->isEmpty()) {
19470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkStroke stroker(*this, width);
19480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        stroker.strokePath(*path, &strokePath);
19490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        path = &strokePath;
19500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
19510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
195240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (path == &src) {
19530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst = src;
195440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
19550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(path == &effectPath || path == &strokePath);
19560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dst->swap(*(SkPath*)path);
19570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
19580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
19590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return width != 0;  // return true if we're filled, or false if we're hairline (width == 0)
19600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1962717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenbergerconst SkRect& SkPaint::doComputeFastBounds(const SkRect& src,
1963717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                                                 SkRect* storage) const {
19640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(storage);
1965717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
1966717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    if (this->getLooper()) {
1967717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        SkASSERT(this->getLooper()->canComputeFastBounds(*this));
1968717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        this->getLooper()->computeFastBounds(*this, src, storage);
1969717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        return *storage;
1970717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    }
1971717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
1972717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    if (this->getStyle() != SkPaint::kFill_Style) {
1973717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        // since we're stroked, outset the rect by the radius (and join type)
1974717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        SkScalar radius = SkScalarHalf(this->getStrokeWidth());
1975717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        if (0 == radius) {  // hairline
1976717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            radius = SK_Scalar1;
1977717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
1978717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            SkScalar scale = this->getStrokeMiter();
1979717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            if (scale > SK_Scalar1) {
1980717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                radius = SkScalarMul(radius, scale);
1981717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            }
19820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1983717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        storage->set(src.fLeft - radius, src.fTop - radius,
1984717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                     src.fRight + radius, src.fBottom + radius);
1985717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    } else {
1986717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        *storage = src;
19870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1988717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
1989717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    // check the mask filter
1990717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    if (this->getMaskFilter()) {
1991717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        this->getMaskFilter()->computeFastBounds(*storage, storage);
1992717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    }
1993717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
199435d15937afb7f4b3472e43ea784b02485ec910fbMike Reed    return *storage;
19950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
19960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
199740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger///////////////////////////////////////////////////////////////////////////////
19980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
199940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic bool has_thick_frame(const SkPaint& paint) {
200040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    return  paint.getStrokeWidth() > 0 &&
200140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            paint.getStyle() != SkPaint::kFill_Style;
20020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
20030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
20050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    const SkPaint& paint,
20060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    bool applyStrokeAndPathEffects,
200740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                    bool forceLinearTextOn) : fPaint(paint) {
20080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
20090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                true);
20100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
201140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (forceLinearTextOn) {
20120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint.setLinearText(true);
201340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
20140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPaint.setMaskFilter(NULL);   // don't want this affecting our path-cache lookup
20150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
201640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
20170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        applyStrokeAndPathEffects = false;
201840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
20190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // can't use our canonical size if we need to apply patheffects/strokes
202140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (fPaint.isLinearText() && !applyStrokeAndPathEffects) {
20220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
20230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
202440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else {
20250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fScale = SK_Scalar1;
202640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
202740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
202840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (!applyStrokeAndPathEffects) {
20290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint.setStyle(SkPaint::kFill_Style);
20300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPaint.setPathEffect(NULL);
20310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
20320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fCache = fPaint.detachCache(NULL);
20340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPaint::Style  style = SkPaint::kFill_Style;
20360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPathEffect*   pe = NULL;
20370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
203840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (!applyStrokeAndPathEffects) {
20390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        style = paint.getStyle();   // restore
20400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        pe = paint.getPathEffect();     // restore
20410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
20420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPaint.setStyle(style);
20430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPaint.setPathEffect(pe);
20440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPaint.setMaskFilter(paint.getMaskFilter());    // restore
20450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // now compute fXOffset if needed
20470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar xOffset = 0;
204940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
20500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int      count;
205140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
205240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                                                         &count, NULL), fScale);
205340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
20540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            width = SkScalarHalf(width);
205540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
20560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        xOffset = -width;
20570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
20580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fXPos = xOffset;
20590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPrevAdvance = 0;
20600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fText = text;
20620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fStop = text + length;
20631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
20641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    fXYIndex = paint.isVerticalText() ? 1 : 0;
20650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
20660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
206740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkTextToPathIter::~SkTextToPathIter() {
20680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkGlyphCache::AttachCache(fCache);
20690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
20700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
207140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerconst SkPath* SkTextToPathIter::next(SkScalar* xpos) {
207240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    while (fText < fStop) {
20730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
20740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
20750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
20761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fPrevAdvance = advance(glyph, fXYIndex);   // + fPaint.getTextTracking();
20770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
207840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (glyph.fWidth) {
207940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (xpos) {
20800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *xpos = fXPos;
208140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
20820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return fCache->findPath(glyph);
20830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
20840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
20850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return NULL;
20860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2087717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2088717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
2089717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
20901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkPaint::nothingToDraw() const {
20911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (fLooper) {
20921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
20931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
20941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkXfermode::Mode mode;
20951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkXfermode::AsMode(fXfermode, &mode)) {
20961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        switch (mode) {
20971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kSrcOver_Mode:
20981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kSrcATop_Mode:
20991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kDstOut_Mode:
21001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kDstOver_Mode:
21011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kPlus_Mode:
21021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                return 0 == this->getAlpha();
21031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            case SkXfermode::kDst_Mode:
21041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                return true;
21051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            default:
21061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                break;
21071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
21081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
21091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return false;
21101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
21111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger//////////// Move these to their own file soon.
21141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
21161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                const SkMatrix& ctm,
21171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                SkBitmap* result, SkIPoint* loc) {
21181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(proxy);
21191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(result);
21201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(loc);
21211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    /*
21221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     *  Give the proxy first shot at the filter. If it returns false, ask
21231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     *  the filter to do it.
21241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger     */
21251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return proxy->filterImage(this, src, ctm, result, loc) ||
21261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger           this->onFilterImage(proxy, src, ctm, result, loc);
21271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
21281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
21301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                 SkIRect* dst) {
21311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(&src);
21321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkASSERT(dst);
21331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return this->onFilterBounds(src, ctm, dst);
21341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
21351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
21371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  SkBitmap*, SkIPoint*) {
21381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return false;
21391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
21401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
21421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   SkIRect* dst) {
21431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    *dst = src;
21441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
21451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
21461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkImageFilter::asABlur(SkSize* sigma) const {
21481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return false;
21491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
21501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkImageFilter::asAnErode(SkISize* radius) const {
21524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return false;
21534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
21544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
21554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerbool SkImageFilter::asADilate(SkISize* radius) const {
21564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return false;
21574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
21584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
21594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger//////
21604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2161717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenbergerbool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) {
2162717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    SkCanvas canvas;
2163717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2164717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    this->init(&canvas);
2165717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    for (;;) {
2166717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        SkPaint p(paint);
2167717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        if (this->next(&canvas, &p)) {
2168717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            p.setLooper(NULL);
2169717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            if (!p.canComputeFastBounds()) {
2170717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                return false;
2171717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            }
2172717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        } else {
2173717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            break;
2174717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        }
2175717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    }
2176717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    return true;
2177717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger}
2178717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2179717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenbergervoid SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
2180717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                                     SkRect* dst) {
2181717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    SkCanvas canvas;
21824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2183717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    this->init(&canvas);
2184717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    for (bool firstTime = true;; firstTime = false) {
2185717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        SkPaint p(paint);
2186717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        if (this->next(&canvas, &p)) {
2187717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            SkRect r(src);
2188717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2189717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            p.setLooper(NULL);
2190717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            p.computeFastBounds(r, &r);
2191717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            canvas.getTotalMatrix().mapRect(&r);
2192717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger
2193717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            if (firstTime) {
2194717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                *dst = r;
2195717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            } else {
2196717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger                dst->join(r);
2197717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            }
2198717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        } else {
2199717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger            break;
2200717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger        }
2201717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger    }
2202717c009190af219a2f9e248d6fa13ad71cfdb0b1Derek Sollenberger}
22031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2204