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