blob: 7985eccf596ab5511beba40636a91cc7126efbe3 [file] [log] [blame]
Seigo Nonaka3da42692018-04-02 21:39:34 -07001/*
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
Seigo Nonaka3da42692018-04-02 21:39:34 -070022#include "minikin/LayoutCache.h"
Seigo Nonaka3e331a42018-04-12 15:08:02 -070023#include "minikin/LayoutCore.h"
Seigo Nonaka3ca44512018-11-15 10:47:12 -080024#include "minikin/MinikinPaint.h"
Seigo Nonaka3da42692018-04-02 21:39:34 -070025
26namespace minikin {
27
28struct LayoutPieces {
Seigo Nonaka3ca44512018-11-15 10:47:12 -080029 const static uint32_t kNoPaintId = static_cast<uint32_t>(-1);
30
Seigo Nonaka749722f2018-04-27 12:24:28 -070031 struct Key {
Seigo Nonaka3ca44512018-11-15 10:47:12 -080032 Key(const Range& range, HyphenEdit hyphenEdit, bool dir, uint32_t paintId)
33 : range(range), hyphenEdit(hyphenEdit), dir(dir), paintId(paintId) {}
Seigo Nonaka749722f2018-04-27 12:24:28 -070034
35 Range range;
36 HyphenEdit hyphenEdit;
Seigo Nonaka3ca44512018-11-15 10:47:12 -080037 bool dir;
38 uint32_t paintId;
Seigo Nonaka749722f2018-04-27 12:24:28 -070039
40 uint32_t hash() const {
Seigo Nonaka39048502018-08-22 16:13:59 -070041 return Hasher()
42 .update(range.getStart())
43 .update(range.getEnd())
44 .update(hyphenEdit)
Seigo Nonaka3ca44512018-11-15 10:47:12 -080045 .update(dir)
46 .update(paintId)
Seigo Nonaka39048502018-08-22 16:13:59 -070047 .hash();
Seigo Nonaka749722f2018-04-27 12:24:28 -070048 }
49
50 bool operator==(const Key& o) const {
Seigo Nonaka3ca44512018-11-15 10:47:12 -080051 return range == o.range && hyphenEdit == o.hyphenEdit && dir == o.dir &&
52 paintId == o.paintId;
Seigo Nonaka749722f2018-04-27 12:24:28 -070053 }
54
Seigo Nonaka3ca44512018-11-15 10:47:12 -080055 uint32_t getMemoryUsage() const {
56 return sizeof(Range) + sizeof(HyphenEdit) + sizeof(bool) + sizeof(uint32_t);
57 }
Seigo Nonaka749722f2018-04-27 12:24:28 -070058 };
59
Seigo Nonaka3da42692018-04-02 21:39:34 -070060 struct KeyHasher {
Seigo Nonaka749722f2018-04-27 12:24:28 -070061 std::size_t operator()(const Key& key) const { return key.hash(); }
Seigo Nonaka3da42692018-04-02 21:39:34 -070062 };
63
Seigo Nonaka3ca44512018-11-15 10:47:12 -080064 struct PaintHasher {
65 std::size_t operator()(const MinikinPaint& paint) const { return paint.hash(); }
66 };
67
Seigo Nonaka71c39662019-01-29 00:35:16 -080068 LayoutPieces() : nextPaintId(0) {}
Seigo Nonaka749722f2018-04-27 12:24:28 -070069 ~LayoutPieces() {}
Seigo Nonaka3da42692018-04-02 21:39:34 -070070
Seigo Nonaka3ca44512018-11-15 10:47:12 -080071 uint32_t nextPaintId;
72 std::unordered_map<MinikinPaint, uint32_t, PaintHasher> paintMap;
Seigo Nonaka749722f2018-04-27 12:24:28 -070073 std::unordered_map<Key, LayoutPiece, KeyHasher> offsetMap;
Seigo Nonaka3da42692018-04-02 21:39:34 -070074
Seigo Nonaka3ca44512018-11-15 10:47:12 -080075 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),
Seigo Nonaka749722f2018-04-27 12:24:28 -070084 std::forward_as_tuple(layout));
Seigo Nonaka3da42692018-04-02 21:39:34 -070085 }
86
87 template <typename F>
Seigo Nonaka749722f2018-04-27 12:24:28 -070088 void getOrCreate(const U16StringPiece& textBuf, const Range& range, const Range& context,
89 const MinikinPaint& paint, bool dir, StartHyphenEdit startEdit,
Seigo Nonaka3ca44512018-11-15 10:47:12 -080090 EndHyphenEdit endEdit, uint32_t paintId, F& f) const {
Seigo Nonaka749722f2018-04-27 12:24:28 -070091 const HyphenEdit edit = packHyphenEdit(startEdit, endEdit);
Seigo Nonaka3ca44512018-11-15 10:47:12 -080092 auto it = offsetMap.find(Key(range, edit, dir, paintId));
Seigo Nonaka3da42692018-04-02 21:39:34 -070093 if (it == offsetMap.end()) {
Seigo Nonaka749722f2018-04-27 12:24:28 -070094 LayoutCache::getInstance().getOrCreate(textBuf.substr(context),
95 range - context.getStart(), paint, dir,
96 startEdit, endEdit, f);
Seigo Nonaka3da42692018-04-02 21:39:34 -070097 } else {
Seigo Nonaka3ca44512018-11-15 10:47:12 -080098 f(it->second, paint);
Seigo Nonaka3da42692018-04-02 21:39:34 -070099 }
100 }
101
Seigo Nonaka3ca44512018-11-15 10:47:12 -0800102 uint32_t findPaintId(const MinikinPaint& paint) const {
103 auto paintIt = paintMap.find(paint);
104 return paintIt == paintMap.end() ? kNoPaintId : paintIt->second;
105 }
106
Seigo Nonaka3da42692018-04-02 21:39:34 -0700107 uint32_t getMemoryUsage() const {
108 uint32_t result = 0;
109 for (const auto& i : offsetMap) {
110 result += i.first.getMemoryUsage() + i.second.getMemoryUsage();
111 }
Seigo Nonaka3ca44512018-11-15 10:47:12 -0800112 result += (sizeof(MinikinPaint) + sizeof(uint32_t)) * paintMap.size();
Seigo Nonaka3da42692018-04-02 21:39:34 -0700113 return result;
114 }
115};
116
117} // namespace minikin
118
119#endif // MINIKIN_LAYOUT_PIECES_H