C++程序  |  158行  |  5.81 KB

/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrStencilAndCoverTextContext_DEFINED
#define GrStencilAndCoverTextContext_DEFINED

#include "GrDrawTarget.h"
#include "GrStrokeInfo.h"
#include "SkDrawFilter.h"
#include "SkTextBlob.h"
#include "SkTHash.h"
#include "SkTInternalLList.h"
#include "SkTLList.h"
#include "batches/GrDrawPathBatch.h"

class GrAtlasTextContext;
class GrTextStrike;
class GrPath;
class SkSurfaceProps;

/*
 * This class implements text rendering using stencil and cover path rendering
 * (by the means of GrDrawTarget::drawPath).
 */
class GrStencilAndCoverTextContext {
public:
    static GrStencilAndCoverTextContext* Create();

    void drawText(GrContext*, GrDrawContext* dc,
                  const GrClip&,  const GrPaint&, const SkPaint&,
                  const SkMatrix& viewMatrix, const SkSurfaceProps&, const char text[],
                  size_t byteLength, SkScalar x,
                  SkScalar y, const SkIRect& clipBounds);
    void drawPosText(GrContext*, GrDrawContext*,
                     const GrClip&, const GrPaint&, const SkPaint&,
                     const SkMatrix& viewMatrix, const SkSurfaceProps&,
                     const char text[], size_t byteLength,
                     const SkScalar pos[], int scalarsPerPosition,
                     const SkPoint& offset, const SkIRect& clipBounds);
    void drawTextBlob(GrContext*, GrDrawContext*, const GrClip&, const SkPaint&,
                      const SkMatrix& viewMatrix, const SkSurfaceProps&, const SkTextBlob*,
                      SkScalar x, SkScalar y,
                      SkDrawFilter*, const SkIRect& clipBounds);

    virtual ~GrStencilAndCoverTextContext();

private:
    GrStencilAndCoverTextContext();

    bool canDraw(const SkPaint& skPaint, const SkMatrix&) {
        return this->internalCanDraw(skPaint);
    }

    bool internalCanDraw(const SkPaint&);

    void uncachedDrawTextBlob(GrContext*, GrDrawContext* dc,
                              const GrClip& clip, const SkPaint& skPaint,
                              const SkMatrix& viewMatrix,
                              const SkSurfaceProps&,
                              const SkTextBlob* blob,
                              SkScalar x, SkScalar y,
                              SkDrawFilter* drawFilter,
                              const SkIRect& clipBounds);

    class FallbackBlobBuilder;

    class TextRun {
    public:
        TextRun(const SkPaint& fontAndStroke);
        ~TextRun();

        void setText(const char text[], size_t byteLength, SkScalar x, SkScalar y);

        void setPosText(const char text[], size_t byteLength, const SkScalar pos[],
                        int scalarsPerPosition, const SkPoint& offset);

        void draw(GrContext*, GrDrawContext*, GrPipelineBuilder*, GrColor, const SkMatrix&,
                  const SkSurfaceProps&,
                  SkScalar x, SkScalar y, const SkIRect& clipBounds,
                  GrAtlasTextContext* fallbackTextContext, const SkPaint& originalSkPaint) const;

        void releaseGlyphCache() const;

        size_t computeSizeInCache() const;

    private:
        typedef GrDrawPathRangeBatch::InstanceData InstanceData;

        SkGlyphCache* getGlyphCache() const;
        GrPathRange* createGlyphs(GrContext*) const;
        void appendGlyph(const SkGlyph&, const SkPoint&, FallbackBlobBuilder*);

        GrStrokeInfo                     fStroke;
        SkPaint                          fFont;
        SkScalar                         fTextRatio;
        float                            fTextInverseRatio;
        bool                             fUsingRawGlyphPaths;
        GrUniqueKey                      fGlyphPathsKey;
        int                              fTotalGlyphCount;
        SkAutoTUnref<InstanceData>       fInstanceData;
        int                              fFallbackGlyphCount;
        SkAutoTUnref<const SkTextBlob>   fFallbackTextBlob;
        mutable SkGlyphCache*            fDetachedGlyphCache;
        mutable uint32_t                 fLastDrawnGlyphsID;
    };

    // Text blobs/caches.

    class TextBlob : public SkTLList<TextRun, 1> {
    public:
        typedef SkTArray<uint32_t, true> Key;

        static const Key& GetKey(const TextBlob* blob) { return blob->key(); }

        static uint32_t Hash(const Key& key) {
            SkASSERT(key.count() > 1); // 1-length keys should be using the blob-id hash map.
            return SkChecksum::Murmur3(key.begin(), sizeof(uint32_t) * key.count());
        }

        TextBlob(uint32_t blobId, const SkTextBlob* skBlob, const SkPaint& skPaint)
            : fKey(&blobId, 1) { this->init(skBlob, skPaint); }

        TextBlob(const Key& key, const SkTextBlob* skBlob, const SkPaint& skPaint)
            : fKey(key) {
            // 1-length keys are unterstood to be the blob id and must use the other constructor.
            SkASSERT(fKey.count() > 1);
            this->init(skBlob, skPaint);
        }

        const Key& key() const { return fKey; }

        size_t cpuMemorySize() const { return fCpuMemorySize; }

    private:
        void init(const SkTextBlob*, const SkPaint&);

        const SkSTArray<1, uint32_t, true>   fKey;
        size_t                               fCpuMemorySize;

        SK_DECLARE_INTERNAL_LLIST_INTERFACE(TextBlob);
    };

    const TextBlob& findOrCreateTextBlob(const SkTextBlob*, const SkPaint&);
    void purgeToFit(const TextBlob&);

    GrAtlasTextContext*                                       fFallbackTextContext;
    SkTHashMap<uint32_t, TextBlob*>                           fBlobIdCache;
    SkTHashTable<TextBlob*, const TextBlob::Key&, TextBlob>   fBlobKeyCache;
    SkTInternalLList<TextBlob>                                fLRUList;
    size_t                                                    fCacheSize;
};

#endif