1 /* 2 * Copyright (C) 2018 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 MINIKIN_LAYOUT_PIECES_H 18 #define MINIKIN_LAYOUT_PIECES_H 19 20 #include <unordered_map> 21 22 #include "minikin/LayoutCache.h" 23 #include "minikin/LayoutCore.h" 24 #include "minikin/MinikinPaint.h" 25 26 namespace minikin { 27 28 struct LayoutPieces { 29 const static uint32_t kNoPaintId = static_cast<uint32_t>(-1); 30 31 struct Key { KeyLayoutPieces::Key32 Key(const Range& range, HyphenEdit hyphenEdit, bool dir, uint32_t paintId) 33 : range(range), hyphenEdit(hyphenEdit), dir(dir), paintId(paintId) {} 34 35 Range range; 36 HyphenEdit hyphenEdit; 37 bool dir; 38 uint32_t paintId; 39 hashLayoutPieces::Key40 uint32_t hash() const { 41 return Hasher() 42 .update(range.getStart()) 43 .update(range.getEnd()) 44 .update(hyphenEdit) 45 .update(dir) 46 .update(paintId) 47 .hash(); 48 } 49 50 bool operator==(const Key& o) const { 51 return range == o.range && hyphenEdit == o.hyphenEdit && dir == o.dir && 52 paintId == o.paintId; 53 } 54 getMemoryUsageLayoutPieces::Key55 uint32_t getMemoryUsage() const { 56 return sizeof(Range) + sizeof(HyphenEdit) + sizeof(bool) + sizeof(uint32_t); 57 } 58 }; 59 60 struct KeyHasher { operatorLayoutPieces::KeyHasher61 std::size_t operator()(const Key& key) const { return key.hash(); } 62 }; 63 64 struct PaintHasher { operatorLayoutPieces::PaintHasher65 std::size_t operator()(const MinikinPaint& paint) const { return paint.hash(); } 66 }; 67 LayoutPiecesLayoutPieces68 LayoutPieces() : nextPaintId(0) {} ~LayoutPiecesLayoutPieces69 ~LayoutPieces() {} 70 71 uint32_t nextPaintId; 72 std::unordered_map<MinikinPaint, uint32_t, PaintHasher> paintMap; 73 std::unordered_map<Key, LayoutPiece, KeyHasher> offsetMap; 74 insertLayoutPieces75 void insert(const Range& range, HyphenEdit edit, const LayoutPiece& layout, bool dir, 76 const MinikinPaint& paint) { 77 uint32_t paintId = findPaintId(paint); 78 if (paintId == kNoPaintId) { 79 paintId = nextPaintId++; 80 paintMap.insert(std::make_pair(paint, paintId)); 81 } 82 offsetMap.emplace(std::piecewise_construct, 83 std::forward_as_tuple(range, edit, dir, paintId), 84 std::forward_as_tuple(layout)); 85 } 86 87 template <typename F> getOrCreateLayoutPieces88 void getOrCreate(const U16StringPiece& textBuf, const Range& range, const Range& context, 89 const MinikinPaint& paint, bool dir, StartHyphenEdit startEdit, 90 EndHyphenEdit endEdit, uint32_t paintId, F& f) const { 91 const HyphenEdit edit = packHyphenEdit(startEdit, endEdit); 92 auto it = offsetMap.find(Key(range, edit, dir, paintId)); 93 if (it == offsetMap.end()) { 94 LayoutCache::getInstance().getOrCreate(textBuf.substr(context), 95 range - context.getStart(), paint, dir, 96 startEdit, endEdit, f); 97 } else { 98 f(it->second, paint); 99 } 100 } 101 findPaintIdLayoutPieces102 uint32_t findPaintId(const MinikinPaint& paint) const { 103 auto paintIt = paintMap.find(paint); 104 return paintIt == paintMap.end() ? kNoPaintId : paintIt->second; 105 } 106 getMemoryUsageLayoutPieces107 uint32_t getMemoryUsage() const { 108 uint32_t result = 0; 109 for (const auto& i : offsetMap) { 110 result += i.first.getMemoryUsage() + i.second.getMemoryUsage(); 111 } 112 result += (sizeof(MinikinPaint) + sizeof(uint32_t)) * paintMap.size(); 113 return result; 114 } 115 }; 116 117 } // namespace minikin 118 119 #endif // MINIKIN_LAYOUT_PIECES_H 120