1 /* 2 * Copyright (C) 2016 The Android Open Source Project 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 17 #ifndef AAPT_COMPILE_IMAGE_H 18 #define AAPT_COMPILE_IMAGE_H 19 20 #include <cstdint> 21 #include <memory> 22 #include <string> 23 #include <vector> 24 25 #include "android-base/macros.h" 26 27 namespace aapt { 28 29 /** 30 * An in-memory image, loaded from disk, with pixels in RGBA_8888 format. 31 */ 32 class Image { 33 public: 34 explicit Image() = default; 35 36 /** 37 * A `height` sized array of pointers, where each element points to a 38 * `width` sized row of RGBA_8888 pixels. 39 */ 40 std::unique_ptr<uint8_t* []> rows; 41 42 /** 43 * The width of the image in RGBA_8888 pixels. This is int32_t because of 44 * 9-patch data 45 * format limitations. 46 */ 47 int32_t width = 0; 48 49 /** 50 * The height of the image in RGBA_8888 pixels. This is int32_t because of 51 * 9-patch data 52 * format limitations. 53 */ 54 int32_t height = 0; 55 56 /** 57 * Buffer to the raw image data stored sequentially. 58 * Use `rows` to access the data on a row-by-row basis. 59 */ 60 std::unique_ptr<uint8_t[]> data; 61 62 private: 63 DISALLOW_COPY_AND_ASSIGN(Image); 64 }; 65 66 /** 67 * A range of pixel values, starting at 'start' and ending before 'end' 68 * exclusive. Or rather [a, b). 69 */ 70 struct Range { 71 int32_t start = 0; 72 int32_t end = 0; 73 74 explicit Range() = default; 75 inline explicit Range(int32_t s, int32_t e) : start(s), end(e) {} 76 }; 77 78 inline bool operator==(const Range& left, const Range& right) { 79 return left.start == right.start && left.end == right.end; 80 } 81 82 /** 83 * Inset lengths from all edges of a rectangle. `left` and `top` are measured 84 * from the left and top 85 * edges, while `right` and `bottom` are measured from the right and bottom 86 * edges, respectively. 87 */ 88 struct Bounds { 89 int32_t left = 0; 90 int32_t top = 0; 91 int32_t right = 0; 92 int32_t bottom = 0; 93 94 explicit Bounds() = default; 95 inline explicit Bounds(int32_t l, int32_t t, int32_t r, int32_t b) 96 : left(l), top(t), right(r), bottom(b) {} 97 98 bool nonZero() const; 99 }; 100 101 inline bool Bounds::nonZero() const { 102 return left != 0 || top != 0 || right != 0 || bottom != 0; 103 } 104 105 inline bool operator==(const Bounds& left, const Bounds& right) { 106 return left.left == right.left && left.top == right.top && 107 left.right == right.right && left.bottom == right.bottom; 108 } 109 110 /** 111 * Contains 9-patch data from a source image. All measurements exclude the 1px 112 * border of the 113 * source 9-patch image. 114 */ 115 class NinePatch { 116 public: 117 static std::unique_ptr<NinePatch> Create(uint8_t** rows, const int32_t width, 118 const int32_t height, 119 std::string* err_out); 120 121 /** 122 * Packs the RGBA_8888 data pointed to by pixel into a uint32_t 123 * with format 0xAARRGGBB (the way 9-patch expects it). 124 */ 125 static uint32_t PackRGBA(const uint8_t* pixel); 126 127 /** 128 * 9-patch content padding/insets. All positions are relative to the 9-patch 129 * NOT including the 1px thick source border. 130 */ 131 Bounds padding; 132 133 /** 134 * Optical layout bounds/insets. This overrides the padding for 135 * layout purposes. All positions are relative to the 9-patch 136 * NOT including the 1px thick source border. 137 * See 138 * https://developer.android.com/about/versions/android-4.3.html#OpticalBounds 139 */ 140 Bounds layout_bounds; 141 142 /** 143 * Outline of the image, calculated based on opacity. 144 */ 145 Bounds outline; 146 147 /** 148 * The computed radius of the outline. If non-zero, the outline is a 149 * rounded-rect. 150 */ 151 float outline_radius = 0.0f; 152 153 /** 154 * The largest alpha value within the outline. 155 */ 156 uint32_t outline_alpha = 0x000000ffu; 157 158 /** 159 * Horizontal regions of the image that are stretchable. 160 * All positions are relative to the 9-patch 161 * NOT including the 1px thick source border. 162 */ 163 std::vector<Range> horizontal_stretch_regions; 164 165 /** 166 * Vertical regions of the image that are stretchable. 167 * All positions are relative to the 9-patch 168 * NOT including the 1px thick source border. 169 */ 170 std::vector<Range> vertical_stretch_regions; 171 172 /** 173 * The colors within each region, fixed or stretchable. 174 * For w*h regions, the color of region (x,y) is addressable 175 * via index y*w + x. 176 */ 177 std::vector<uint32_t> region_colors; 178 179 /** 180 * Returns serialized data containing the original basic 9-patch meta data. 181 * Optical layout bounds and round rect outline data must be serialized 182 * separately using SerializeOpticalLayoutBounds() and 183 * SerializeRoundedRectOutline(). 184 */ 185 std::unique_ptr<uint8_t[]> SerializeBase(size_t* out_len) const; 186 187 /** 188 * Serializes the layout bounds. 189 */ 190 std::unique_ptr<uint8_t[]> SerializeLayoutBounds(size_t* out_len) const; 191 192 /** 193 * Serializes the rounded-rect outline. 194 */ 195 std::unique_ptr<uint8_t[]> SerializeRoundedRectOutline(size_t* out_len) const; 196 197 private: 198 explicit NinePatch() = default; 199 200 DISALLOW_COPY_AND_ASSIGN(NinePatch); 201 }; 202 203 ::std::ostream& operator<<(::std::ostream& out, const Range& range); 204 ::std::ostream& operator<<(::std::ostream& out, const Bounds& bounds); 205 ::std::ostream& operator<<(::std::ostream& out, const NinePatch& nine_patch); 206 207 } // namespace aapt 208 209 #endif /* AAPT_COMPILE_IMAGE_H */ 210