1 /*
2 * Copyright (c) 2024 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 "cj_measure_ffi.h"
17
18 #include <malloc.h>
19
20 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
21 #include "bridge/cj_frontend/frontend/cj_frontend_abstract.h"
22
23 using namespace OHOS::Ace;
24 using namespace OHOS::Ace::Framework;
25
26 namespace {
27 std::vector<FontStyle> FONTSTYLE_TYPES = {
28 FontStyle::NORMAL, FontStyle::ITALIC
29 };
30
31 std::vector<TextAlign> TEXT_ALIGNS = {
32 TextAlign::START,
33 TextAlign::CENTER,
34 TextAlign::END,
35 TextAlign::LEFT,
36 TextAlign::RIGHT,
37 TextAlign::JUSTIFY
38 };
39 std::vector<TextOverflow> TEXTOVERFLOW = {
40 TextOverflow::NONE,
41 TextOverflow::CLIP,
42 TextOverflow::ELLIPSIS,
43 TextOverflow::MARQUEE
44 };
45 std::vector<TextCase> TEXTCASE = {
46 TextCase::NORMAL,
47 TextCase::LOWERCASE,
48 TextCase::UPPERCASE
49 };
50 std::vector<WordBreak> WORDBREAK = {
51 WordBreak::NORMAL,
52 WordBreak::BREAK_ALL,
53 WordBreak::BREAK_WORD
54 };
55
FromCJCreateMeasureContext(CJMeasureContextToC context)56 MeasureContext FromCJCreateMeasureContext(CJMeasureContextToC context)
57 {
58 MeasureContext measureContext;
59
60 measureContext.textContent = std::string(context.textContent);
61 measureContext.fontWeight = std::string(context.fontWeight);
62 measureContext.fontFamily = std::string(context.fontFamily);
63 measureContext.maxlines = static_cast<int32_t>(context.maxLines);
64 measureContext.textAlign = TEXT_ALIGNS[context.textAlign];
65 measureContext.fontStyle = FONTSTYLE_TYPES[context.fontStyle];
66 measureContext.textOverlayFlow = TEXTOVERFLOW[context.overflow];
67 measureContext.textCase = TEXTCASE[context.textCase];
68 measureContext.wordBreak = WORDBREAK[context.wordBreak];
69
70 if (context.constraintWidth.hasValue) {
71 measureContext.constraintWidth = Dimension(
72 context.constraintWidth.value.value,
73 DimensionUnit(context.constraintWidth.value.unitType)
74 );
75 }
76
77 if (context.fontSize.hasValue) {
78 measureContext.fontSize = Dimension(
79 context.fontSize.value.value,
80 DimensionUnit(context.fontSize.value.unitType)
81 );
82 }
83
84 if (context.lineHeight.hasValue) {
85 measureContext.lineHeight = Dimension(
86 context.lineHeight.value.value,
87 DimensionUnit(context.lineHeight.value.unitType)
88 );
89 }
90
91 if (context.baselineOffset.hasValue) {
92 measureContext.baselineOffset = Dimension(
93 context.baselineOffset.value.value,
94 DimensionUnit(context.baselineOffset.value.unitType)
95 );
96 }
97
98 if (context.letterSpacing.hasValue) {
99 measureContext.letterSpacing = Dimension(
100 context.letterSpacing.value.value,
101 DimensionUnit(context.letterSpacing.value.unitType)
102 );
103 }
104
105 if (context.textIndent.hasValue) {
106 measureContext.textIndent = Dimension(
107 context.textIndent.value.value,
108 DimensionUnit(context.textIndent.value.unitType)
109 );
110 }
111
112 return measureContext;
113 }
114 } // namespace
115
116
117 extern "C" {
FfiMeasureText(const CJMeasureContextToC cjcontext)118 double FfiMeasureText(const CJMeasureContextToC cjcontext)
119 {
120 auto frontend = AceType::DynamicCast<CJFrontendAbstract>(Utils::GetCurrentFrontend());
121 if (!frontend) {
122 LOGE("Can not get frontend.");
123 return 0.0;
124 }
125 MeasureContext context = FromCJCreateMeasureContext(cjcontext);
126
127 return frontend->MeasureText(context);
128 }
129
FfiMeasureTextSize(const CJMeasureContextToC cjcontext)130 CJSize FfiMeasureTextSize(const CJMeasureContextToC cjcontext)
131 {
132 auto frontend = AceType::DynamicCast<CJFrontendAbstract>(Utils::GetCurrentFrontend());
133 CJSize thisSize;
134 thisSize.height = 0.0;
135 thisSize.width = 0.0;
136 if (!frontend) {
137 LOGE("Can not get frontend.");
138 return thisSize;
139 }
140
141 MeasureContext measureContext = FromCJCreateMeasureContext(cjcontext);
142 auto size = frontend->MeasureTextSize(measureContext);
143 thisSize.height = size.Height();
144 thisSize.width = size.Width();
145 return thisSize;
146 }
147 }