1 /*
2 * Copyright (c) 2022-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 "core/components_ng/pattern/calendar/calendar_paint_method.h"
17
18 #include <cstdint>
19
20 #include "base/geometry/ng/rect_t.h"
21 #include "base/geometry/offset.h"
22 #include "base/geometry/point.h"
23 #include "base/i18n/localization.h"
24 #include "base/memory/referenced.h"
25 #include "base/utils/string_utils.h"
26 #include "base/utils/utils.h"
27 #include "bridge/common/utils/utils.h"
28 #include "core/common/font_manager.h"
29 #include "core/components/calendar/calendar_theme.h"
30 #include "core/components/common/properties/color.h"
31 #include "core/components_ng/pattern/calendar/calendar_pattern.h"
32 #include "core/components_ng/pattern/calendar/calendar_paint_property.h"
33 #include "core/components_ng/render/canvas_image.h"
34 #include "core/components_ng/render/drawing.h"
35 #include "core/components_ng/render/drawing_prop_convertor.h"
36 #include "core/components_ng/render/paint_property.h"
37
38 namespace OHOS::Ace::NG {
39
40 namespace {
41
42 const char ELLIPSIS[] = "...";
43 constexpr int32_t ROW_COUNT_FOUR = 4;
44 constexpr int32_t ROW_COUNT_FIVE = 5;
45 constexpr int32_t ROW_COUNT_SIX = 6;
46 constexpr int32_t TEXT_MAX_LENGTH = 3;
47 constexpr int32_t TEXT_END_INDEX = 2;
48 constexpr int32_t WEEK_TEXT_END_INDEX = 3;
49 constexpr double WEEKEND_TRANSPARENT = 0x7D;
50 constexpr Dimension CALENDAR_DISTANCE_ADJUST_FOCUSED_EVENT = 4.0_vp;
51 constexpr double DEVICE_HEIGHT_LIMIT = 640.0;
52
GetTextParagraph(const std::string & text,const RSTextStyle & textStyle)53 std::unique_ptr<RSParagraph> GetTextParagraph(const std::string& text, const RSTextStyle& textStyle)
54 {
55 RSParagraphStyle style;
56 #ifndef USE_GRAPHIC_TEXT_GINE
57 auto fontCollection = RSFontCollection::GetInstance(false);
58 #else
59 auto fontCollection = RSFontCollection::Create();
60 #endif
61 CHECK_NULL_RETURN(fontCollection, nullptr);
62 #ifndef USE_GRAPHIC_TEXT_GINE
63 std::unique_ptr<RSParagraphBuilder> builder = RSParagraphBuilder::CreateRosenBuilder(style, fontCollection);
64 #else
65 std::unique_ptr<RSParagraphBuilder> builder = RSParagraphBuilder::Create(style, fontCollection);
66 #endif
67 builder->PushStyle(textStyle);
68 #ifndef USE_GRAPHIC_TEXT_GINE
69 builder->AddText(StringUtils::Str8ToStr16(text));
70 return builder->Build();
71 #else
72 builder->AppendText(StringUtils::Str8ToStr16(text));
73 return builder->CreateTypography();
74 #endif
75 }
76
DrawCalendarText(RSCanvas * canvas,const std::string & text,const RSTextStyle & textStyle,const Rect & boxRect,Rect & textRect)77 void DrawCalendarText(
78 RSCanvas* canvas, const std::string& text, const RSTextStyle& textStyle, const Rect& boxRect, Rect& textRect)
79 {
80 // The lunar calendar description is truncated by more than three characters.
81 std::string newText { text };
82 auto wText = StringUtils::ToWstring(text);
83 if (wText.size() > TEXT_MAX_LENGTH) {
84 wText = wText.substr(0, TEXT_END_INDEX);
85 newText = StringUtils::ToString(wText);
86 newText += ELLIPSIS;
87 }
88
89 auto paragraph = GetTextParagraph(newText, textStyle);
90 CHECK_NULL_VOID(paragraph);
91 const auto& offset = boxRect.GetOffset();
92 paragraph->Layout(boxRect.Width());
93 double textWidth = paragraph->GetMaxIntrinsicWidth();
94 double textHeight = paragraph->GetHeight();
95 // paint text in center of item
96 double textPaintOffsetX = (boxRect.Width() - textWidth) / 2.0;
97 double textPaintOffsetY = (boxRect.Height() - textHeight) / 2.0;
98 paragraph->Paint(canvas, offset.GetX() + textPaintOffsetX, offset.GetY() + textPaintOffsetY);
99 textRect.SetRect(offset.GetX() + textPaintOffsetX, offset.GetY() + textPaintOffsetY, textWidth, textHeight);
100 }
101
DrawCalendarText(RSCanvas * canvas,const std::string & text,const RSTextStyle & textStyle,const Rect & boxRect)102 void DrawCalendarText(RSCanvas* canvas, const std::string& text, const RSTextStyle& textStyle, const Rect& boxRect)
103 {
104 Rect textRect;
105 DrawCalendarText(canvas, text, textStyle, boxRect, textRect);
106 }
107
108 } // namespace
109
GetContentDrawFunction(PaintWrapper * paintWrapper)110 CanvasDrawFunction CalendarPaintMethod::GetContentDrawFunction(PaintWrapper* paintWrapper)
111 {
112 auto renderContext = paintWrapper->GetRenderContext();
113 CHECK_NULL_RETURN(renderContext, nullptr);
114 auto calendarNode = renderContext->GetHost();
115 CHECK_NULL_RETURN(calendarNode, nullptr);
116 textDirection_ = calendarNode->GetLayoutProperty()->GetNonAutoLayoutDirection();
117
118 auto paintProperty = DynamicCast<CalendarPaintProperty>(paintWrapper->GetPaintProperty());
119 CHECK_NULL_RETURN(paintProperty, nullptr);
120 frameSize_ = paintWrapper->GetGeometryNode()->GetFrameSize();
121 auto paintFunc = [weak = WeakClaim(this), paintProperty](RSCanvas& canvas) {
122 auto calendar_ = weak.Upgrade();
123 if (calendar_) {
124 calendar_->PaintContent(canvas, paintProperty);
125 }
126 };
127 return paintFunc;
128 }
129
PaintContent(RSCanvas & canvas,const RefPtr<CalendarPaintProperty> & paintProperty)130 void CalendarPaintMethod::PaintContent(RSCanvas& canvas, const RefPtr<CalendarPaintProperty>& paintProperty)
131 {
132 SetCalendarTheme(paintProperty);
133 DrawWeekAndDates(canvas, offset_);
134 }
135
DrawWeekAndDates(RSCanvas & canvas,Offset offset)136 void CalendarPaintMethod::DrawWeekAndDates(RSCanvas& canvas, Offset offset)
137 {
138 weekNumbers_ = Localization::GetInstance()->GetWeekdays(true);
139 if (!obtainedMonth_.days.empty()) {
140 calendarDays_.assign(obtainedMonth_.days.begin(), obtainedMonth_.days.end());
141 }
142 offset += (isCalendarDialog_ ? Offset(CALENDAR_DISTANCE_ADJUST_FOCUSED_EVENT.ConvertToPx(), 0)
143 : Offset(touchCircleStrokeWidth_, 0));
144 DrawWeek(canvas, offset);
145 if (calendarDays_.empty()) {
146 return;
147 }
148 DrawDates(canvas, offset);
149 }
150
DrawDates(RSCanvas & canvas,const Offset & offset)151 void CalendarPaintMethod::DrawDates(RSCanvas& canvas, const Offset& offset)
152 {
153 uint32_t totalWeek = weekNumbers_.size();
154 int32_t dateNumber = 0;
155 double dailyRowSpace = 0.0;
156 double dayNumberStartY = topPadding_ + weekHeight_ + weekAndDayRowSpace_;
157
158 // Set the rowCount.
159 if (totalWeek != 0) {
160 rowCount_ = static_cast<int32_t>(calendarDays_.size() / totalWeek);
161 }
162
163 // Set dailyFourRowSpace_ for four line calendar.
164 // Set dailyFiveRowSpace_ for five line calendar.
165 // Set dailySixRowSpace_ for six line calendar.
166 switch (rowCount_) {
167 case ROW_COUNT_FOUR: {
168 dailyRowSpace = dailyFourRowSpace_;
169 break;
170 }
171 case ROW_COUNT_SIX: {
172 dailyRowSpace = dailySixRowSpace_;
173 break;
174 }
175 case ROW_COUNT_FIVE:
176 default:
177 dailyRowSpace = dailyFiveRowSpace_;
178 break;
179 }
180
181 for (int32_t row = 0; row < rowCount_; row++) {
182 double y = row * (dayHeight_ + dailyRowSpace) + dayNumberStartY;
183 for (uint32_t column = 0; column < totalWeek; column++) {
184 const auto& day = calendarDays_[dateNumber++];
185 double x = textDirection_ == TextDirection::LTR ? column * (dayWidth_ + colSpace_)
186 : (totalWeek - column - 1) * (dayWidth_ + colSpace_);
187 auto dayOffset = Offset(x, y);
188 DrawCalendar(canvas, offset, dayOffset, day);
189 }
190 }
191 }
192
DrawCalendar(RSCanvas & canvas,const Offset & offset,const Offset & dayOffset,const CalendarDay & day)193 void CalendarPaintMethod::DrawCalendar(
194 RSCanvas& canvas, const Offset& offset, const Offset& dayOffset, const CalendarDay& day)
195 {
196 RSTextStyle dateTextStyle;
197 RSTextStyle lunarTextStyle;
198 InitTextStyle(dateTextStyle, lunarTextStyle);
199 #ifndef USE_GRAPHIC_TEXT_GINE
200 dateTextStyle.locale_ = Localization::GetInstance()->GetFontLocale();
201 lunarTextStyle.locale_ = Localization::GetInstance()->GetFontLocale();
202 #else
203 dateTextStyle.locale = Localization::GetInstance()->GetFontLocale();
204 lunarTextStyle.locale = Localization::GetInstance()->GetFontLocale();
205 #endif
206
207 auto x = dayOffset.GetX();
208 auto y = dayOffset.GetY();
209
210 if (isCalendarDialog_) {
211 x += CALENDAR_DISTANCE_ADJUST_FOCUSED_EVENT.ConvertToPx();
212 SetCalendarPickerDayTextStyle(dateTextStyle, day);
213 DrawCalendarPickerBackgroundArea(day, canvas, x, y);
214
215 Offset dateNumberOffset = Offset(x, y + (dayHeight_ / 2 - gregorianDayHeight_ / 2));
216 PaintDay(canvas, dateNumberOffset, day, dateTextStyle);
217 return;
218 }
219
220 // First of all, check whether the day is current month or not, and set text style.
221 SetDayTextStyle(dateTextStyle, lunarTextStyle, day);
222
223 if (day.focused && day.month.month == currentMonth_.month) {
224 if (IsToday(day)) {
225 DrawTodayArea(canvas, offset, x, y);
226 } else {
227 DrawFocusedArea(canvas, offset, x, y);
228 }
229 }
230
231 if (showLunar_ && !day.lunarDay.empty()) {
232 // paint day
233 Offset dateNumberOffset = offset + Offset(x, y + gregorianDayYAxisOffset_);
234 PaintDay(canvas, dateNumberOffset, day, dateTextStyle);
235
236 // paint lunar day
237 Offset lunarDayOffset = offset + Offset(x, y + lunarDayYAxisOffset_);
238 PaintLunarDay(canvas, lunarDayOffset, day, lunarTextStyle);
239 } else {
240 // when there is no lunar calendar, the date is displayed in the center
241 Offset dateNumberOffset = offset + Offset(x, y + (focusedAreaRadius_ - gregorianDayHeight_ / 2));
242 PaintDay(canvas, dateNumberOffset, day, dateTextStyle);
243 }
244 }
245
DrawTodayArea(RSCanvas & canvas,const Offset & offset,double x,double y) const246 void CalendarPaintMethod::DrawTodayArea(RSCanvas& canvas, const Offset& offset, double x, double y) const
247 {
248 // draw Today background circle
249 RSBrush brush;
250 brush.SetAntiAlias(true);
251 brush.SetColor(focusedAreaBackgroundColor_);
252 canvas.AttachBrush(brush);
253
254 Offset circleCenter = Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_,
255 y - (1.0_vp).ConvertToPx() + focusedAreaRadius_);
256 Offset bgCircleStart = offset + circleCenter;
257 canvas.DrawCircle(RSPoint(static_cast<float>(bgCircleStart.GetX()), static_cast<float>(bgCircleStart.GetY())),
258 static_cast<float>(focusedAreaRadius_));
259 canvas.DetachBrush();
260 }
261
DrawFocusedArea(RSCanvas & canvas,const Offset & offset,double x,double y) const262 void CalendarPaintMethod::DrawFocusedArea(RSCanvas& canvas, const Offset& offset, double x, double y) const
263 {
264 // draw focus background circle
265 RSPen pen;
266 pen.SetAntiAlias(true);
267 pen.SetColor(focusedAreaBackgroundColor_);
268 canvas.AttachPen(pen);
269
270 Offset circleCenter = Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_,
271 y - (1.0_vp).ConvertToPx() + focusedAreaRadius_);
272 Offset bgCircleStart = offset + circleCenter;
273 canvas.DrawCircle(RSPoint(static_cast<float>(bgCircleStart.GetX()), static_cast<float>(bgCircleStart.GetY())),
274 static_cast<float>(focusedAreaRadius_));
275 canvas.DetachPen();
276 }
277
DrawCalendarPickerBackgroundArea(const CalendarDay & day,RSCanvas & canvas,double x,double y) const278 void CalendarPaintMethod::DrawCalendarPickerBackgroundArea(
279 const CalendarDay& day, RSCanvas& canvas, double x, double y) const
280 {
281 RSBrush brush;
282 brush.SetAntiAlias(true);
283 brush.SetColor(ToRSColor(Color::TRANSPARENT));
284 if (day.month.year == obtainedMonth_.year && day.month.month == obtainedMonth_.month) {
285 if (day.isSelected) {
286 brush.SetColor(IsToday(day) ? backgroundSelectedTodayColor_ : backgroundSelectedNotTodayColor_);
287 } else if (day.isPressing) {
288 brush.SetColor(backgroundPressColor_);
289 } else if (day.isHovering) {
290 brush.SetColor(backgroundHoverColor_);
291 }
292 }
293
294 canvas.AttachBrush(brush);
295 RSRect rect(static_cast<float>(x), static_cast<float>(y), static_cast<float>(x + dayWidth_),
296 static_cast<float>(y + dayHeight_));
297 auto rrect = RSRoundRect(rect, dayRadius_, dayRadius_);
298 canvas.DrawRoundRect(rrect);
299 canvas.DetachBrush();
300
301 if (day.isKeyFocused) {
302 RSPen pen;
303 pen.SetAntiAlias(true);
304 pen.SetColor(backgroundKeyFocusedColor_);
305 pen.SetWidth(calendarDayKeyFocusedPenWidth_);
306 canvas.AttachPen(pen);
307
308 auto focusedX = x - (calendarDayKeyFocusedWidth_ - dayWidth_) / 2 - calendarDayKeyFocusedPenWidth_ / 2;
309 auto focusedY = y - (calendarDayKeyFocusedWidth_ - dayWidth_) / 2 - calendarDayKeyFocusedPenWidth_ / 2;
310 RSRect keyFocusedrect(static_cast<float>(focusedX), static_cast<float>(focusedY),
311 static_cast<float>(focusedX + calendarDayKeyFocusedWidth_ + calendarDayKeyFocusedPenWidth_),
312 static_cast<float>(focusedY + calendarDayKeyFocusedWidth_ + calendarDayKeyFocusedPenWidth_));
313 auto keyFocusedrrect = RSRoundRect(keyFocusedrect,
314 dayRadius_ / dayWidth_ * (calendarDayKeyFocusedWidth_ + calendarDayKeyFocusedPenWidth_),
315 dayRadius_ / dayWidth_ * (calendarDayKeyFocusedWidth_ + calendarDayKeyFocusedPenWidth_));
316 canvas.DrawRoundRect(keyFocusedrrect);
317 canvas.DetachPen();
318 }
319 }
320
InitTextStyle(RSTextStyle & dateTextStyle,RSTextStyle & lunarTextStyle)321 void CalendarPaintMethod::InitTextStyle(RSTextStyle& dateTextStyle, RSTextStyle& lunarTextStyle)
322 {
323 #ifndef USE_GRAPHIC_TEXT_GINE
324 dateTextStyle.fontSize_ = dayFontSize_;
325 dateTextStyle.fontWeight_ = static_cast<RSFontWeight>(dayFontWeight_);
326
327 lunarTextStyle.fontSize_ = lunarDayFontSize_;
328 lunarTextStyle.fontWeight_ = static_cast<RSFontWeight>(lunarDayFontWeight_);
329
330 if (!appFontFamilies_.empty()) {
331 dateTextStyle.fontFamilies_ = appFontFamilies_;
332 lunarTextStyle.fontFamilies_ = appFontFamilies_;
333 }
334 #else
335 dateTextStyle.fontSize = dayFontSize_;
336 dateTextStyle.fontWeight = static_cast<RSFontWeight>(dayFontWeight_);
337
338 lunarTextStyle.fontSize = lunarDayFontSize_;
339 lunarTextStyle.fontWeight = static_cast<RSFontWeight>(lunarDayFontWeight_);
340
341 if (!appFontFamilies_.empty()) {
342 dateTextStyle.fontFamilies = appFontFamilies_;
343 lunarTextStyle.fontFamilies = appFontFamilies_;
344 }
345 #endif
346 }
347
SetDayTextStyle(RSTextStyle & dateTextStyle,RSTextStyle & lunarTextStyle,const CalendarDay & day)348 void CalendarPaintMethod::SetDayTextStyle(
349 RSTextStyle& dateTextStyle, RSTextStyle& lunarTextStyle, const CalendarDay& day)
350 {
351 // Set the noncurrent month style and current month style.
352 if (day.month.month != currentMonth_.month) {
353 #ifndef USE_GRAPHIC_TEXT_GINE
354 dateTextStyle.color_ = nonCurrentMonthDayColor_;
355 lunarTextStyle.color_ = day.markLunarDay ? RSColor(markLunarColor_.GetRed(), markLunarColor_.GetGreen(),
356 markLunarColor_.GetBlue(), WEEKEND_TRANSPARENT) : nonCurrentMonthLunarColor_;
357 #else
358 dateTextStyle.color = nonCurrentMonthDayColor_;
359 lunarTextStyle.color = day.markLunarDay ? RSColor(markLunarColor_.GetRed(), markLunarColor_.GetGreen(),
360 markLunarColor_.GetBlue(), WEEKEND_TRANSPARENT) : nonCurrentMonthLunarColor_;
361 #endif
362 } else {
363 #ifndef USE_GRAPHIC_TEXT_GINE
364 dateTextStyle.color_ = (IsToday(day) && day.focused) ? focusedDayColor_
365 : IsToday(day) ? todayDayColor_
366 : IsOffDay(day) ? weekendDayColor_
367 : dayColor_;
368 lunarTextStyle.color_ =
369 (IsToday(day) && day.focused) ? focusedLunarColor_
370 : IsToday(day) ? todayLunarColor_
371 : (day.markLunarDay ? markLunarColor_ : (IsOffDay(day) ? weekendLunarColor_ : lunarColor_));
372 #else
373 dateTextStyle.color = (IsToday(day) && day.focused) ? focusedDayColor_
374 : IsToday(day) ? todayDayColor_
375 : IsOffDay(day) ? weekendDayColor_
376 : dayColor_;
377 lunarTextStyle.color =
378 (IsToday(day) && day.focused) ? focusedLunarColor_
379 : IsToday(day) ? todayLunarColor_
380 : (day.markLunarDay ? markLunarColor_ : (IsOffDay(day) ? weekendLunarColor_ : lunarColor_));
381 #endif
382 }
383 }
384
SetCalendarPickerDayTextStyle(RSTextStyle & dateTextStyle,const CalendarDay & day)385 void CalendarPaintMethod::SetCalendarPickerDayTextStyle(RSTextStyle& dateTextStyle, const CalendarDay& day)
386 {
387 if (day.month.month != currentMonth_.month) {
388 #ifndef USE_GRAPHIC_TEXT_GINE
389 dateTextStyle.color_ = textNonCurrentMonthColor_;
390 #else
391 dateTextStyle.color = textNonCurrentMonthColor_;
392 #endif
393 } else {
394 if (IsToday(day)) {
395 #ifndef USE_GRAPHIC_TEXT_GINE
396 dateTextStyle.color_ = day.isSelected ? textSelectedDayColor_ : textCurrentDayColor_;
397 #else
398 dateTextStyle.color = day.isSelected ? textSelectedDayColor_ : textCurrentDayColor_;
399 #endif
400 } else {
401 #ifndef USE_GRAPHIC_TEXT_GINE
402 dateTextStyle.color_ = textCurrentMonthColor_;
403 #else
404 dateTextStyle.color = textCurrentMonthColor_;
405 #endif
406 }
407 }
408 }
409
SetOffWorkTextStyle(RSTextStyle & offWorkTextStyle,const CalendarDay & day) const410 void CalendarPaintMethod::SetOffWorkTextStyle(RSTextStyle& offWorkTextStyle, const CalendarDay& day) const
411 {
412 // Paint off or work mark value.
413 #ifndef USE_GRAPHIC_TEXT_GINE
414 offWorkTextStyle.fontWeight_ = static_cast<RSFontWeight>(workStateFontWeight_);
415 offWorkTextStyle.locale_ = Localization::GetInstance()->GetFontLocale();
416
417 if (!appFontFamilies_.empty()) {
418 offWorkTextStyle.fontFamilies_ = appFontFamilies_;
419 }
420 #else
421 offWorkTextStyle.fontWeight = static_cast<RSFontWeight>(workStateFontWeight_);
422 offWorkTextStyle.locale = Localization::GetInstance()->GetFontLocale();
423
424 if (!appFontFamilies_.empty()) {
425 offWorkTextStyle.fontFamilies = appFontFamilies_;
426 }
427 #endif
428 if (day.month.month == currentMonth_.month) {
429 if (day.dayMark == "work") {
430 #ifndef USE_GRAPHIC_TEXT_GINE
431 offWorkTextStyle.fontSize_ = workDayMarkSize_;
432 offWorkTextStyle.color_ = workDayMarkColor_;
433 #else
434 offWorkTextStyle.fontSize = workDayMarkSize_;
435 offWorkTextStyle.color = workDayMarkColor_;
436 #endif
437 } else if (day.dayMark == "off") {
438 #ifndef USE_GRAPHIC_TEXT_GINE
439 offWorkTextStyle.fontSize_ = offDayMarkSize_;
440 offWorkTextStyle.color_ = offDayMarkColor_;
441 #else
442 offWorkTextStyle.fontSize = offDayMarkSize_;
443 offWorkTextStyle.color = offDayMarkColor_;
444 #endif
445 }
446 } else {
447 if (day.dayMark == "work") {
448 #ifndef USE_GRAPHIC_TEXT_GINE
449 offWorkTextStyle.fontSize_ = workDayMarkSize_;
450 offWorkTextStyle.color_ =
451 RSColor(nonCurrentMonthWorkDayMarkColor_.GetRed(), nonCurrentMonthWorkDayMarkColor_.GetGreen(),
452 nonCurrentMonthWorkDayMarkColor_.GetBlue(), WEEKEND_TRANSPARENT);
453 #else
454 offWorkTextStyle.fontSize = workDayMarkSize_;
455 offWorkTextStyle.color =
456 RSColor(nonCurrentMonthWorkDayMarkColor_.GetRed(), nonCurrentMonthWorkDayMarkColor_.GetGreen(),
457 nonCurrentMonthWorkDayMarkColor_.GetBlue(), WEEKEND_TRANSPARENT);
458 #endif
459 } else if (day.dayMark == "off") {
460 #ifndef USE_GRAPHIC_TEXT_GINE
461 offWorkTextStyle.fontSize_ = offDayMarkSize_;
462 offWorkTextStyle.color_ =
463 RSColor(nonCurrentMonthOffDayMarkColor_.GetRed(), nonCurrentMonthOffDayMarkColor_.GetGreen(),
464 nonCurrentMonthOffDayMarkColor_.GetBlue(), WEEKEND_TRANSPARENT);
465 #else
466 offWorkTextStyle.fontSize = offDayMarkSize_;
467 offWorkTextStyle.color =
468 RSColor(nonCurrentMonthOffDayMarkColor_.GetRed(), nonCurrentMonthOffDayMarkColor_.GetGreen(),
469 nonCurrentMonthOffDayMarkColor_.GetBlue(), WEEKEND_TRANSPARENT);
470 #endif
471 }
472 }
473
474 // If it is today and it is focused, workState color is same as focused day color.
475 if (IsToday(day) && day.focused) {
476 #ifndef USE_GRAPHIC_TEXT_GINE
477 offWorkTextStyle.color_ = focusedDayColor_;
478 #else
479 offWorkTextStyle.color = focusedDayColor_;
480 #endif
481 }
482 }
483
PaintDay(RSCanvas & canvas,const Offset & offset,const CalendarDay & day,RSTextStyle & textStyle) const484 void CalendarPaintMethod::PaintDay(
485 RSCanvas& canvas, const Offset& offset, const CalendarDay& day, RSTextStyle& textStyle) const
486 {
487 // Paint day value.
488 Rect boxRect { offset.GetX(), offset.GetY(), dayWidth_, gregorianDayHeight_ };
489 Rect textRect;
490
491 auto dayStr = std::to_string(day.day);
492 dayStr = Localization::GetInstance()->NumberFormat(day.day);
493 DrawCalendarText(&canvas, dayStr, textStyle, boxRect, textRect);
494
495 // Paint off and work mark value.
496 if (!day.dayMark.empty() && showHoliday_) {
497 RSTextStyle workStateStyle;
498 boxRect = { textRect.GetOffset().GetX() + textRect.Width() - workStateHorizontalMovingDistance_,
499 textRect.GetOffset().GetY() + textRect.Height() - workStateVerticalMovingDistance_, workStateWidth_,
500 workStateWidth_ };
501 SetOffWorkTextStyle(workStateStyle, day);
502 DrawCalendarText(&canvas, day.dayMarkValue, workStateStyle, boxRect);
503 }
504 }
505
PaintLunarDay(RSCanvas & canvas,const Offset & offset,const CalendarDay & day,const RSTextStyle & textStyle) const506 void CalendarPaintMethod::PaintLunarDay(
507 RSCanvas& canvas, const Offset& offset, const CalendarDay& day, const RSTextStyle& textStyle) const
508 {
509 Rect boxRect = { offset.GetX(), offset.GetY(), dayWidth_, lunarDayHeight_ };
510 DrawCalendarText(&canvas, day.lunarDay, textStyle, boxRect);
511 }
512
DrawWeek(RSCanvas & canvas,const Offset & offset) const513 void CalendarPaintMethod::DrawWeek(RSCanvas& canvas, const Offset& offset) const
514 {
515 uint32_t totalWeek = weekNumbers_.size();
516 RSTextStyle weekTextStyle;
517 #ifndef USE_GRAPHIC_TEXT_GINE
518 weekTextStyle.color_ = weekColor_;
519 weekTextStyle.fontSize_ = weekFontSize_;
520 weekTextStyle.locale_ = Localization::GetInstance()->GetFontLocale();
521
522 if (!appFontFamilies_.empty()) {
523 weekTextStyle.fontFamilies_ = appFontFamilies_;
524 }
525 #else
526 weekTextStyle.color = weekColor_;
527 weekTextStyle.fontSize = weekFontSize_;
528 weekTextStyle.locale = Localization::GetInstance()->GetFontLocale();
529
530 if (!appFontFamilies_.empty()) {
531 weekTextStyle.fontFamilies = appFontFamilies_;
532 }
533 #endif
534 static const int32_t daysOfWeek = 7;
535
536 auto startDayOfWeek = startOfWeek_;
537 for (uint32_t column = 0; column < totalWeek; column++) {
538 double x = textDirection_ == TextDirection::LTR ? column * (weekWidth_ + colSpace_)
539 : (totalWeek - column - 1) * (weekWidth_ + colSpace_);
540 Offset weekNumberOffset = offset + Offset(x, topPadding_);
541 Rect boxRect { weekNumberOffset.GetX(), weekNumberOffset.GetY(), weekWidth_, weekHeight_ };
542 std::string newText { weekNumbers_[(startDayOfWeek + 1) % daysOfWeek] };
543 auto wText = StringUtils::ToWstring(newText);
544 if (wText.size() > TEXT_MAX_LENGTH) {
545 wText = wText.substr(0, WEEK_TEXT_END_INDEX);
546 newText = StringUtils::ToString(wText);
547 }
548 DrawCalendarText(&canvas, newText, weekTextStyle, boxRect);
549 ++startDayOfWeek;
550 }
551 }
552
SetCalendarTheme(const RefPtr<CalendarPaintProperty> & paintProperty)553 void CalendarPaintMethod::SetCalendarTheme(const RefPtr<CalendarPaintProperty>& paintProperty)
554 {
555 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
556 CHECK_NULL_VOID(pipelineContext);
557 RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
558 CHECK_NULL_VOID(theme);
559
560 auto fontManager = pipelineContext->GetFontManager();
561 if (fontManager && !(fontManager->GetAppCustomFont().empty())) {
562 appFontFamilies_ = Framework::ConvertStrToFontFamilies(fontManager->GetAppCustomFont());
563 }
564
565 weekColor_ = ToRSColor(paintProperty->GetWeekColor().value_or(theme->GetCalendarTheme().weekColor));
566 dayColor_ = ToRSColor(paintProperty->GetDayColor().value_or(theme->GetCalendarTheme().dayColor));
567 lunarColor_ = ToRSColor(paintProperty->GetLunarColor().value_or(theme->GetCalendarTheme().lunarColor));
568 weekendDayColor_ =
569 ToRSColor(paintProperty->GetWeekendDayColor().value_or(theme->GetCalendarTheme().weekendDayColor));
570 weekendLunarColor_ =
571 ToRSColor(paintProperty->GetWeekendLunarColor().value_or(theme->GetCalendarTheme().weekendLunarColor));
572 nonCurrentMonthDayColor_ = ToRSColor(
573 paintProperty->GetNonCurrentMonthDayColor().value_or(theme->GetCalendarTheme().nonCurrentMonthDayColor));
574 nonCurrentMonthLunarColor_ = ToRSColor(
575 paintProperty->GetNonCurrentMonthLunarColor().value_or(theme->GetCalendarTheme().nonCurrentMonthLunarColor));
576 workDayMarkColor_ =
577 ToRSColor(paintProperty->GetWorkDayMarkColor().value_or(theme->GetCalendarTheme().workDayMarkColor));
578 offDayMarkColor_ =
579 ToRSColor(paintProperty->GetOffDayMarkColor().value_or(theme->GetCalendarTheme().offDayMarkColor));
580 nonCurrentMonthWorkDayMarkColor_ = ToRSColor(paintProperty->GetNonCurrentMonthWorkDayMarkColor().value_or(
581 theme->GetCalendarTheme().nonCurrentMonthWorkDayMarkColor));
582 nonCurrentMonthOffDayMarkColor_ = ToRSColor(paintProperty->GetNonCurrentMonthOffDayMarkColor().value_or(
583 theme->GetCalendarTheme().nonCurrentMonthOffDayMarkColor));
584 focusedDayColor_ =
585 ToRSColor(paintProperty->GetFocusedDayColor().value_or(theme->GetCalendarTheme().focusedDayColor));
586 focusedLunarColor_ =
587 ToRSColor(paintProperty->GetFocusedLunarColor().value_or(theme->GetCalendarTheme().focusedLunarColor));
588 focusedAreaBackgroundColor_ = ToRSColor(
589 paintProperty->GetFocusedAreaBackgroundColor().value_or(theme->GetCalendarTheme().focusedAreaBackgroundColor));
590 markLunarColor_ = ToRSColor(paintProperty->GetMarkLunarColor().value_or(theme->GetCalendarTheme().markLunarColor));
591
592 todayDayColor_ = RSColor(theme->GetCalendarTheme().todayColor.GetValue());
593 todayLunarColor_ = RSColor(theme->GetCalendarTheme().todayLunarColor.GetValue());
594
595 dayFontWeight_ = StringUtils::StringToFontWeight(theme->GetCalendarTheme().dayFontWeight);
596 lunarDayFontWeight_ = StringUtils::StringToFontWeight(theme->GetCalendarTheme().lunarDayFontWeight);
597 workStateFontWeight_ = StringUtils::StringToFontWeight(theme->GetCalendarTheme().workStateFontWeight);
598
599 topPadding_ = isCalendarDialog_ ? 0.0 : theme->GetCalendarTheme().topPadding.ConvertToPx();
600 weekFontSize_ = paintProperty->GetWeekFontSize().value_or(theme->GetCalendarTheme().weekFontSize).ConvertToPx();
601 dayFontSize_ = paintProperty->GetDayFontSize().value_or(theme->GetCalendarTheme().dayFontSize).ConvertToPx();
602 lunarDayFontSize_ =
603 paintProperty->GetLunarDayFontSize().value_or(theme->GetCalendarTheme().lunarDayFontSize).ConvertToPx();
604 workDayMarkSize_ =
605 paintProperty->GetWorkDayMarkSize().value_or(theme->GetCalendarTheme().workDayMarkSize).ConvertToPx();
606 offDayMarkSize_ =
607 paintProperty->GetOffDayMarkSize().value_or(theme->GetCalendarTheme().offDayMarkSize).ConvertToPx();
608 focusedAreaRadius_ = paintProperty->GetFocusedAreaRadiusValue({}).ConvertToPx() <= 0
609 ? theme->GetCalendarTheme().focusedAreaRadius.ConvertToPx()
610 : paintProperty->GetFocusedAreaRadiusValue({}).ConvertToPx();
611
612 weekHeight_ = paintProperty->GetWeekHeightValue({}).ConvertToPx() <= 0
613 ? theme->GetCalendarTheme().weekHeight.ConvertToPx()
614 : paintProperty->GetWeekHeightValue({}).ConvertToPx();
615 dayHeight_ = paintProperty->GetDayHeightValue({}).ConvertToPx() <= 0
616 ? theme->GetCalendarTheme().dayHeight.ConvertToPx()
617 : paintProperty->GetDayHeightValue({}).ConvertToPx();
618 weekWidth_ = paintProperty->GetWeekWidthValue({}).ConvertToPx() <= 0
619 ? theme->GetCalendarTheme().weekWidth.ConvertToPx()
620 : paintProperty->GetWeekWidthValue({}).ConvertToPx();
621 dayWidth_ = paintProperty->GetDayWidthValue({}).ConvertToPx() <= 0
622 ? theme->GetCalendarTheme().dayWidth.ConvertToPx()
623 : paintProperty->GetDayWidthValue({}).ConvertToPx();
624 weekAndDayRowSpace_ =
625 paintProperty->GetWeekAndDayRowSpace().value_or(theme->GetCalendarTheme().weekAndDayRowSpace).ConvertToPx();
626
627 touchCircleStrokeWidth_ = theme->GetCalendarTheme().touchCircleStrokeWidth.ConvertToPx();
628
629 colSpace_ = paintProperty->GetColSpaceValue({}).ConvertToPx() <= 0
630 ? theme->GetCalendarTheme().colSpace.ConvertToPx()
631 : paintProperty->GetColSpaceValue({}).ConvertToPx();
632 dailyFourRowSpace_ = NonPositive(paintProperty->GetDailyFourRowSpaceValue({}).ConvertToPx())
633 ? theme->GetCalendarTheme().dailySixRowSpace.ConvertToPx()
634 : paintProperty->GetDailyFourRowSpaceValue({}).ConvertToPx();
635 dailyFiveRowSpace_ = paintProperty->GetDailyFiveRowSpaceValue({}).ConvertToPx() <= 0
636 ? theme->GetCalendarTheme().dailyFiveRowSpace.ConvertToPx()
637 : paintProperty->GetDailyFiveRowSpaceValue({}).ConvertToPx();
638
639 dailySixRowSpace_ = paintProperty->GetDailySixRowSpaceValue({}).ConvertToPx() <= 0
640 ? theme->GetCalendarTheme().dailySixRowSpace.ConvertToPx()
641 : paintProperty->GetDailySixRowSpaceValue({}).ConvertToPx();
642
643 gregorianDayHeight_ = paintProperty->GetGregorianCalendarHeightValue({}).ConvertToPx() <= 0
644 ? theme->GetCalendarTheme().gregorianCalendarHeight.ConvertToPx()
645 : paintProperty->GetGregorianCalendarHeightValue({}).ConvertToPx();
646
647 lunarDayHeight_ = paintProperty->GetLunarHeight().value_or(theme->GetCalendarTheme().lunarHeight).ConvertToPx();
648
649 gregorianDayYAxisOffset_ =
650 paintProperty->GetDayYAxisOffset().value_or(theme->GetCalendarTheme().dayYAxisOffset).ConvertToPx();
651 lunarDayYAxisOffset_ =
652 paintProperty->GetLunarDayYAxisOffset().value_or(theme->GetCalendarTheme().lunarDayYAxisOffset).ConvertToPx();
653
654 workStateWidth_ = paintProperty->GetWorkStateWidthValue({}).ConvertToPx() <= 0
655 ? theme->GetCalendarTheme().workStateWidth.ConvertToPx()
656 : paintProperty->GetWorkStateWidthValue({}).ConvertToPx();
657
658 workStateHorizontalMovingDistance_ = paintProperty->GetWorkStateHorizontalMovingDistance()
659 .value_or(theme->GetCalendarTheme().workStateHorizontalMovingDistance)
660 .ConvertToPx();
661 workStateVerticalMovingDistance_ = paintProperty->GetWorkStateVerticalMovingDistance()
662 .value_or(theme->GetCalendarTheme().workStateVerticalMovingDistance)
663 .ConvertToPx();
664 dayRadius_ = paintProperty->GetDayRadiusValue(theme->GetCalendarDayRadius()).ConvertToPx();
665 textNonCurrentMonthColor_ = ToRSColor(theme->GetTextNonCurrentMonthColor());
666 textSelectedDayColor_ = ToRSColor(theme->GetTextSelectedDayColor());
667 textCurrentDayColor_ = ToRSColor(theme->GetTextCurrentDayColor());
668 textCurrentMonthColor_ = ToRSColor(theme->GetTextCurrentMonthColor());
669 backgroundKeyFocusedColor_ = ToRSColor(theme->GetBackgroundKeyFocusedColor());
670 backgroundSelectedTodayColor_ = ToRSColor(theme->GetBackgroundSelectedTodayColor());
671 backgroundSelectedNotTodayColor_ = ToRSColor(theme->GetBackgroundSelectedNotTodayColor());
672 backgroundHoverColor_ = ToRSColor(theme->GetBackgroundHoverColor());
673 backgroundPressColor_ = ToRSColor(theme->GetBackgroundPressColor());
674
675 auto fontSizeScale = pipelineContext->GetFontScale();
676 if (fontSizeScale < theme->GetCalendarPickerLargeScale() ||
677 Dimension(pipelineContext->GetRootHeight()).ConvertToVp() < DEVICE_HEIGHT_LIMIT) {
678 calendarDayKeyFocusedWidth_ = theme->GetCalendarDayKeyFocusedWidth().ConvertToPx();
679 } else {
680 calendarDayKeyFocusedWidth_ = theme->GetCalendarLargeDayKeyFocusedWidth().ConvertToPx();
681 }
682
683 calendarDayKeyFocusedPenWidth_ = theme->GetCalendarDayKeyFocusedPenWidth().ConvertToPx();
684 if (paintProperty->HasShowLunar()) {
685 showLunar_ = paintProperty->GetShowLunarValue();
686 }
687 showHoliday_ = paintProperty->GetShowHolidayValue(true);
688 if (paintProperty->HasStartOfWeek()) {
689 startOfWeek_ = static_cast<int32_t>(paintProperty->GetStartOfWeekValue());
690 }
691 startOfWeek_ = static_cast<int32_t>(log2(startOfWeek_));
692 if (paintProperty->HasOffDays()) {
693 offDays_ = paintProperty->GetOffDaysValue();
694 }
695 currentMonth_.month = obtainedMonth_.month;
696 }
697
IsToday(const CalendarDay & day) const698 bool CalendarPaintMethod::IsToday(const CalendarDay& day) const
699 {
700 auto today = calendarDay_;
701 return today.month == day.month && today.day == day.day;
702 }
703
IsOffDay(const CalendarDay & dayInfo) const704 bool CalendarPaintMethod::IsOffDay(const CalendarDay& dayInfo) const
705 {
706 std::vector<std::string> days;
707 StringUtils::StringSplitter(offDays_, ',', days);
708 int32_t daysOfWeek = 7;
709 for (const auto& day : days) {
710 auto num = (StringUtils::StringToInt(day) + (daysOfWeek - static_cast<int32_t>(startOfWeek_))) % daysOfWeek;
711 if ((dayInfo.index % daysOfWeek) == num) {
712 return true;
713 }
714 }
715 return false;
716 }
717 } // namespace OHOS::Ace::NG
718