summaryrefslogtreecommitdiffstats
path: root/WebKit/android/nav/FindCanvas.h
blob: 4ecbf37ed46ce5a41102e2d8a89be5da55f5de43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
 * Copyright 2008, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef Find_Canvas_h
#define Find_Canvas_h

#include "SkBounder.h"
#include "SkCanvas.h"
#include "SkPicture.h"
#include "SkRegion.h"
#include "SkTDArray.h"
#include "icu/unicode/umachine.h"

class SkRect;
class SkTypeface;

// Stores both region information and an SkPicture of the match, so that the
// region can be drawn, followed by drawing the matching text on top of it.
// This class owns its SkPicture
class MatchInfo {
public:
    MatchInfo();
    ~MatchInfo();
    MatchInfo(const MatchInfo& src);
    const SkRegion& getLocation() const { return m_location; }
    // Return a pointer to our picture, representing the matching text.  Does
    // not transfer ownership of the picture.
    SkPicture* getPicture() const { return m_picture; }
    // This will make a copy of the region, and increase the ref count on the
    // SkPicture.  If this MatchInfo already had one, unref it.
    void set(const SkRegion& region, SkPicture* pic);
private:
    MatchInfo& operator=(MatchInfo& src);
    SkRegion    m_location;
    SkPicture*  m_picture;
};

// A class containing a typeface for reference, the length in glyphs, and
// the upper and lower case representations of the search string.
class GlyphSet {
public:
    GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
            size_t byteLength);
    ~GlyphSet();
    GlyphSet& operator=(GlyphSet& src);

    // Return true iff c matches one of our glyph arrays at index
    bool characterMatches(uint16_t c, int index);
    
    int getCount() const { return mCount; }

    const SkTypeface* getTypeface() const { return mTypeface; }

private:
    // Disallow copy constructor
    GlyphSet(GlyphSet& src) { }

    // mTypeface is used for comparison only
    const SkTypeface* mTypeface;
    // mLowerGlyphs points to all of our storage space: the lower set followed
    // by the upper set.  mUpperGlyphs is purely a convenience pointer to the
    // start of the upper case glyphs.
    uint16_t*   mLowerGlyphs;
    uint16_t*   mUpperGlyphs;
    // mCount is the number of glyphs of the search string.  Must be the same
    // for both the lower case set and the upper case set.
    int         mCount;

    // Arbitrarily chose the maximum storage to use in the GlyphSet.  This is
    // based on the length of the word being searched.  If users are always
    // searching for 3 letter words (for example), an ideal number would be 3.
    // Each time the user searches for a word longer than (in this case, 3) that
    // will result in calling new/delete.
    enum Storage {
        MAX_STORAGE_COUNT = 16
    };
    // In order to eliminate new/deletes, create storage that will be enough
    // most of the time
    uint16_t    mStorage[2*MAX_STORAGE_COUNT];
};

class FindBounder : public SkBounder {
public:
    FindBounder() {}
    ~FindBounder() {}
protected:
    virtual bool onIRect(const SkIRect&) { return false; }
};

class FindCanvas : public SkCanvas {
public:
    FindCanvas(int width, int height, const UChar* , const UChar*,
            size_t byteLength);

    virtual ~FindCanvas();

    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
                          SkScalar y, const SkPaint& paint);

    /* FIXME: This path has not been tested. */
    virtual void drawPosText(const void* text, size_t byteLength,
                             const SkPoint pos[], const SkPaint& paint);

    /* Also untested */
    virtual void drawPosTextH(const void* text, size_t byteLength,
                              const SkScalar xpos[], SkScalar constY,
                              const SkPaint& paint);

    /* Not sure what to do here or for drawTextOnPathHV */
    virtual void drawTextOnPath(const void* text, size_t byteLength,
                                const SkPath& path, const SkMatrix* matrix,
                                const SkPaint& paint) {
    }

    int found() const { return mNumFound; }

    // This method detaches our array of matches and passes ownership to
    // the caller, who is then responsible for deleting them.
    WTF::Vector<MatchInfo>* detachMatches() {
        WTF::Vector<MatchInfo>* array = mMatches;
        mMatches = NULL;
        return array;
    }

private:
    // These calls are made by findHelper to store information about each match
    // that is found.  They return a rectangle which is used to highlight the
    // match.  They also add to our SkPicture (which can be accessed with
    // getDrawnMatches) a draw of each match.  This way it can be drawn after
    // the rectangle.  The rect that is returned is in device coordinates.
    SkRect addMatchNormal(int index,
        const SkPaint& paint, int count, const uint16_t* glyphs,
        const SkScalar pos[], SkScalar y);

    SkRect addMatchPos(int index,
        const SkPaint& paint, int count, const uint16_t* glyphs,
        const SkScalar xPos[], SkScalar /* y */);

    SkRect addMatchPosH(int index,
        const SkPaint& paint, int count, const uint16_t* glyphs,
        const SkScalar position[], SkScalar constY);

    // Helper for each of our draw calls
    void findHelper(const void* text, size_t byteLength, const SkPaint& paint,
                    const SkScalar xPos[], SkScalar y,
                    SkRect (FindCanvas::*addMatch)(int index,
                    const SkPaint& paint, int count, const uint16_t* glyphs,
                    const SkScalar pos[], SkScalar y));

    // If we already have a working canvas, grab it.  Otherwise, create a new
    // one.
    SkCanvas* getWorkingCanvas();

    // Return the set of glyphs and its count for the text being searched for
    // and the parameter paint.  If one has already been created and cached
    // for this paint, use it.  If not, create a new one and cache it.
    GlyphSet* getGlyphs(const SkPaint& paint);

    // Store all the accumulated info about a match in our vector.
    void insertMatchInfo(const SkRegion& region);

    // Throw away our cumulative information about our working SkCanvas.  After
    // this call, next call to getWorkingCanvas will create a new one.
    void resetWorkingCanvas();

    // Since we may transfer ownership of this array (see detachRects()), we
    // hold a pointer to the array instead of just the array itself.
    WTF::Vector<MatchInfo>* mMatches;
    const UChar*            mLowerText;
    const UChar*            mUpperText;
    size_t                  mLength;
    FindBounder             mBounder;
    int                     mNumFound;
    SkScalar                mOutset;
    SkTDArray<GlyphSet>     mGlyphSets;

    SkPicture*              mWorkingPicture;
    SkCanvas*               mWorkingCanvas;
    SkRegion                mWorkingRegion;
    int                     mWorkingIndex;
};

#endif  // Find_Canvas_h