1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "typeface.h"
17
18 #include <hb.h>
19
20 #include "texgine_exception.h"
21 #include "texgine/utils/exlog.h"
22 #include "texgine/utils/trace.h"
23
24 namespace OHOS {
25 namespace Rosen {
26 namespace TextEngine {
MakeFromFile(const std::string & filename)27 std::unique_ptr<Typeface> Typeface::MakeFromFile(const std::string &filename)
28 {
29 auto st = TexgineTypeface::MakeFromFile(filename.c_str());
30 if (st == nullptr || st->GetTypeface() == nullptr) {
31 throw TEXGINE_EXCEPTION(API_FAILED);
32 }
33
34 return std::make_unique<Typeface>(st);
35 }
36
Typeface(std::shared_ptr<TexgineTypeface> tf)37 Typeface::Typeface(std::shared_ptr<TexgineTypeface> tf)
38 : typeface_(tf)
39 {
40 if (typeface_ != nullptr) {
41 typeface_->GetFamilyName(&name_);
42 }
43 }
44
~Typeface()45 Typeface::~Typeface()
46 {
47 if (hblob_ != nullptr) {
48 hb_blob_destroy(hblob_);
49 }
50 }
51
GetName()52 std::string Typeface::GetName()
53 {
54 return name_.ToString();
55 }
56
ParseCmap(const std::shared_ptr<CmapParser> & parser)57 bool Typeface::ParseCmap(const std::shared_ptr<CmapParser> &parser)
58 {
59 LOGEX_FUNC_LINE(DEBUG) << "Parse Cmap: " << GetName();
60 ScopedTrace scope("Typeface::InitCmap");
61 auto tag = HB_TAG('c', 'm', 'a', 'p');
62 if (typeface_ == nullptr || typeface_->GetTypeface() == nullptr) {
63 LOGEX_FUNC_LINE(WARN) << "typeface_ is nullptr";
64 return false;
65 }
66
67 auto size = typeface_->GetTableSize(tag);
68 if (size <= 0) {
69 LOGEX_FUNC_LINE(ERROR) << name_.ToString() << " haven't cmap";
70 throw TEXGINE_EXCEPTION(API_FAILED);
71 }
72
73 cmapData_ = std::make_unique<char[]>(size);
74 auto retv = typeface_->GetTableData(tag, 0, size, cmapData_.get());
75 if (size != retv) {
76 LOGEX_FUNC_LINE(ERROR) << "getTableData failed size: " << size << ", retv: " << retv;
77 throw TEXGINE_EXCEPTION(API_FAILED);
78 }
79
80 hblob_ = hb_blob_create(reinterpret_cast<const char *>(cmapData_.get()),
81 size, HB_MEMORY_MODE_WRITABLE, cmapData_.get(), nullptr);
82 if (hblob_ == nullptr) {
83 LOGEX_FUNC_LINE(ERROR) << "hblob_ is nullptr";
84 throw TEXGINE_EXCEPTION(API_FAILED);
85 }
86
87 scope.Finish();
88 ScopedTrace scope2("Typeface::ParseCmap");
89 auto retval = parser->Parse(hb_blob_get_data(hblob_, nullptr), hb_blob_get_length(hblob_));
90 return retval == 0;
91 }
92
Has(uint32_t ch)93 bool Typeface::Has(uint32_t ch)
94 {
95 while (cmapParser_ == nullptr) {
96 auto name = GetName();
97 auto it = cmapCache_.find(name);
98 if (it != cmapCache_.end()) {
99 cmapParser_ = cmapCache_[name];
100 break;
101 }
102
103 auto parser = std::make_shared<CmapParser>();
104 if (ParseCmap(parser)) {
105 cmapParser_ = parser;
106 cmapCache_[name] = parser;
107 } else {
108 cmapCache_.erase(name);
109 return false;
110 }
111 }
112
113 return cmapParser_->GetGlyphId(ch) != CmapParser::INVALID_GLYPH_ID;
114 }
115 } // namespace TextEngine
116 } // namespace Rosen
117 } // namespace OHOS
118