2 * Copyright 2008, The Android Open Source Project
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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 THE COPYRIGHT OWNER 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.
30 #include "SkBounder.h"
32 #include "SkPicture.h"
34 #include "SkTDArray.h"
35 #include "icu/unicode/umachine.h"
36 #include "wtf/Vector.h"
46 // Stores both region information and an SkPicture of the match, so that the
47 // region can be drawn, followed by drawing the matching text on top of it.
48 // This class owns its SkPicture
53 MatchInfo(const MatchInfo& src);
54 const SkRegion& getLocation() const { return m_location; }
55 // Return a pointer to our picture, representing the matching text. Does
56 // not transfer ownership of the picture.
57 SkPicture* getPicture() const { return m_picture; }
58 // This will make a copy of the region, and increase the ref count on the
59 // SkPicture. If this MatchInfo already had one, unref it.
60 bool isInLayer() const { return m_layerId >= 0; }
61 int layerId() const { return m_layerId; }
62 void set(const SkRegion& region, SkPicture* pic, int layerId);
64 MatchInfo& operator=(MatchInfo& src);
70 // A class containing a typeface for reference, the length in glyphs, and
71 // the upper and lower case representations of the search string.
74 GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
77 GlyphSet& operator=(GlyphSet& src);
79 // Return true iff c matches one of our glyph arrays at index
80 bool characterMatches(uint16_t c, int index);
82 int getCount() const { return mCount; }
84 const SkTypeface* getTypeface() const { return mTypeface; }
87 // Disallow copy constructor
88 GlyphSet(GlyphSet& src) { }
90 // mTypeface is used for comparison only
91 const SkTypeface* mTypeface;
92 // mLowerGlyphs points to all of our storage space: the lower set followed
93 // by the upper set. mUpperGlyphs is purely a convenience pointer to the
94 // start of the upper case glyphs.
95 uint16_t* mLowerGlyphs;
96 uint16_t* mUpperGlyphs;
97 // mCount is the number of glyphs of the search string. Must be the same
98 // for both the lower case set and the upper case set.
101 // Arbitrarily chose the maximum storage to use in the GlyphSet. This is
102 // based on the length of the word being searched. If users are always
103 // searching for 3 letter words (for example), an ideal number would be 3.
104 // Each time the user searches for a word longer than (in this case, 3) that
105 // will result in calling new/delete.
107 MAX_STORAGE_COUNT = 16
109 // In order to eliminate new/deletes, create storage that will be enough
111 uint16_t mStorage[2*MAX_STORAGE_COUNT];
114 class FindBounder : public SkBounder {
119 virtual bool onIRect(const SkIRect&) { return false; }
122 class FindCanvas : public SkCanvas {
124 FindCanvas(int width, int height, const UChar* , const UChar*,
127 virtual ~FindCanvas();
129 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
130 SkScalar y, const SkPaint& paint);
132 /* FIXME: This path has not been tested. */
133 virtual void drawPosText(const void* text, size_t byteLength,
134 const SkPoint pos[], const SkPaint& paint);
137 virtual void drawPosTextH(const void* text, size_t byteLength,
138 const SkScalar xpos[], SkScalar constY,
139 const SkPaint& paint);
141 /* Not sure what to do here or for drawTextOnPathHV */
142 virtual void drawTextOnPath(const void* text, size_t byteLength,
143 const SkPath& path, const SkMatrix* matrix,
144 const SkPaint& paint) {
147 void drawLayers(WebCore::LayerAndroid* );
148 int found() const { return mNumFound; }
149 void setLayerId(int layerId) { mLayerId = layerId; }
151 // This method detaches our array of matches and passes ownership to
152 // the caller, who is then responsible for deleting them.
153 WTF::Vector<MatchInfo>* detachMatches() {
154 WTF::Vector<MatchInfo>* array = mMatches;
160 // These calls are made by findHelper to store information about each match
161 // that is found. They return a rectangle which is used to highlight the
162 // match. They also add to our SkPicture (which can be accessed with
163 // getDrawnMatches) a draw of each match. This way it can be drawn after
164 // the rectangle. The rect that is returned is in device coordinates.
165 SkRect addMatchNormal(int index,
166 const SkPaint& paint, int count, const uint16_t* glyphs,
167 const SkScalar pos[], SkScalar y);
169 SkRect addMatchPos(int index,
170 const SkPaint& paint, int count, const uint16_t* glyphs,
171 const SkScalar xPos[], SkScalar /* y */);
173 SkRect addMatchPosH(int index,
174 const SkPaint& paint, int count, const uint16_t* glyphs,
175 const SkScalar position[], SkScalar constY);
177 // Helper for each of our draw calls
178 void findHelper(const void* text, size_t byteLength, const SkPaint& paint,
179 const SkScalar xPos[], SkScalar y,
180 SkRect (FindCanvas::*addMatch)(int index,
181 const SkPaint& paint, int count, const uint16_t* glyphs,
182 const SkScalar pos[], SkScalar y));
184 // If we already have a working canvas, grab it. Otherwise, create a new
186 SkCanvas* getWorkingCanvas();
188 // Return the set of glyphs and its count for the text being searched for
189 // and the parameter paint. If one has already been created and cached
190 // for this paint, use it. If not, create a new one and cache it.
191 GlyphSet* getGlyphs(const SkPaint& paint);
193 // Store all the accumulated info about a match in our vector.
194 void insertMatchInfo(const SkRegion& region);
196 // Throw away our cumulative information about our working SkCanvas. After
197 // this call, next call to getWorkingCanvas will create a new one.
198 void resetWorkingCanvas();
200 // Since we may transfer ownership of this array (see detachRects()), we
201 // hold a pointer to the array instead of just the array itself.
202 WTF::Vector<MatchInfo>* mMatches;
203 const UChar* mLowerText;
204 const UChar* mUpperText;
206 FindBounder mBounder;
209 SkTDArray<GlyphSet> mGlyphSets;
211 SkPicture* mWorkingPicture;
212 SkCanvas* mWorkingCanvas;
213 SkRegion mWorkingRegion;
222 m_hasCurrentLocation = false;
223 m_isFindPaintSetUp = false;
225 ~FindOnPage() { delete m_matches; }
226 void clearCurrentLocation() { m_hasCurrentLocation = false; }
227 WebCore::IntRect currentMatchBounds() const;
228 void drawLayer(SkCanvas* canvas, const WebCore::IntRect* vis, int layerId);
229 void findNext(bool forward);
230 void setMatches(WTF::Vector<MatchInfo>* matches);
232 void drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused);
233 void setUpFindPaint();
234 void storeCurrentMatchLocation();
235 WTF::Vector<MatchInfo>* m_matches;
236 // Stores the location of the current match.
237 SkIPoint m_currentMatchLocation;
238 // Tells whether the value in m_currentMatchLocation is valid.
239 bool m_hasCurrentLocation;
240 // Tells whether we have done the setup to draw the Find matches.
241 bool m_isFindPaintSetUp;
242 // Paint used to draw our Find matches.
244 // Paint used for the background of our Find matches.
245 SkPaint m_findBlurPaint;
246 unsigned m_findIndex;
249 #endif // Find_Canvas_h