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 }