• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2008, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef Find_Canvas_h
27 #define Find_Canvas_h
28 
29 #include "SkBounder.h"
30 #include "SkCanvas.h"
31 #include "SkPicture.h"
32 #include "SkRegion.h"
33 #include "SkTDArray.h"
34 #include "icu/unicode/umachine.h"
35 #include "wtf/Vector.h"
36 
37 class SkRect;
38 class SkTypeface;
39 
40 // Stores both region information and an SkPicture of the match, so that the
41 // region can be drawn, followed by drawing the matching text on top of it.
42 // This class owns its SkPicture
43 class MatchInfo {
44 public:
45     MatchInfo();
46     ~MatchInfo();
47     MatchInfo(const MatchInfo& src);
getLocation()48     const SkRegion& getLocation() const { return m_location; }
49     // Return a pointer to our picture, representing the matching text.  Does
50     // not transfer ownership of the picture.
getPicture()51     SkPicture* getPicture() const { return m_picture; }
52     // This will make a copy of the region, and increase the ref count on the
53     // SkPicture.  If this MatchInfo already had one, unref it.
54     void set(const SkRegion& region, SkPicture* pic);
55 private:
56     MatchInfo& operator=(MatchInfo& src);
57     SkRegion    m_location;
58     SkPicture*  m_picture;
59 };
60 
61 // A class containing a typeface for reference, the length in glyphs, and
62 // the upper and lower case representations of the search string.
63 class GlyphSet {
64 public:
65     GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
66             size_t byteLength);
67     ~GlyphSet();
68     GlyphSet& operator=(GlyphSet& src);
69 
70     // Return true iff c matches one of our glyph arrays at index
71     bool characterMatches(uint16_t c, int index);
72 
getCount()73     int getCount() const { return mCount; }
74 
getTypeface()75     const SkTypeface* getTypeface() const { return mTypeface; }
76 
77 private:
78     // Disallow copy constructor
GlyphSet(GlyphSet & src)79     GlyphSet(GlyphSet& src) { }
80 
81     // mTypeface is used for comparison only
82     const SkTypeface* mTypeface;
83     // mLowerGlyphs points to all of our storage space: the lower set followed
84     // by the upper set.  mUpperGlyphs is purely a convenience pointer to the
85     // start of the upper case glyphs.
86     uint16_t*   mLowerGlyphs;
87     uint16_t*   mUpperGlyphs;
88     // mCount is the number of glyphs of the search string.  Must be the same
89     // for both the lower case set and the upper case set.
90     int         mCount;
91 
92     // Arbitrarily chose the maximum storage to use in the GlyphSet.  This is
93     // based on the length of the word being searched.  If users are always
94     // searching for 3 letter words (for example), an ideal number would be 3.
95     // Each time the user searches for a word longer than (in this case, 3) that
96     // will result in calling new/delete.
97     enum Storage {
98         MAX_STORAGE_COUNT = 16
99     };
100     // In order to eliminate new/deletes, create storage that will be enough
101     // most of the time
102     uint16_t    mStorage[2*MAX_STORAGE_COUNT];
103 };
104 
105 class FindBounder : public SkBounder {
106 public:
FindBounder()107     FindBounder() {}
~FindBounder()108     ~FindBounder() {}
109 protected:
onIRect(const SkIRect &)110     virtual bool onIRect(const SkIRect&) { return false; }
111 };
112 
113 class FindCanvas : public SkCanvas {
114 public:
115     FindCanvas(int width, int height, const UChar* , const UChar*,
116             size_t byteLength);
117 
118     virtual ~FindCanvas();
119 
120     virtual void drawText(const void* text, size_t byteLength, SkScalar x,
121                           SkScalar y, const SkPaint& paint);
122 
123     /* FIXME: This path has not been tested. */
124     virtual void drawPosText(const void* text, size_t byteLength,
125                              const SkPoint pos[], const SkPaint& paint);
126 
127     /* Also untested */
128     virtual void drawPosTextH(const void* text, size_t byteLength,
129                               const SkScalar xpos[], SkScalar constY,
130                               const SkPaint& paint);
131 
132     /* Not sure what to do here or for drawTextOnPathHV */
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)133     virtual void drawTextOnPath(const void* text, size_t byteLength,
134                                 const SkPath& path, const SkMatrix* matrix,
135                                 const SkPaint& paint) {
136     }
137 
found()138     int found() const { return mNumFound; }
139 
140     // This method detaches our array of matches and passes ownership to
141     // the caller, who is then responsible for deleting them.
detachMatches()142     WTF::Vector<MatchInfo>* detachMatches() {
143         WTF::Vector<MatchInfo>* array = mMatches;
144         mMatches = NULL;
145         return array;
146     }
147 
148 private:
149     // These calls are made by findHelper to store information about each match
150     // that is found.  They return a rectangle which is used to highlight the
151     // match.  They also add to our SkPicture (which can be accessed with
152     // getDrawnMatches) a draw of each match.  This way it can be drawn after
153     // the rectangle.  The rect that is returned is in device coordinates.
154     SkRect addMatchNormal(int index,
155         const SkPaint& paint, int count, const uint16_t* glyphs,
156         const SkScalar pos[], SkScalar y);
157 
158     SkRect addMatchPos(int index,
159         const SkPaint& paint, int count, const uint16_t* glyphs,
160         const SkScalar xPos[], SkScalar /* y */);
161 
162     SkRect addMatchPosH(int index,
163         const SkPaint& paint, int count, const uint16_t* glyphs,
164         const SkScalar position[], SkScalar constY);
165 
166     // Helper for each of our draw calls
167     void findHelper(const void* text, size_t byteLength, const SkPaint& paint,
168                     const SkScalar xPos[], SkScalar y,
169                     SkRect (FindCanvas::*addMatch)(int index,
170                     const SkPaint& paint, int count, const uint16_t* glyphs,
171                     const SkScalar pos[], SkScalar y));
172 
173     // If we already have a working canvas, grab it.  Otherwise, create a new
174     // one.
175     SkCanvas* getWorkingCanvas();
176 
177     // Return the set of glyphs and its count for the text being searched for
178     // and the parameter paint.  If one has already been created and cached
179     // for this paint, use it.  If not, create a new one and cache it.
180     GlyphSet* getGlyphs(const SkPaint& paint);
181 
182     // Store all the accumulated info about a match in our vector.
183     void insertMatchInfo(const SkRegion& region);
184 
185     // Throw away our cumulative information about our working SkCanvas.  After
186     // this call, next call to getWorkingCanvas will create a new one.
187     void resetWorkingCanvas();
188 
189     // Since we may transfer ownership of this array (see detachRects()), we
190     // hold a pointer to the array instead of just the array itself.
191     WTF::Vector<MatchInfo>* mMatches;
192     const UChar*            mLowerText;
193     const UChar*            mUpperText;
194     size_t                  mLength;
195     FindBounder             mBounder;
196     int                     mNumFound;
197     SkScalar                mOutset;
198     SkTDArray<GlyphSet>     mGlyphSets;
199 
200     SkPicture*              mWorkingPicture;
201     SkCanvas*               mWorkingCanvas;
202     SkRegion                mWorkingRegion;
203     int                     mWorkingIndex;
204 };
205 
206 #endif  // Find_Canvas_h
207 
208