| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 1 | /* | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 2 |  * Copyright (C) 2013 The Android Open Source Project | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 3 |  * | 
 | 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 5 |  * you may not use this file except in compliance with the License. | 
 | 6 |  * You may obtain a copy of the License at | 
 | 7 |  * | 
 | 8 |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 9 |  * | 
 | 10 |  * Unless required by applicable law or agreed to in writing, software | 
 | 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 | 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 13 |  * See the License for the specific language governing permissions and | 
 | 14 |  * limitations under the License. | 
 | 15 |  */ | 
 | 16 |  | 
| Romain Guy | 5b3b352 | 2010-10-27 18:57:51 -0700 | [diff] [blame] | 17 | #ifndef ANDROID_HWUI_PATH_CACHE_H | 
 | 18 | #define ANDROID_HWUI_PATH_CACHE_H | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 19 |  | 
| Chris Craik | 96a5c4c | 2015-01-27 15:46:35 -0800 | [diff] [blame] | 20 | #include "Debug.h" | 
 | 21 | #include "Texture.h" | 
 | 22 | #include "thread/Task.h" | 
 | 23 | #include "thread/TaskProcessor.h" | 
 | 24 | #include "utils/Macros.h" | 
 | 25 | #include "utils/Pair.h" | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 26 |  | 
| Chris Craik | 96a5c4c | 2015-01-27 15:46:35 -0800 | [diff] [blame] | 27 | #include <GLES2/gl2.h> | 
 | 28 | #include <SkPath.h> | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 29 | #include <utils/LruCache.h> | 
 | 30 | #include <utils/Mutex.h> | 
| Romain Guy | fe48f65 | 2010-11-11 15:36:56 -0800 | [diff] [blame] | 31 | #include <utils/Vector.h> | 
 | 32 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 33 | class SkBitmap; | 
 | 34 | class SkCanvas; | 
| Romain Guy | ca89e2a | 2013-03-08 17:44:20 -0800 | [diff] [blame] | 35 | class SkPaint; | 
| Chris Craik | 564acf7 | 2014-01-02 16:46:18 -0800 | [diff] [blame] | 36 | struct SkRect; | 
| Romain Guy | ff26a0c | 2011-01-20 11:35:46 -0800 | [diff] [blame] | 37 |  | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 38 | namespace android { | 
 | 39 | namespace uirenderer { | 
 | 40 |  | 
| Romain Guy | ca89e2a | 2013-03-08 17:44:20 -0800 | [diff] [blame] | 41 | class Caches; | 
 | 42 |  | 
| Romain Guy | 9e10841 | 2010-11-09 14:35:20 -0800 | [diff] [blame] | 43 | /////////////////////////////////////////////////////////////////////////////// | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 44 | // Defines | 
 | 45 | /////////////////////////////////////////////////////////////////////////////// | 
 | 46 |  | 
 | 47 | // Debug | 
 | 48 | #if DEBUG_PATHS | 
 | 49 |     #define PATH_LOGD(...) ALOGD(__VA_ARGS__) | 
 | 50 | #else | 
 | 51 |     #define PATH_LOGD(...) | 
 | 52 | #endif | 
 | 53 |  | 
 | 54 | /////////////////////////////////////////////////////////////////////////////// | 
| Romain Guy | 9e10841 | 2010-11-09 14:35:20 -0800 | [diff] [blame] | 55 | // Classes | 
 | 56 | /////////////////////////////////////////////////////////////////////////////// | 
 | 57 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 58 | /** | 
 | 59 |  * Alpha texture used to represent a path. | 
 | 60 |  */ | 
 | 61 | struct PathTexture: public Texture { | 
| Romain Guy | 8aa195d | 2013-06-04 18:00:09 -0700 | [diff] [blame] | 62 |     PathTexture(Caches& caches): Texture(caches) { | 
| Romain Guy | ff26a0c | 2011-01-20 11:35:46 -0800 | [diff] [blame] | 63 |     } | 
 | 64 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 65 |     ~PathTexture() { | 
 | 66 |         clearTask(); | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 67 |     } | 
 | 68 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 69 |     /** | 
 | 70 |      * Left coordinate of the path bounds. | 
 | 71 |      */ | 
 | 72 |     float left; | 
 | 73 |     /** | 
 | 74 |      * Top coordinate of the path bounds. | 
 | 75 |      */ | 
 | 76 |     float top; | 
 | 77 |     /** | 
 | 78 |      * Offset to draw the path at the correct origin. | 
 | 79 |      */ | 
 | 80 |     float offset; | 
 | 81 |  | 
 | 82 |     sp<Task<SkBitmap*> > task() const { | 
 | 83 |         return mTask; | 
| Romain Guy | 059e12c | 2012-11-28 17:35:51 -0800 | [diff] [blame] | 84 |     } | 
 | 85 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 86 |     void setTask(const sp<Task<SkBitmap*> >& task) { | 
 | 87 |         mTask = task; | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 88 |     } | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 89 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 90 |     void clearTask() { | 
| Chris Craik | e84a208 | 2014-12-22 14:28:49 -0800 | [diff] [blame] | 91 |         if (mTask != nullptr) { | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 92 |             mTask.clear(); | 
 | 93 |         } | 
 | 94 |     } | 
| Romain Guy | b29cfbf | 2011-03-18 16:24:19 -0700 | [diff] [blame] | 95 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 96 | private: | 
 | 97 |     sp<Task<SkBitmap*> > mTask; | 
 | 98 | }; // struct PathTexture | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 99 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 100 | enum ShapeType { | 
 | 101 |     kShapeNone, | 
 | 102 |     kShapeRect, | 
 | 103 |     kShapeRoundRect, | 
 | 104 |     kShapeCircle, | 
 | 105 |     kShapeOval, | 
 | 106 |     kShapeArc, | 
 | 107 |     kShapePath | 
 | 108 | }; | 
 | 109 |  | 
 | 110 | struct PathDescription { | 
| Chris Craik | 05f3d6e | 2014-06-02 16:27:04 -0700 | [diff] [blame] | 111 |     DESCRIPTION_TYPE(PathDescription); | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 112 |     ShapeType type; | 
 | 113 |     SkPaint::Join join; | 
 | 114 |     SkPaint::Cap cap; | 
 | 115 |     SkPaint::Style style; | 
 | 116 |     float miter; | 
 | 117 |     float strokeWidth; | 
 | 118 |     SkPathEffect* pathEffect; | 
 | 119 |     union Shape { | 
 | 120 |         struct Path { | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 121 |             const SkPath* mPath; | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 122 |         } path; | 
 | 123 |         struct RoundRect { | 
 | 124 |             float mWidth; | 
 | 125 |             float mHeight; | 
 | 126 |             float mRx; | 
 | 127 |             float mRy; | 
 | 128 |         } roundRect; | 
 | 129 |         struct Circle { | 
 | 130 |             float mRadius; | 
 | 131 |         } circle; | 
 | 132 |         struct Oval { | 
 | 133 |             float mWidth; | 
 | 134 |             float mHeight; | 
 | 135 |         } oval; | 
 | 136 |         struct Rect { | 
 | 137 |             float mWidth; | 
 | 138 |             float mHeight; | 
 | 139 |         } rect; | 
 | 140 |         struct Arc { | 
 | 141 |             float mWidth; | 
 | 142 |             float mHeight; | 
 | 143 |             float mStartAngle; | 
 | 144 |             float mSweepAngle; | 
 | 145 |             bool mUseCenter; | 
 | 146 |         } arc; | 
 | 147 |     } shape; | 
 | 148 |  | 
 | 149 |     PathDescription(); | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 150 |     PathDescription(ShapeType shapeType, const SkPaint* paint); | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 151 |  | 
 | 152 |     hash_t hash() const; | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 153 | }; | 
| Romain Guy | 059e12c | 2012-11-28 17:35:51 -0800 | [diff] [blame] | 154 |  | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 155 | /** | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 156 |  * A simple LRU shape cache. The cache has a maximum size expressed in bytes. | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 157 |  * Any texture added to the cache causing the cache to grow beyond the maximum | 
 | 158 |  * allowed size will also cause the oldest texture to be kicked out. | 
 | 159 |  */ | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 160 | class PathCache: public OnEntryRemoved<PathDescription, PathTexture*> { | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 161 | public: | 
| Romain Guy | fb8b763 | 2010-08-23 21:05:08 -0700 | [diff] [blame] | 162 |     PathCache(); | 
| Romain Guy | ca89e2a | 2013-03-08 17:44:20 -0800 | [diff] [blame] | 163 |     ~PathCache(); | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 164 |  | 
 | 165 |     /** | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 166 |      * Used as a callback when an entry is removed from the cache. | 
 | 167 |      * Do not invoke directly. | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 168 |      */ | 
| Chris Craik | e84a208 | 2014-12-22 14:28:49 -0800 | [diff] [blame] | 169 |     void operator()(PathDescription& path, PathTexture*& texture) override; | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 170 |  | 
 | 171 |     /** | 
 | 172 |      * Clears the cache. This causes all textures to be deleted. | 
 | 173 |      */ | 
 | 174 |     void clear(); | 
 | 175 |  | 
 | 176 |     /** | 
 | 177 |      * Sets the maximum size of the cache in bytes. | 
 | 178 |      */ | 
 | 179 |     void setMaxSize(uint32_t maxSize); | 
 | 180 |     /** | 
 | 181 |      * Returns the maximum size of the cache in bytes. | 
 | 182 |      */ | 
 | 183 |     uint32_t getMaxSize(); | 
 | 184 |     /** | 
 | 185 |      * Returns the current size of the cache in bytes. | 
 | 186 |      */ | 
 | 187 |     uint32_t getSize(); | 
 | 188 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 189 |     PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint); | 
 | 190 |     PathTexture* getCircle(float radius, const SkPaint* paint); | 
 | 191 |     PathTexture* getOval(float width, float height, const SkPaint* paint); | 
 | 192 |     PathTexture* getRect(float width, float height, const SkPaint* paint); | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 193 |     PathTexture* getArc(float width, float height, float startAngle, float sweepAngle, | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 194 |             bool useCenter, const SkPaint* paint); | 
 | 195 |     PathTexture* get(const SkPath* path, const SkPaint* paint); | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 196 |  | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 197 |     /** | 
| Romain Guy | fe48f65 | 2010-11-11 15:36:56 -0800 | [diff] [blame] | 198 |      * Removes the specified path. This is meant to be called from threads | 
 | 199 |      * that are not the EGL context thread. | 
 | 200 |      */ | 
 | 201 |     void removeDeferred(SkPath* path); | 
 | 202 |     /** | 
 | 203 |      * Process deferred removals. | 
 | 204 |      */ | 
 | 205 |     void clearGarbage(); | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 206 |     /** | 
 | 207 |      * Trims the contents of the cache, removing items until it's under its | 
 | 208 |      * specified limit. | 
 | 209 |      * | 
 | 210 |      * Trimming is used for caches that support pre-caching from a worker | 
 | 211 |      * thread. During pre-caching the maximum limit of the cache can be | 
 | 212 |      * exceeded for the duration of the frame. It is therefore required to | 
 | 213 |      * trim the cache at the end of the frame to keep the total amount of | 
 | 214 |      * memory used under control. | 
 | 215 |      */ | 
 | 216 |     void trim(); | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 217 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 218 |     /** | 
 | 219 |      * Precaches the specified path using background threads. | 
 | 220 |      */ | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 221 |     void precache(const SkPath* path, const SkPaint* paint); | 
| Romain Guy | ca89e2a | 2013-03-08 17:44:20 -0800 | [diff] [blame] | 222 |  | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 223 |     static bool canDrawAsConvexPath(SkPath* path, const SkPaint* paint); | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 224 |     static void computePathBounds(const SkPath* path, const SkPaint* paint, | 
 | 225 |             float& left, float& top, float& offset, uint32_t& width, uint32_t& height); | 
 | 226 |     static void computeBounds(const SkRect& bounds, const SkPaint* paint, | 
 | 227 |             float& left, float& top, float& offset, uint32_t& width, uint32_t& height); | 
 | 228 |  | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 229 | private: | 
| Romain Guy | c5cbee7 | 2013-03-20 19:15:02 -0700 | [diff] [blame] | 230 |     typedef Pair<SkPath*, SkPath*> path_pair_t; | 
 | 231 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 232 |     PathTexture* addTexture(const PathDescription& entry, | 
 | 233 |             const SkPath *path, const SkPaint* paint); | 
 | 234 |     PathTexture* addTexture(const PathDescription& entry, SkBitmap* bitmap); | 
| Romain Guy | 4500a8d | 2013-03-26 17:29:51 -0700 | [diff] [blame] | 235 |  | 
 | 236 |     /** | 
 | 237 |      * Generates the texture from a bitmap into the specified texture structure. | 
 | 238 |      */ | 
 | 239 |     void generateTexture(SkBitmap& bitmap, Texture* texture); | 
 | 240 |     void generateTexture(const PathDescription& entry, SkBitmap* bitmap, PathTexture* texture, | 
 | 241 |             bool addToCache = true); | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 242 |  | 
 | 243 |     PathTexture* get(const PathDescription& entry) { | 
 | 244 |         return mCache.get(entry); | 
 | 245 |     } | 
 | 246 |  | 
 | 247 |     /** | 
| Romain Guy | c5cbee7 | 2013-03-20 19:15:02 -0700 | [diff] [blame] | 248 |      * Removes an entry. | 
 | 249 |      * The pair must define first=path, second=sourcePath | 
 | 250 |      */ | 
| Romain Guy | e3b0a01 | 2013-06-26 15:45:41 -0700 | [diff] [blame] | 251 |     void remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair); | 
| Romain Guy | c5cbee7 | 2013-03-20 19:15:02 -0700 | [diff] [blame] | 252 |  | 
 | 253 |     /** | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 254 |      * Ensures there is enough space in the cache for a texture of the specified | 
 | 255 |      * dimensions. | 
 | 256 |      */ | 
 | 257 |     void purgeCache(uint32_t width, uint32_t height); | 
 | 258 |  | 
 | 259 |     void removeTexture(PathTexture* texture); | 
 | 260 |  | 
 | 261 |     bool checkTextureSize(uint32_t width, uint32_t height) { | 
 | 262 |         if (width > mMaxTextureSize || height > mMaxTextureSize) { | 
 | 263 |             ALOGW("Shape too large to be rendered into a texture (%dx%d, max=%dx%d)", | 
 | 264 |                     width, height, mMaxTextureSize, mMaxTextureSize); | 
 | 265 |             return false; | 
 | 266 |         } | 
 | 267 |         return true; | 
 | 268 |     } | 
 | 269 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 270 |     void init(); | 
 | 271 |  | 
| Romain Guy | 5dc7fa7 | 2013-03-11 20:48:31 -0700 | [diff] [blame] | 272 |     class PathTask: public Task<SkBitmap*> { | 
| Romain Guy | ca89e2a | 2013-03-08 17:44:20 -0800 | [diff] [blame] | 273 |     public: | 
| Chris Craik | d218a92 | 2014-01-02 17:13:34 -0800 | [diff] [blame] | 274 |         PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture): | 
| Chris Craik | 906d47f | 2014-06-27 18:30:23 -0700 | [diff] [blame] | 275 |             path(*path), paint(*paint), texture(texture) { | 
| Romain Guy | 5dc7fa7 | 2013-03-11 20:48:31 -0700 | [diff] [blame] | 276 |         } | 
| Romain Guy | ca89e2a | 2013-03-08 17:44:20 -0800 | [diff] [blame] | 277 |  | 
| Romain Guy | 5dc7fa7 | 2013-03-11 20:48:31 -0700 | [diff] [blame] | 278 |         ~PathTask() { | 
 | 279 |             delete future()->get(); | 
 | 280 |         } | 
| Romain Guy | ca89e2a | 2013-03-08 17:44:20 -0800 | [diff] [blame] | 281 |  | 
| Chris Craik | 906d47f | 2014-06-27 18:30:23 -0700 | [diff] [blame] | 282 |         // copied, since input path not refcounted / guaranteed to survive for duration of task | 
 | 283 |         // TODO: avoid deep copy with refcounting | 
 | 284 |         const SkPath path; | 
 | 285 |  | 
 | 286 |         // copied, since input paint may not be immutable | 
| Kenny Root | 25e40de | 2014-05-30 11:51:20 -0700 | [diff] [blame] | 287 |         const SkPaint paint; | 
| Romain Guy | 5dc7fa7 | 2013-03-11 20:48:31 -0700 | [diff] [blame] | 288 |         PathTexture* texture; | 
| Romain Guy | ca89e2a | 2013-03-08 17:44:20 -0800 | [diff] [blame] | 289 |     }; | 
 | 290 |  | 
| Romain Guy | 5dc7fa7 | 2013-03-11 20:48:31 -0700 | [diff] [blame] | 291 |     class PathProcessor: public TaskProcessor<SkBitmap*> { | 
 | 292 |     public: | 
 | 293 |         PathProcessor(Caches& caches); | 
 | 294 |         ~PathProcessor() { } | 
 | 295 |  | 
| Chris Craik | e84a208 | 2014-12-22 14:28:49 -0800 | [diff] [blame] | 296 |         virtual void onProcess(const sp<Task<SkBitmap*> >& task) override; | 
| Romain Guy | 5dc7fa7 | 2013-03-11 20:48:31 -0700 | [diff] [blame] | 297 |  | 
 | 298 |     private: | 
 | 299 |         uint32_t mMaxTextureSize; | 
 | 300 |     }; | 
 | 301 |  | 
| Romain Guy | c46d07a | 2013-03-15 19:06:39 -0700 | [diff] [blame] | 302 |     LruCache<PathDescription, PathTexture*> mCache; | 
 | 303 |     uint32_t mSize; | 
 | 304 |     uint32_t mMaxSize; | 
 | 305 |     GLuint mMaxTextureSize; | 
 | 306 |  | 
 | 307 |     bool mDebugEnabled; | 
 | 308 |  | 
| Romain Guy | 5dc7fa7 | 2013-03-11 20:48:31 -0700 | [diff] [blame] | 309 |     sp<PathProcessor> mProcessor; | 
| Romain Guy | c5cbee7 | 2013-03-20 19:15:02 -0700 | [diff] [blame] | 310 |  | 
 | 311 |     Vector<path_pair_t> mGarbage; | 
| Romain Guy | a2341a9 | 2010-09-08 18:04:33 -0700 | [diff] [blame] | 312 |     mutable Mutex mLock; | 
| Romain Guy | 7fbcc04 | 2010-08-04 15:40:07 -0700 | [diff] [blame] | 313 | }; // class PathCache | 
 | 314 |  | 
 | 315 | }; // namespace uirenderer | 
 | 316 | }; // namespace android | 
 | 317 |  | 
| Romain Guy | 5b3b352 | 2010-10-27 18:57:51 -0700 | [diff] [blame] | 318 | #endif // ANDROID_HWUI_PATH_CACHE_H |