1 /*
2  * Copyright (c) 2021-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/calendar/rosen_render_calendar.h"
17 
18 #ifndef USE_GRAPHIC_TEXT_GINE
19 #include "txt/paragraph_builder.h"
20 #include "txt/paragraph_style.h"
21 #else
22 #include "rosen_text/typography_create.h"
23 #include "rosen_text/typography_style.h"
24 #endif
25 
26 #include "base/i18n/localization.h"
27 #include "core/components/font/rosen_font_collection.h"
28 #include "core/pipeline/base/rosen_render_context.h"
29 
30 namespace OHOS::Ace {
31 namespace {
32 
33 const char ELLIPSIS[] = "...";
34 constexpr double CURRENT_MONTH_TRANSPARENT = 0xFF;
35 constexpr double NON_CURRENT_MONTH_TRANSPARENT = 0x32;
36 constexpr double WEEKEND_TRANSPARENT = 0x7D;
37 constexpr double SCHEDULE_MARKER_TRANSPARENT = 0x4B;
38 constexpr Dimension CARD_CALENDAR_TITLE_HEIGHT = 68.0_vp;
39 
40 #ifndef USE_GRAPHIC_TEXT_GINE
GetTextParagraph(const std::string & text,const txt::TextStyle & textStyle)41 std::unique_ptr<txt::Paragraph> GetTextParagraph(const std::string& text, const txt::TextStyle& textStyle)
42 {
43     txt::ParagraphStyle style;
44 #else
45 std::unique_ptr<Rosen::Typography> GetTextParagraph(const std::string& text, const Rosen::TextStyle& textStyle)
46 {
47     Rosen::TypographyStyle style;
48 #endif
49     auto fontCollection = RosenFontCollection::GetInstance().GetFontCollection();
50     if (!fontCollection) {
51         LOGW("MeasureText: fontCollection is null");
52         return nullptr;
53     }
54 #ifndef USE_GRAPHIC_TEXT_GINE
55     std::unique_ptr<txt::ParagraphBuilder> builder = txt::ParagraphBuilder::CreateTxtBuilder(style, fontCollection);
56     builder->PushStyle(textStyle);
57     builder->AddText(StringUtils::Str8ToStr16(text));
58     return builder->Build();
59 #else
60     std::unique_ptr<Rosen::TypographyCreate> builder = Rosen::TypographyCreate::Create(style, fontCollection);
61     builder->PushStyle(textStyle);
62     builder->AppendText(StringUtils::Str8ToStr16(text));
63     return builder->CreateTypography();
64 #endif
65 }
66 
67 #ifndef USE_ROSEN_DRAWING
68 #ifndef USE_GRAPHIC_TEXT_GINE
69 void DrawCalendarText(
70     SkCanvas* canvas, const std::string& text, const txt::TextStyle& textStyle, const Rect& boxRect, Rect& textRect)
71 #else
72 void DrawCalendarText(
73     SkCanvas* canvas, const std::string& text, const Rosen::TextStyle& textStyle, const Rect& boxRect, Rect& textRect)
74 #endif
75 #else
76 #ifndef USE_GRAPHIC_TEXT_GINE
77 void DrawCalendarText(RSCanvas* canvas,
78     const std::string& text, const txt::TextStyle& textStyle, const Rect& boxRect, Rect& textRect)
79 #else
80 void DrawCalendarText(RSCanvas* canvas,
81     const std::string& text, const Rosen::TextStyle& textStyle, const Rect& boxRect, Rect& textRect)
82 #endif
83 #endif
84 {
85     // The lunar calendar description is truncated by more than three characters.
86     std::string newText { text };
87     auto wText = StringUtils::ToWstring(text);
88     if (wText.size() > 3) {
89         wText = wText.substr(0, 2);
90         newText = StringUtils::ToString(wText);
91         newText += ELLIPSIS;
92     }
93 
94     auto paragraph = GetTextParagraph(newText, textStyle);
95     if (!paragraph) {
96         return;
97     }
98     const auto& offset = boxRect.GetOffset();
99     paragraph->Layout(boxRect.Width());
100     double textWidth = paragraph->GetMaxIntrinsicWidth();
101     double textHeight = paragraph->GetHeight();
102     // paint text in center of item
103     double textPaintOffsetX = (boxRect.Width() - textWidth) / 2.0;
104     double textPaintOffsetY = (boxRect.Height() - textHeight) / 2.0;
105     paragraph->Paint(canvas, offset.GetX() + textPaintOffsetX, offset.GetY() + textPaintOffsetY);
106     textRect.SetRect(offset.GetX() + textPaintOffsetX, offset.GetY() + textPaintOffsetY, textWidth, textHeight);
107 }
108 
109 #ifndef USE_ROSEN_DRAWING
110 #ifndef USE_GRAPHIC_TEXT_GINE
111 void DrawCalendarText(SkCanvas* canvas, const std::string& text, const txt::TextStyle& textStyle, const Rect& boxRect)
112 #else
113 void DrawCalendarText(SkCanvas* canvas, const std::string& text, const Rosen::TextStyle& textStyle, const Rect& boxRect)
114 #endif
115 #else
116 #ifndef USE_GRAPHIC_TEXT_GINE
117 void DrawCalendarText(RSCanvas* canvas,
118     const std::string& text, const txt::TextStyle& textStyle, const Rect& boxRect)
119 #else
120 void DrawCalendarText(RSCanvas* canvas,
121     const std::string& text, const Rosen::TextStyle& textStyle, const Rect& boxRect)
122 #endif
123 #endif
124 {
125     Rect textRect;
126     DrawCalendarText(canvas, text, textStyle, boxRect, textRect);
127 }
128 } // namespace
129 
Update(const RefPtr<Component> & component)130 void RosenRenderCalendar::Update(const RefPtr<Component>& component)
131 {
132     auto calendarMonth = AceType::DynamicCast<CalendarMonthComponent>(component);
133     if (!calendarMonth) {
134         LOGE("calendar component is null");
135         return;
136     }
137 
138     textDirection_ = calendarMonth->GetTextDirection();
139     auto calendarTheme = calendarMonth->GetCalendarTheme();
140     cardCalendar_ = calendarMonth->IsCardCalendar();
141     if (!isV2Component_) {
142         calendarTheme_ = cardCalendar_ ? calendarTheme->GetCardCalendarTheme() : calendarTheme->GetCalendarTheme();
143     }
144     RenderCalendar::Update(component);
145     if (auto rsNode = GetRSNode()) {
146         rsNode->SetClipToFrame(true);
147     }
148 }
149 
Paint(RenderContext & context,const Offset & offset)150 void RosenRenderCalendar::Paint(RenderContext& context, const Offset& offset)
151 {
152     if (isV2Component_ && !isNeedRepaint_) {
153         AddContentLayer(context);
154         DrawTouchedArea(context, offset);
155         return;
156     }
157     SetCalendarTheme();
158     if (isV2Component_) {
159 #ifdef OHOS_PLATFORM
160         const Size& layout = GetLayoutSize();
161 #ifndef USE_ROSEN_DRAWING
162         OHOS::Rosen::RSRecordingCanvas canvas(layout.Width(), layout.Height());
163 #else
164         RSRecordingCanvas canvas(layout.Width(), layout.Height());
165 #endif
166         DrawWeekAndDates(&canvas, offset);
167         drawCmdList_ = canvas.GetDrawCmdList();
168         isNeedRepaint_ = false;
169         AddContentLayer(context);
170         DrawTouchedArea(context, offset);
171 #endif
172     } else {
173         auto canvas = static_cast<RosenRenderContext*>(&context)->GetCanvas();
174         if (!canvas) {
175             LOGE("paint canvas is null");
176             return;
177         }
178         DrawWeekAndDates(canvas, offset);
179     }
180 }
181 
PerformLayout()182 void RosenRenderCalendar::PerformLayout()
183 {
184     RenderCalendar::PerformLayout();
185     topPadding_ = type_ == CalendarType::SIMPLE ? 0.0 : NormalizeToPx(calendarTheme_.topPadding);
186     weekFontSize_ = NormalizeToPx(calendarTheme_.weekFontSize);
187     dayFontSize_ = NormalizeToPx(calendarTheme_.dayFontSize);
188     lunarDayFontSize_ = NormalizeToPx(calendarTheme_.lunarDayFontSize);
189     workDayMarkSize_ = NormalizeToPx(calendarTheme_.workDayMarkSize);
190     offDayMarkSize_ = NormalizeToPx(calendarTheme_.offDayMarkSize);
191     focusedAreaRadius_ = NormalizeToPx(calendarTheme_.focusedAreaRadius);
192     weekHeight_ = NormalizeToPx(calendarTheme_.weekHeight);
193     dayHeight_ = NormalizeToPx(calendarTheme_.dayHeight);
194     weekWidth_ = NormalizeToPx(calendarTheme_.weekWidth);
195     dayWidth_ = NormalizeToPx(calendarTheme_.dayWidth);
196     weekAndDayRowSpace_ = NormalizeToPx(calendarTheme_.weekAndDayRowSpace);
197     touchCircleStrokeWidth_ = NormalizeToPx(calendarTheme_.touchCircleStrokeWidth);
198     double titleHeight = topPadding_ + weekHeight_ + weekAndDayRowSpace_;
199     double boundaryRowOffset = NormalizeToPx(calendarTheme_.boundaryRowOffset);
200     double boundaryColOffset = NormalizeToPx(calendarTheme_.boundaryColOffset);
201     const static int32_t daysOfWeek = 7;
202     const static int32_t fiveRow = 5;
203     const static int32_t sixRow = 6;
204     const static float heightOffset = 1.5f;
205     weekAndDayRowSpace_ = NormalizeToPx(calendarTheme_.weekAndDayRowSpace);
206     if (cardCalendar_ || isV2Component_) {
207         colSpace_ = (maxWidth_ - dayWidth_ * daysOfWeek - boundaryRowOffset) / (daysOfWeek - 1);
208         dailyFiveRowSpace_ = (maxHeight_ - titleHeight - dayHeight_ * fiveRow - boundaryColOffset) / (fiveRow - 1);
209         dailySixRowSpace_ = (maxHeight_ - titleHeight - dayHeight_ * sixRow - boundaryColOffset) / (sixRow - 1);
210     } else if (type_ == CalendarType::SIMPLE) {
211         colSpace_ = (maxWidth_ - boundaryRowOffset - dayWidth_ * daysOfWeek) / (daysOfWeek - 1);
212         dailyFiveRowSpace_ =
213             (maxHeight_ - boundaryColOffset - weekAndDayRowSpace_ - weekHeight_ - dayHeight_ * fiveRow) / (fiveRow - 1);
214         dailySixRowSpace_ =
215             (maxHeight_ - boundaryColOffset - weekAndDayRowSpace_ - weekHeight_ - dayHeight_ * sixRow) / (sixRow - 1);
216     } else {
217         colSpace_ = NormalizeToPx(calendarTheme_.colSpace);
218         dailyFiveRowSpace_ = NormalizeToPx(calendarTheme_.dailyFiveRowSpace);
219         dailySixRowSpace_ = NormalizeToPx(calendarTheme_.dailySixRowSpace);
220     }
221     gregorianCalendarHeight_ = NormalizeToPx(calendarTheme_.gregorianCalendarHeight);
222     workStateWidth_ = NormalizeToPx(calendarTheme_.workStateWidth);
223     workStateHorizontalMovingDistance_ = NormalizeToPx(calendarTheme_.workStateHorizontalMovingDistance);
224     workStateVerticalMovingDistance_ = NormalizeToPx(calendarTheme_.workStateVerticalMovingDistance);
225     auto dayHeight = rowCount_ ? (maxHeight_ - NormalizeToPx(CARD_CALENDAR_TITLE_HEIGHT)) / rowCount_ : 0.0;
226     auto heightDifference = dayWidth_ - dayHeight;
227     if (cardCalendar_ && GreatNotEqual(dayWidth_, dayHeight) && GreatNotEqual(heightDifference, heightOffset)) {
228         needShrink_ = true;
229         focusedAreaRadius_ = (maxHeight_ - NormalizeToPx(CARD_CALENDAR_TITLE_HEIGHT)) / (rowCount_ * 2);
230     } else {
231         needShrink_ = false;
232     }
233 }
234 
235 #ifndef USE_ROSEN_DRAWING
DrawWeekAndDates(SkCanvas * canvas,Offset offset)236 void RosenRenderCalendar::DrawWeekAndDates(SkCanvas* canvas, Offset offset)
237 #else
238 void RosenRenderCalendar::DrawWeekAndDates(RSCanvas* canvas, Offset offset)
239 #endif
240 {
241     uint32_t totalWeek = weekNumbers_.size();
242     uint32_t daysCount = static_cast<uint32_t>(rowCount_) * totalWeek;
243     if (calendarDays_.size() < daysCount) {
244         return;
245     }
246 
247     if (isV2Component_) {
248         offset += { touchCircleStrokeWidth_, 0 };
249     }
250     DrawWeek(canvas, offset);
251 
252     int32_t dateNumber = 0;
253     double dailyRowSpace = 0.0;
254     static const Dimension dateOffset = 4.0_vp;
255     double dayNumberStartY = topPadding_ + weekHeight_ + weekAndDayRowSpace_;
256     if (rowCount_ == 5) { // five line calendar
257         dailyRowSpace = dailyFiveRowSpace_;
258     } else if (rowCount_ == 6) { // six line calendar
259         dailyRowSpace = dailySixRowSpace_;
260     }
261     for (int32_t row = 0; row < rowCount_; row++) {
262         double y = row * (dayHeight_ + dailyRowSpace) + dayNumberStartY;
263         for (uint32_t column = 0; column < totalWeek; column++) {
264             const auto& day = calendarDays_[dateNumber++];
265             double x = textDirection_ == TextDirection::LTR ? column * (dayWidth_ + colSpace_)
266                                                             : (totalWeek - column - 1) * (dayWidth_ + colSpace_);
267             auto dayOffset = Offset(x, y);
268             if (cardCalendar_ || isV2Component_) {
269                 DrawCardCalendar(canvas, offset + Offset(0, NormalizeToPx(dateOffset)), dayOffset, day, dateNumber);
270             } else {
271                 DrawTvCalendar(canvas, offset, dayOffset, day, dateNumber);
272             }
273         }
274     }
275 }
276 
277 #ifndef USE_ROSEN_DRAWING
DrawFocusedArea(SkCanvas * canvas,const Offset & offset,const CalendarDay & day,double x,double y) const278 void RosenRenderCalendar::DrawFocusedArea(
279     SkCanvas* canvas, const Offset& offset, const CalendarDay& day, double x, double y) const
280 #else
281 void RosenRenderCalendar::DrawFocusedArea(
282     RSCanvas* canvas, const Offset& offset, const CalendarDay& day, double x, double y) const
283 #endif
284 {
285     auto pipelineContext = context_.Upgrade();
286     if (!pipelineContext) {
287         LOGE("pipeline context");
288         return;
289     }
290     // start focus animation
291     Offset circleStart =
292         GetGlobalOffset() + Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2, y - NormalizeToPx(1.0_vp));
293     RRect focusAnimationRRect =
294         RRect::MakeRRect(Rect(0.0, 0.0, focusedAreaRadius_ * 2, focusedAreaRadius_ * 2), Radius(focusedAreaRadius_));
295     pipelineContext->ShowFocusAnimation(focusAnimationRRect, Color::WHITE, circleStart);
296 
297     // draw focus background circle
298 #ifndef USE_ROSEN_DRAWING
299     SkPaint paint;
300     paint.setAntiAlias(true);
301 
302     if (SystemProperties::GetDeviceType() == DeviceType::WATCH || type_ == CalendarType::SIMPLE) {
303         if (day.dayMark == "work" && showHoliday_) {
304             paint.setColor(workDayMarkColor_);
305         } else if (day.dayMark == "off" && showHoliday_) {
306             paint.setColor(offDayMarkColor_);
307         } else {
308             paint.setColor(focusedAreaBackgroundColor_);
309         }
310     } else {
311         paint.setColor(focusedAreaBackgroundColor_);
312     }
313     Offset circleCenter =
314         type_ == CalendarType::SIMPLE
315             ? Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_, y + focusedAreaRadius_)
316             : Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_,
317                 y - NormalizeToPx(1.0_vp) + focusedAreaRadius_);
318     Offset bgCircleStart = offset + circleCenter;
319     canvas->drawCircle(bgCircleStart.GetX(), bgCircleStart.GetY(), focusedAreaRadius_, paint);
320 #else
321     RSBrush brush;
322     brush.SetAntiAlias(true);
323 
324     if (SystemProperties::GetDeviceType() == DeviceType::WATCH || type_ == CalendarType::SIMPLE) {
325         if (day.dayMark == "work" && showHoliday_) {
326             brush.SetColor(workDayMarkColor_);
327         } else if (day.dayMark == "off" && showHoliday_) {
328             brush.SetColor(offDayMarkColor_);
329         } else {
330             brush.SetColor(focusedAreaBackgroundColor_);
331         }
332     } else {
333         brush.SetColor(focusedAreaBackgroundColor_);
334     }
335     Offset circleCenter =
336         type_ == CalendarType::SIMPLE
337             ? Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_, y + focusedAreaRadius_)
338             : Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_,
339                 y - NormalizeToPx(1.0_vp) + focusedAreaRadius_);
340     Offset bgCircleStart = offset + circleCenter;
341     canvas->AttachBrush(brush);
342     canvas->DrawCircle(RSPoint(bgCircleStart.GetX(), bgCircleStart.GetY()), focusedAreaRadius_);
343     canvas->DetachBrush();
344 #endif
345 }
346 
347 #ifndef USE_ROSEN_DRAWING
DrawWeek(SkCanvas * canvas,const Offset & offset) const348 void RosenRenderCalendar::DrawWeek(SkCanvas* canvas, const Offset& offset) const
349 #else
350 void RosenRenderCalendar::DrawWeek(RSCanvas* canvas, const Offset& offset) const
351 #endif
352 {
353     uint32_t totalWeek = weekNumbers_.size();
354 #ifndef USE_GRAPHIC_TEXT_GINE
355     txt::TextStyle weekTextStyle;
356     weekTextStyle.color = weekColor_;
357     weekTextStyle.font_size = weekFontSize_;
358     if (cardCalendar_) {
359         weekTextStyle.font_weight = static_cast<txt::FontWeight>(FontWeight::W500);
360     }
361 #else
362     Rosen::TextStyle weekTextStyle;
363     weekTextStyle.color = weekColor_;
364     weekTextStyle.fontSize = weekFontSize_;
365     if (cardCalendar_) {
366         weekTextStyle.fontWeight = static_cast<Rosen::FontWeight>(FontWeight::W500);
367     }
368 #endif
369     weekTextStyle.locale = Localization::GetInstance()->GetFontLocale();
370     static const int32_t daysOfWeek = 7;
371     auto startDayOfWeek = dataAdapter_->GetStartDayOfWeek();
372     for (uint32_t column = 0; column < totalWeek; column++) {
373         double x = textDirection_ == TextDirection::LTR ? column * (weekWidth_ + colSpace_)
374                                                         : (totalWeek - column - 1) * (weekWidth_ + colSpace_);
375         Offset weekNumberOffset = offset + Offset(x, topPadding_);
376         Rect boxRect { weekNumberOffset.GetX(), weekNumberOffset.GetY(), weekWidth_, weekHeight_ };
377         std::string newText { weekNumbers_[(startDayOfWeek + 1) % daysOfWeek] };
378         auto wText = StringUtils::ToWstring(newText);
379         if (wText.size() > 3) {
380             wText = wText.substr(0, 3);
381             newText = StringUtils::ToString(wText);
382         }
383         DrawCalendarText(canvas, newText, weekTextStyle, boxRect);
384         ++startDayOfWeek;
385     }
386 }
387 
388 #ifndef USE_ROSEN_DRAWING
DrawBlurArea(SkCanvas * canvas,const Offset & offset,double x,double y) const389 void RosenRenderCalendar::DrawBlurArea(SkCanvas* canvas, const Offset& offset, double x, double y) const
390 #else
391 void RosenRenderCalendar::DrawBlurArea(RSCanvas* canvas, const Offset& offset, double x, double y) const
392 #endif
393 {
394     auto pipelineContext = GetContext().Upgrade();
395     if (!pipelineContext) {
396         LOGE("pipeline context is null");
397         return;
398     }
399     // start focus animation
400 #ifndef USE_ROSEN_DRAWING
401     SkPaint paint;
402     paint.setAntiAlias(true);
403     paint.setColor(blurAreaBackgroundColor_);
404     Offset circleCenter = Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_,
405         y - NormalizeToPx(1.0_vp) + focusedAreaRadius_);
406     Offset bgCircleStart = offset + circleCenter;
407     canvas->drawCircle(bgCircleStart.GetX(), bgCircleStart.GetY(), focusedAreaRadius_, paint);
408 #else
409     RSBrush brush;
410     brush.SetAntiAlias(true);
411     brush.SetColor(blurAreaBackgroundColor_);
412     Offset circleCenter = Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_,
413         y - NormalizeToPx(1.0_vp) + focusedAreaRadius_);
414     Offset bgCircleStart = offset + circleCenter;
415     canvas->AttachBrush(brush);
416     canvas->DrawCircle(RSPoint(bgCircleStart.GetX(), bgCircleStart.GetY()), focusedAreaRadius_);
417     canvas->DetachBrush();
418 #endif
419 }
420 
421 #ifndef USE_ROSEN_DRAWING
422 #ifndef USE_GRAPHIC_TEXT_GINE
PaintDay(SkCanvas * canvas,const Offset & offset,const CalendarDay & day,txt::TextStyle & textStyle) const423 void RosenRenderCalendar::PaintDay(
424     SkCanvas* canvas, const Offset& offset, const CalendarDay& day, txt::TextStyle& textStyle) const
425 #else
426 void RosenRenderCalendar::PaintDay(
427     SkCanvas* canvas, const Offset& offset, const CalendarDay& day, Rosen::TextStyle& textStyle) const
428 #endif
429 #else
430 #ifndef USE_GRAPHIC_TEXT_GINE
431 void RosenRenderCalendar::PaintDay(
432     RSCanvas* canvas, const Offset& offset, const CalendarDay& day, txt::TextStyle& textStyle) const
433 #else
434 void RosenRenderCalendar::PaintDay(
435     RSCanvas* canvas, const Offset& offset, const CalendarDay& day, Rosen::TextStyle& textStyle) const
436 #endif
437 #endif
438 {
439     // paint day
440     Rect boxRect { offset.GetX(), offset.GetY(), dayWidth_, gregorianCalendarHeight_ };
441     Rect textRect;
442 #ifndef USE_GRAPHIC_TEXT_GINE
443     txt::TextStyle workStateStyle;
444 #else
445     Rosen::TextStyle workStateStyle;
446 #endif
447     if (!day.dayMark.empty() && showHoliday_ && type_ == CalendarType::SIMPLE) {
448 #ifndef USE_ROSEN_DRAWING
449         if (day.dayMark == "work") {
450             textStyle.color = SkColor(calendarTheme_.simpleWorkTextColor.GetValue());
451         } else if (day.dayMark == "off") {
452             textStyle.color = SkColor(calendarTheme_.simpleOffTextColor.GetValue());
453         }
454 #else
455         if (day.dayMark == "work") {
456             textStyle.color = RSColorQuad(calendarTheme_.simpleWorkTextColor.GetValue());
457         } else if (day.dayMark == "off") {
458             textStyle.color = RSColorQuad(calendarTheme_.simpleOffTextColor.GetValue());
459         }
460 #endif
461     }
462     if ((SystemProperties::GetDeviceType() == DeviceType::WATCH || type_ == CalendarType::SIMPLE) && IsToday(day) &&
463         !day.dayMark.empty() && showHoliday_) {
464         auto workStateOffset = offset + Offset(0, NormalizeToPx(calendarTheme_.workStateOffset));
465         boxRect.SetOffset(workStateOffset);
466         workStateStyle.color = Color::WHITE.GetValue();
467 #ifndef USE_GRAPHIC_TEXT_GINE
468         workStateStyle.font_size = dayFontSize_;
469 #else
470         workStateStyle.fontSize = dayFontSize_;
471 #endif
472         DrawCalendarText(canvas, day.dayMarkValue, workStateStyle, boxRect, textRect);
473         return;
474     }
475     if ((SystemProperties::GetDeviceType() == DeviceType::WATCH || type_ == CalendarType::SIMPLE) &&
476         day.month.month != currentMonth_.month) {
477         return;
478     }
479     auto dayStr = std::to_string(day.day);
480     dayStr = Localization::GetInstance()->NumberFormat(day.day);
481     DrawCalendarText(canvas, dayStr, textStyle, boxRect, textRect);
482 
483     if (!day.dayMark.empty() && showHoliday_ && type_ != CalendarType::SIMPLE) {
484         if (cardCalendar_) {
485             InitWorkStateStyle(day, offset, workStateStyle, boxRect);
486         } else {
487 #ifndef USE_GRAPHIC_TEXT_GINE
488             workStateStyle.font_weight = static_cast<txt::FontWeight>(workStateFontWeight_);
489 #else
490             workStateStyle.fontWeight = static_cast<Rosen::FontWeight>(workStateFontWeight_);
491 #endif
492             workStateStyle.locale = Localization::GetInstance()->GetFontLocale();
493             boxRect = { textRect.GetOffset().GetX() + textRect.Width() - workStateHorizontalMovingDistance_,
494                 textRect.GetOffset().GetY() + textRect.Height() - workStateVerticalMovingDistance_, workStateWidth_,
495                 workStateWidth_ };
496             if (day.month.month == currentMonth_.month) {
497                 if (day.dayMark == "work") {
498 #ifndef USE_GRAPHIC_TEXT_GINE
499                     workStateStyle.font_size = workDayMarkSize_;
500 #else
501                     workStateStyle.fontSize = workDayMarkSize_;
502 #endif
503                     workStateStyle.color = workDayMarkColor_;
504                 } else if (day.dayMark == "off") {
505 #ifndef USE_GRAPHIC_TEXT_GINE
506                     workStateStyle.font_size = offDayMarkSize_;
507 #else
508                     workStateStyle.fontSize = offDayMarkSize_;
509 #endif
510                     workStateStyle.color = offDayMarkColor_;
511                 }
512             } else {
513 #ifndef USE_ROSEN_DRAWING
514                 if (day.dayMark == "work") {
515 #ifndef USE_GRAPHIC_TEXT_GINE
516                     workStateStyle.font_size = workDayMarkSize_;
517 #else
518                     workStateStyle.fontSize = workDayMarkSize_;
519 #endif
520                     workStateStyle.color = isV2Component_ ? SkColorSetA(workDayMarkColor_, WEEKEND_TRANSPARENT)
521                                                           : nonCurrentMonthWorkDayMarkColor_;
522                 } else if (day.dayMark == "off") {
523 #ifndef USE_GRAPHIC_TEXT_GINE
524                     workStateStyle.font_size = offDayMarkSize_;
525 #else
526                     workStateStyle.fontSize = offDayMarkSize_;
527 #endif
528                     workStateStyle.color = isV2Component_ ? SkColorSetA(offDayMarkColor_, WEEKEND_TRANSPARENT)
529                                                           : nonCurrentMonthOffDayMarkColor_;
530                 }
531 #else
532                 if (day.dayMark == "work") {
533 #ifndef USE_GRAPHIC_TEXT_GINE
534                     workStateStyle.font_size = workDayMarkSize_;
535 #else
536                     workStateStyle.fontSize = workDayMarkSize_;
537 #endif
538                     workStateStyle.color = isV2Component_ ?
539                         RSColor::ColorQuadSetARGB(WEEKEND_TRANSPARENT, RSColor::ColorQuadGetR(workDayMarkColor_),
540                         RSColor::ColorQuadGetG(workDayMarkColor_), RSColor::ColorQuadGetB(workDayMarkColor_))
541                         : nonCurrentMonthWorkDayMarkColor_;
542                 } else if (day.dayMark == "off") {
543 #ifndef USE_GRAPHIC_TEXT_GINE
544                     workStateStyle.font_size = offDayMarkSize_;
545 #else
546                     workStateStyle.fontSize = offDayMarkSize_;
547 #endif
548                     workStateStyle.color = isV2Component_ ?
549                         RSColor::ColorQuadSetARGB(WEEKEND_TRANSPARENT, RSColor::ColorQuadGetR(offDayMarkColor_),
550                         RSColor::ColorQuadGetG(offDayMarkColor_), RSColor::ColorQuadGetB(offDayMarkColor_))
551                         : nonCurrentMonthOffDayMarkColor_;
552                 }
553 #endif
554             }
555             if (day.focused) {
556                 workStateStyle.color = Color::BLACK.GetValue();
557             }
558             if (isV2Component_ && IsToday(day) && day.touched) {
559                 workStateStyle.color = focusedDayColor_;
560             }
561         }
562         DrawCalendarText(canvas, day.dayMarkValue, workStateStyle, boxRect);
563     }
564 }
565 
566 #ifndef USE_ROSEN_DRAWING
567 #ifndef USE_GRAPHIC_TEXT_GINE
PaintLunarDay(SkCanvas * canvas,const Offset & offset,const CalendarDay & day,const txt::TextStyle & textStyle) const568 void RosenRenderCalendar::PaintLunarDay(
569     SkCanvas* canvas, const Offset& offset, const CalendarDay& day, const txt::TextStyle& textStyle) const
570 #else
571 void RosenRenderCalendar::PaintLunarDay(
572     SkCanvas* canvas, const Offset& offset, const CalendarDay& day, const Rosen::TextStyle& textStyle) const
573 #endif
574 #else
575 #ifndef USE_GRAPHIC_TEXT_GINE
576 void RosenRenderCalendar::PaintLunarDay(
577     RSCanvas* canvas, const Offset& offset, const CalendarDay& day, const txt::TextStyle& textStyle) const
578 #else
579 void RosenRenderCalendar::PaintLunarDay(
580     RSCanvas* canvas, const Offset& offset, const CalendarDay& day, const Rosen::TextStyle& textStyle) const
581 #endif
582 #endif
583 {
584     Rect boxRect;
585     cardCalendar_ || isV2Component_
586         ? boxRect = { offset.GetX(), offset.GetY(), dayWidth_, NormalizeToPx(calendarTheme_.lunarHeight) }
587         : boxRect = { offset.GetX(), offset.GetY(), dayWidth_, dayHeight_ - gregorianCalendarHeight_ };
588     DrawCalendarText(canvas, day.lunarDay, textStyle, boxRect);
589 }
590 
591 #ifndef USE_GRAPHIC_TEXT_GINE
SetNonFocusStyle(const CalendarDay & day,txt::TextStyle & dateTextStyle,txt::TextStyle & lunarTextStyle)592 void RosenRenderCalendar::SetNonFocusStyle(
593     const CalendarDay& day, txt::TextStyle& dateTextStyle, txt::TextStyle& lunarTextStyle)
594 #else
595 void RosenRenderCalendar::SetNonFocusStyle(
596     const CalendarDay& day, Rosen::TextStyle& dateTextStyle, Rosen::TextStyle& lunarTextStyle)
597 #endif
598 {
599 #ifndef USE_ROSEN_DRAWING
600     SkColor dateTextColor;
601     SkColor lunarTextColor;
602     if (day.month.month != currentMonth_.month) {
603         dateTextColor = nonCurrentMonthDayColor_;
604         lunarTextColor =
605             day.markLunarDay ? SkColorSetA(markLunarColor_, WEEKEND_TRANSPARENT) : nonCurrentMonthLunarColor_;
606 #else
607     RSColorQuad dateTextColor;
608     RSColorQuad lunarTextColor;
609     if (day.month.month != currentMonth_.month) {
610         dateTextColor = nonCurrentMonthDayColor_;
611         lunarTextColor = day.markLunarDay ? RSColor::ColorQuadSetARGB(WEEKEND_TRANSPARENT,
612             RSColor::ColorQuadGetR(markLunarColor_), RSColor::ColorQuadGetG(markLunarColor_),
613             RSColor::ColorQuadGetB(markLunarColor_)) : nonCurrentMonthLunarColor_;
614 #endif
615     } else if (IsToday(day)) {
616         dateTextColor = todayDayColor_;
617         lunarTextColor = todayLunarColor_;
618     } else if (IsOffDay(day)) {
619         dateTextColor = weekendDayColor_;
620         lunarTextColor = day.markLunarDay ? markLunarColor_ : weekendLunarColor_;
621     } else {
622         dateTextColor = dayColor_;
623         lunarTextColor = day.markLunarDay ? markLunarColor_ : lunarColor_;
624     }
625 
626     dateTextStyle.color = dateTextColor;
627     lunarTextStyle.color = lunarTextColor;
628 }
629 
630 void RosenRenderCalendar::DrawTouchedArea(RenderContext& context, Offset offset) const
631 {
632     auto canvas = static_cast<RosenRenderContext*>(&context)->GetCanvas();
633     if (!canvas) {
634         LOGE("paint canvas is null");
635         return;
636     }
637     if (IsValid(touchIndex_) && IsToday(calendarDays_[touchIndex_])) {
638         return;
639     }
640     offset += { touchCircleStrokeWidth_, 0 };
641 #ifndef USE_ROSEN_DRAWING
642     SkPaint paint;
643     paint.setAntiAlias(true);
644     paint.setColor(focusedAreaBackgroundColor_);
645     paint.setStrokeWidth(touchCircleStrokeWidth_);
646     paint.setStyle(SkPaint::kStroke_Style);
647 #else
648     RSPen pen;
649     pen.SetAntiAlias(true);
650     pen.SetColor(focusedAreaBackgroundColor_);
651     pen.SetWidth(touchCircleStrokeWidth_);
652 #endif
653     static const Dimension dateOffset = 4.0_vp;
654     const static int32_t totalWeek = 7;
655     int32_t column = touchIndex_ % totalWeek;
656     double dailyRowSpace = rowCount_ == 5 ? dailyFiveRowSpace_ : dailySixRowSpace_;
657     double dayNumberStartY = topPadding_ + weekHeight_ + weekAndDayRowSpace_ + NormalizeToPx(dateOffset);
658     double x = textDirection_ == TextDirection::LTR ? column * (dayWidth_ + colSpace_)
659                                                     : (totalWeek - column - 1) * (dayWidth_ + colSpace_);
660     double y = (touchIndex_ / 7) * (dayHeight_ + dailyRowSpace) + dayNumberStartY;
661     Offset circleCenter = Offset(x - (focusedAreaRadius_ * 2 - dayWidth_) / 2 + focusedAreaRadius_,
662         y - NormalizeToPx(1.0_vp) + focusedAreaRadius_);
663     Offset bgCircleStart = offset + circleCenter;
664 #ifndef USE_ROSEN_DRAWING
665     canvas->drawCircle(bgCircleStart.GetX(), bgCircleStart.GetY(), focusedAreaRadius_, paint);
666 #else
667     canvas->AttachPen(pen);
668     canvas->DrawCircle(RSPoint(bgCircleStart.GetX(), bgCircleStart.GetY()), focusedAreaRadius_);
669     canvas->DetachPen();
670 #endif
671 }
672 
673 #ifndef USE_ROSEN_DRAWING
674 void RosenRenderCalendar::DrawCardCalendar(
675     SkCanvas* canvas, const Offset& offset, const Offset& dayOffset, const CalendarDay& day, int32_t dateNumber)
676 #else
677 void RosenRenderCalendar::DrawCardCalendar(
678     RSCanvas* canvas, const Offset& offset, const Offset& dayOffset, const CalendarDay& day, int32_t dateNumber)
679 #endif
680 {
681 #ifndef USE_GRAPHIC_TEXT_GINE
682     txt::TextStyle dateTextStyle;
683     txt::TextStyle lunarTextStyle;
684 #else
685     Rosen::TextStyle dateTextStyle;
686     Rosen::TextStyle lunarTextStyle;
687 #endif
688     InitTextStyle(dateTextStyle, lunarTextStyle);
689     SetNonFocusStyle(day, dateTextStyle, lunarTextStyle);
690     dateTextStyle.locale = Localization::GetInstance()->GetFontLocale();
691     auto x = dayOffset.GetX();
692     auto y = dayOffset.GetY();
693     if (isV2Component_) {
694         if (calendarController_->FirstSetToday() && IsToday(day) && (day.month.month == currentMonth_.month)) {
695             calendarDays_[day.index].touched = true;
696             touchIndex_ = day.index;
697             calendarController_->SetFirstSetToday(false);
698         }
699     }
700     if (IsToday(day) && (day.month.month == currentMonth_.month)) {
701         dateTextStyle.color = isV2Component_ ? focusedAreaBackgroundColor_ : focusedDayColor_;
702         lunarTextStyle.color = isV2Component_ ? focusedAreaBackgroundColor_ : focusedDayColor_;
703         if (!isV2Component_) {
704             DrawFocusedArea(canvas, offset, day, x, y);
705         }
706     }
707 
708     if (isV2Component_ && day.touched) {
709         if (IsToday(day) && (day.month.month == currentMonth_.month)) {
710             dateTextStyle.color = focusedDayColor_;
711             lunarTextStyle.color = focusedDayColor_;
712             DrawFocusedArea(canvas, offset, day, x, y);
713         }
714     }
715 
716     if (needShrink_) {
717         Offset dateNumberOffset = offset + Offset(x, y + (focusedAreaRadius_ - gregorianCalendarHeight_ / 2));
718         PaintDay(canvas, dateNumberOffset, day, dateTextStyle);
719         return;
720     }
721 
722     auto dayYAxisOffset = calendarTheme_.dayYAxisOffset;
723     Offset dateNumberOffset = offset + Offset(x, y + NormalizeToPx(dayYAxisOffset));
724     PaintDay(canvas, dateNumberOffset, day, dateTextStyle);
725 
726     if (dataAdapter_->ShowLunar() && !day.lunarDay.empty()) {
727         auto lunarDayYAxisOffset = calendarTheme_.lunarDayYAxisOffset;
728         Offset lunarDayOffset = offset + Offset(x, y + NormalizeToPx(lunarDayYAxisOffset));
729         PaintLunarDay(canvas, lunarDayOffset, day, lunarTextStyle);
730     }
731 
732     if (day.isFirstOfLunar) {
733         auto underscoreXAxisOffset = calendarTheme_.underscoreXAxisOffset;
734         auto underscoreYAxisOffset = calendarTheme_.underscoreYAxisOffset;
735         Offset underscoreOffset =
736             offset + Offset(x + NormalizeToPx(underscoreXAxisOffset), y + NormalizeToPx(underscoreYAxisOffset));
737         PaintUnderscore(canvas, underscoreOffset, day);
738     }
739 
740     if (day.hasSchedule) {
741         auto scheduleMarkerXAxisOffset = calendarTheme_.scheduleMarkerXAxisOffset;
742         auto scheduleMarkerYAxisOffset = calendarTheme_.scheduleMarkerYAxisOffset;
743         Offset scheduleMarkerOffset =
744             offset + Offset(x + NormalizeToPx(scheduleMarkerXAxisOffset), y + NormalizeToPx(scheduleMarkerYAxisOffset));
745         PaintScheduleMarker(canvas, scheduleMarkerOffset, day);
746     }
747 }
748 
749 #ifndef USE_ROSEN_DRAWING
750 void RosenRenderCalendar::DrawTvCalendar(
751     SkCanvas* canvas, const Offset& offset, const Offset& dayOffset, const CalendarDay& day, int32_t dateNumber)
752 #else
753 void RosenRenderCalendar::DrawTvCalendar(RSCanvas* canvas,
754     const Offset& offset, const Offset& dayOffset, const CalendarDay& day, int32_t dateNumber)
755 #endif
756 {
757     if ((SystemProperties::GetDeviceType() == DeviceType::WATCH || type_ == CalendarType::SIMPLE) &&
758         day.month.month != currentMonth_.month) {
759         return;
760     }
761 #ifndef USE_GRAPHIC_TEXT_GINE
762     txt::TextStyle dateTextStyle;
763     txt::TextStyle lunarTextStyle;
764 #else
765     Rosen::TextStyle dateTextStyle;
766     Rosen::TextStyle lunarTextStyle;
767 #endif
768     InitTextStyle(dateTextStyle, lunarTextStyle);
769     dateTextStyle.locale = Localization::GetInstance()->GetFontLocale();
770     lunarTextStyle.locale = Localization::GetInstance()->GetFontLocale();
771 
772     auto renderSwiper = calendarController_->GetRenderSwiper();
773     if (!renderSwiper) {
774         return;
775     }
776     int32_t selectedDay = selectedDayNumber_ + firstDayIndex_ - 1;
777     auto x = dayOffset.GetX();
778     auto y = dayOffset.GetY();
779     if (SystemProperties::GetDeviceType() == DeviceType::WATCH || type_ == CalendarType::SIMPLE) {
780         if (IsToday(day) && (day.month.month == currentMonth_.month)) {
781             dateTextStyle.color = focusedDayColor_;
782             lunarTextStyle.color = focusedDayColor_;
783             DrawFocusedArea(canvas, offset, day, x, y);
784         } else {
785             SetNonFocusStyle(day, dateTextStyle, lunarTextStyle);
786         }
787     } else {
788         if (day.focused && day.month.month == currentMonth_.month && !renderSwiper->GetMoveStatus() &&
789             indexOfContainer_ == calendarController_->GetCurrentIndex()) {
790             dateTextStyle.color = focusedDayColor_;
791             lunarTextStyle.color = focusedLunarColor_;
792             DrawFocusedArea(canvas, offset, day, x, y);
793         } else {
794             SetNonFocusStyle(day, dateTextStyle, lunarTextStyle);
795         }
796     }
797 
798     if (selectedDay == (dateNumber - 1) && !calendarFocusStatus_ && !renderSwiper->GetMoveStatus() &&
799         hasRequestFocus_) {
800         DrawBlurArea(canvas, offset, x, y);
801     }
802 
803     if (dataAdapter_->ShowLunar() && !day.lunarDay.empty()) {
804         // paint day
805         Offset dateNumberOffset = offset + Offset(x, y);
806         PaintDay(canvas, dateNumberOffset, day, dateTextStyle);
807 
808         // paint lunar day
809         Offset lunarDayOffset = offset + Offset(x, y + gregorianCalendarHeight_);
810         PaintLunarDay(canvas, lunarDayOffset, day, lunarTextStyle);
811     } else {
812         // when there is no lunar calendar, the date is displayed in the center
813         Offset dateNumberOffset = offset + Offset(x, y + (focusedAreaRadius_ - gregorianCalendarHeight_ / 2));
814         PaintDay(canvas, dateNumberOffset, day, dateTextStyle);
815     }
816 }
817 
818 #ifndef USE_GRAPHIC_TEXT_GINE
819 void RosenRenderCalendar::InitTextStyle(txt::TextStyle& dateTextStyle, txt::TextStyle& lunarTextStyle)
820 {
821     dateTextStyle.font_size = dayFontSize_;
822     dateTextStyle.font_weight = static_cast<txt::FontWeight>(dayFontWeight_);
823 
824     lunarTextStyle.font_size = lunarDayFontSize_;
825     lunarTextStyle.font_weight = static_cast<txt::FontWeight>(lunarDayFontWeight_);
826 }
827 #else
828 void RosenRenderCalendar::InitTextStyle(Rosen::TextStyle& dateTextStyle, Rosen::TextStyle& lunarTextStyle)
829 {
830     dateTextStyle.fontSize = dayFontSize_;
831     dateTextStyle.fontWeight = static_cast<Rosen::FontWeight>(dayFontWeight_);
832 
833     lunarTextStyle.fontSize = lunarDayFontSize_;
834     lunarTextStyle.fontWeight = static_cast<Rosen::FontWeight>(lunarDayFontWeight_);
835 }
836 #endif
837 
838 #ifndef USE_ROSEN_DRAWING
839 void RosenRenderCalendar::PaintUnderscore(SkCanvas* canvas, const Offset& offset, const CalendarDay& day)
840 {
841     auto underscoreWidth = calendarTheme_.underscoreWidth;
842     auto underscoreLength = calendarTheme_.underscoreLength;
843     SkPaint paint;
844     SkColor color;
845     if (day.month.month != currentMonth_.month) {
846         color = SkColorSetA(focusedAreaBackgroundColor_, NON_CURRENT_MONTH_TRANSPARENT);
847     } else if (IsToday(day)) {
848         color = isV2Component_ && !day.touched ? SkColorSetA(focusedAreaBackgroundColor_, CURRENT_MONTH_TRANSPARENT)
849                                                : focusedDayColor_;
850     } else if (day.weekend) {
851         color = SkColorSetA(focusedAreaBackgroundColor_, WEEKEND_TRANSPARENT);
852     } else {
853         color = SkColorSetA(focusedAreaBackgroundColor_, CURRENT_MONTH_TRANSPARENT);
854     }
855     paint.setAntiAlias(true);
856     paint.setColor(color);
857     paint.setStyle(SkPaint::Style::kStroke_Style);
858     paint.setStrokeWidth(NormalizeToPx(underscoreWidth));
859     canvas->drawLine(offset.GetX(), offset.GetY() + NormalizeToPx(underscoreWidth) / 2,
860         offset.GetX() + NormalizeToPx(underscoreLength), offset.GetY() + NormalizeToPx(underscoreWidth) / 2, paint);
861 }
862 #else
863 void RosenRenderCalendar::PaintUnderscore(RSCanvas* canvas, const Offset& offset, const CalendarDay& day)
864 {
865     auto underscoreWidth = calendarTheme_.underscoreWidth;
866     auto underscoreLength = calendarTheme_.underscoreLength;
867     RSPen pen;
868     RSColorQuad color;
869     if (day.month.month != currentMonth_.month) {
870         color = RSColor::ColorQuadSetARGB(NON_CURRENT_MONTH_TRANSPARENT,
871             RSColor::ColorQuadGetR(focusedAreaBackgroundColor_), RSColor::ColorQuadGetG(focusedAreaBackgroundColor_),
872             RSColor::ColorQuadGetB(focusedAreaBackgroundColor_));
873     } else if (IsToday(day)) {
874         color = isV2Component_ && !day.touched
875             ? RSColor::ColorQuadSetARGB(CURRENT_MONTH_TRANSPARENT, RSColor::ColorQuadGetR(focusedAreaBackgroundColor_),
876             RSColor::ColorQuadGetG(focusedAreaBackgroundColor_), RSColor::ColorQuadGetB(focusedAreaBackgroundColor_))
877             : focusedDayColor_;
878     } else if (day.weekend) {
879         color = RSColor::ColorQuadSetARGB(WEEKEND_TRANSPARENT, RSColor::ColorQuadGetR(focusedAreaBackgroundColor_),
880             RSColor::ColorQuadGetG(focusedAreaBackgroundColor_), RSColor::ColorQuadGetB(focusedAreaBackgroundColor_));
881     } else {
882         color = RSColor::ColorQuadSetARGB(CURRENT_MONTH_TRANSPARENT,
883             RSColor::ColorQuadGetR(focusedAreaBackgroundColor_), RSColor::ColorQuadGetG(focusedAreaBackgroundColor_),
884             RSColor::ColorQuadGetB(focusedAreaBackgroundColor_));
885     }
886     pen.SetAntiAlias(true);
887     pen.SetColor(color);
888     pen.SetWidth(NormalizeToPx(underscoreWidth));
889     canvas->AttachPen(pen);
890     canvas->DrawLine(RSPoint(offset.GetX(), offset.GetY() + NormalizeToPx(underscoreWidth) / 2),
891         RSPoint(
892             offset.GetX() + NormalizeToPx(underscoreLength), offset.GetY() + NormalizeToPx(underscoreWidth) / 2));
893     canvas->DetachPen();
894 }
895 #endif
896 
897 #ifndef USE_ROSEN_DRAWING
898 void RosenRenderCalendar::PaintScheduleMarker(SkCanvas* canvas, const Offset& offset, const CalendarDay& day)
899 {
900     auto scheduleMarkerRadius = calendarTheme_.scheduleMarkerRadius;
901     SkPaint paint;
902     SkColor color;
903     if (day.month.month != currentMonth_.month) {
904         color = SkColorSetA(focusedAreaBackgroundColor_, NON_CURRENT_MONTH_TRANSPARENT);
905     } else if (IsToday(day)) {
906         color = isV2Component_ && !day.touched ? SkColorSetA(focusedAreaBackgroundColor_, SCHEDULE_MARKER_TRANSPARENT)
907                                                : focusedDayColor_;
908     } else {
909         color = SkColorSetA(focusedAreaBackgroundColor_, SCHEDULE_MARKER_TRANSPARENT);
910     }
911     paint.setAntiAlias(true);
912     paint.setColor(color);
913     canvas->drawCircle(offset.GetX(), offset.GetY(), NormalizeToPx(scheduleMarkerRadius), paint);
914 }
915 #else
916 void RosenRenderCalendar::PaintScheduleMarker(RSCanvas* canvas, const Offset& offset, const CalendarDay& day)
917 {
918     auto scheduleMarkerRadius = calendarTheme_.scheduleMarkerRadius;
919     RSBrush brush;
920     RSColorQuad color;
921     if (day.month.month != currentMonth_.month) {
922         color = RSColor::ColorQuadSetARGB(NON_CURRENT_MONTH_TRANSPARENT,
923             RSColor::ColorQuadGetR(focusedAreaBackgroundColor_), RSColor::ColorQuadGetG(focusedAreaBackgroundColor_),
924             RSColor::ColorQuadGetB(focusedAreaBackgroundColor_));
925     } else if (IsToday(day)) {
926         color = isV2Component_ && !day.touched
927             ? RSColor::ColorQuadSetARGB(SCHEDULE_MARKER_TRANSPARENT,
928             RSColor::ColorQuadGetR(focusedAreaBackgroundColor_), RSColor::ColorQuadGetG(focusedAreaBackgroundColor_),
929             RSColor::ColorQuadGetB(focusedAreaBackgroundColor_)) : focusedDayColor_;
930     } else {
931         color = RSColor::ColorQuadSetARGB(SCHEDULE_MARKER_TRANSPARENT,
932             RSColor::ColorQuadGetR(focusedAreaBackgroundColor_), RSColor::ColorQuadGetG(focusedAreaBackgroundColor_),
933             RSColor::ColorQuadGetB(focusedAreaBackgroundColor_));
934     }
935     brush.SetAntiAlias(true);
936     brush.SetColor(color);
937     canvas->AttachBrush(brush);
938     canvas->DrawCircle(RSPoint(offset.GetX(), offset.GetY()), NormalizeToPx(scheduleMarkerRadius));
939     canvas->DetachBrush();
940 }
941 #endif
942 
943 #ifndef USE_GRAPHIC_TEXT_GINE
944 void RosenRenderCalendar::InitWorkStateStyle(
945     const CalendarDay& day, const Offset& offset, txt::TextStyle& workStateStyle, Rect& boxRect) const
946 {
947     workStateStyle.font_weight = static_cast<txt::FontWeight>(FontWeight::W500);
948 #else
949 void RosenRenderCalendar::InitWorkStateStyle(
950     const CalendarDay& day, const Offset& offset, Rosen::TextStyle& workStateStyle, Rect& boxRect) const
951 {
952     workStateStyle.fontWeight = static_cast<Rosen::FontWeight>(FontWeight::W500);
953 #endif
954     workStateStyle.locale = Localization::GetInstance()->GetFontLocale();
955     static const Dimension workStateWidth = 8.0_vp;
956     static const int32_t twoDigitMaker = 10;
957     static const Dimension OneDigitXAxisOffset = 26.0_vp;
958     static const Dimension workStateYAxisOffset = 6.0_vp;
959     static const Dimension twoDigitXAxisOffset = 31.0_vp;
960     if (day.day < twoDigitMaker) {
961         boxRect = { offset.GetX() + NormalizeToPx(OneDigitXAxisOffset),
962             offset.GetY() + NormalizeToPx(workStateYAxisOffset), NormalizeToPx(workStateWidth),
963             NormalizeToPx(workStateWidth) };
964     } else {
965         boxRect = { offset.GetX() + NormalizeToPx(twoDigitXAxisOffset),
966             offset.GetY() + NormalizeToPx(workStateYAxisOffset), NormalizeToPx(workStateWidth),
967             NormalizeToPx(workStateWidth) };
968     }
969 
970 #ifndef USE_GRAPHIC_TEXT_GINE
971     workStateStyle.font_size = NormalizeToPx(workStateWidth);
972 #else
973     workStateStyle.fontSize = NormalizeToPx(workStateWidth);
974 #endif
975 
976     if (day.month.month != currentMonth_.month) {
977 #ifndef USE_ROSEN_DRAWING
978         auto offColor = SkColorSetA(markLunarColor_, WEEKEND_TRANSPARENT);
979         auto workColor = SkColorSetA(workDayMarkColor_, WEEKEND_TRANSPARENT);
980 #else
981         auto offColor = RSColor::ColorQuadSetARGB(WEEKEND_TRANSPARENT, RSColor::ColorQuadGetR(markLunarColor_),
982             RSColor::ColorQuadGetG(markLunarColor_), RSColor::ColorQuadGetB(markLunarColor_));
983         auto workColor = RSColor::ColorQuadSetARGB(WEEKEND_TRANSPARENT, RSColor::ColorQuadGetR(workDayMarkColor_),
984             RSColor::ColorQuadGetG(workDayMarkColor_), RSColor::ColorQuadGetB(workDayMarkColor_));
985 #endif
986         SetWorkStateStyle(day, workColor, offColor, workStateStyle);
987     } else if (IsToday(day)) {
988         SetWorkStateStyle(day, focusedDayColor_, focusedDayColor_, workStateStyle);
989     } else if (IsOffDay(day)) {
990         auto offColor = markLunarColor_;
991         auto workColor = workDayMarkColor_;
992         SetWorkStateStyle(day, workColor, offColor, workStateStyle);
993     } else {
994         SetWorkStateStyle(day, workDayMarkColor_, markLunarColor_, workStateStyle);
995     }
996 }
997 
998 #ifndef USE_ROSEN_DRAWING
999 #ifndef USE_GRAPHIC_TEXT_GINE
1000 void RosenRenderCalendar::SetWorkStateStyle(
1001     const CalendarDay& day, SkColor workColor, SkColor offColor, txt::TextStyle& workStateStyle) const
1002 #else
1003 void RosenRenderCalendar::SetWorkStateStyle(
1004     const CalendarDay& day, SkColor workColor, SkColor offColor, Rosen::TextStyle& workStateStyle) const
1005 #endif
1006 #else
1007 #ifndef USE_GRAPHIC_TEXT_GINE
1008 void RosenRenderCalendar::SetWorkStateStyle(const CalendarDay& day, RSColorQuad workColor,
1009     RSColorQuad offColor, txt::TextStyle& workStateStyle) const
1010 #else
1011 void RosenRenderCalendar::SetWorkStateStyle(
1012     const CalendarDay& day, SkColor workColor, RSColorQuad offColor, Rosen::TextStyle& workStateStyle) const
1013 #endif
1014 #endif
1015 {
1016     if (day.dayMark == "work") {
1017         workStateStyle.color = workColor;
1018     } else if (day.dayMark == "off") {
1019         workStateStyle.color = offColor;
1020     }
1021 }
1022 
1023 void RosenRenderCalendar::SetCalendarTheme()
1024 {
1025     auto theme = GetTheme<CalendarTheme>();
1026     if (cardCalendar_ && theme) {
1027         calendarTheme_ = theme->GetCardCalendarTheme();
1028     }
1029 #ifndef USE_ROSEN_DRAWING
1030     touchColor_ = SkColor(calendarTheme_.touchColor.GetValue());
1031     weekColor_ = SkColor(calendarTheme_.weekColor.GetValue());
1032     dayColor_ = SkColor(calendarTheme_.dayColor.GetValue());
1033     lunarColor_ = SkColor(calendarTheme_.lunarColor.GetValue());
1034     weekendDayColor_ = SkColor(calendarTheme_.weekendDayColor.GetValue());
1035     weekendLunarColor_ = SkColor(calendarTheme_.weekendLunarColor.GetValue());
1036     todayDayColor_ = SkColor(calendarTheme_.todayColor.GetValue());
1037     todayLunarColor_ = SkColor(calendarTheme_.todayLunarColor.GetValue());
1038     nonCurrentMonthDayColor_ = SkColor(calendarTheme_.nonCurrentMonthDayColor.GetValue());
1039     nonCurrentMonthLunarColor_ = SkColor(calendarTheme_.nonCurrentMonthLunarColor.GetValue());
1040     workDayMarkColor_ = SkColor(calendarTheme_.workDayMarkColor.GetValue());
1041     offDayMarkColor_ = SkColor(calendarTheme_.offDayMarkColor.GetValue());
1042     nonCurrentMonthWorkDayMarkColor_ = SkColor(calendarTheme_.nonCurrentMonthWorkDayMarkColor.GetValue());
1043     nonCurrentMonthOffDayMarkColor_ = SkColor(calendarTheme_.nonCurrentMonthOffDayMarkColor.GetValue());
1044     focusedDayColor_ = SkColor(calendarTheme_.focusedDayColor.GetValue());
1045     focusedLunarColor_ = SkColor(calendarTheme_.focusedLunarColor.GetValue());
1046     focusedAreaBackgroundColor_ = SkColor(calendarTheme_.focusedAreaBackgroundColor.GetValue());
1047     blurAreaBackgroundColor_ = SkColor(calendarTheme_.blurAreaBackgroundColor.GetValue());
1048     markLunarColor_ = SkColor(calendarTheme_.markLunarColor.GetValue());
1049 #else
1050     touchColor_ = RSColorQuad(calendarTheme_.touchColor.GetValue());
1051     weekColor_ = RSColorQuad(calendarTheme_.weekColor.GetValue());
1052     dayColor_ = RSColorQuad(calendarTheme_.dayColor.GetValue());
1053     lunarColor_ = RSColorQuad(calendarTheme_.lunarColor.GetValue());
1054     weekendDayColor_ = RSColorQuad(calendarTheme_.weekendDayColor.GetValue());
1055     weekendLunarColor_ = RSColorQuad(calendarTheme_.weekendLunarColor.GetValue());
1056     todayDayColor_ = RSColorQuad(calendarTheme_.todayColor.GetValue());
1057     todayLunarColor_ = RSColorQuad(calendarTheme_.todayLunarColor.GetValue());
1058     nonCurrentMonthDayColor_ = RSColorQuad(calendarTheme_.nonCurrentMonthDayColor.GetValue());
1059     nonCurrentMonthLunarColor_ = RSColorQuad(calendarTheme_.nonCurrentMonthLunarColor.GetValue());
1060     workDayMarkColor_ = RSColorQuad(calendarTheme_.workDayMarkColor.GetValue());
1061     offDayMarkColor_ = RSColorQuad(calendarTheme_.offDayMarkColor.GetValue());
1062     nonCurrentMonthWorkDayMarkColor_ = RSColorQuad(calendarTheme_.nonCurrentMonthWorkDayMarkColor.GetValue());
1063     nonCurrentMonthOffDayMarkColor_ = RSColorQuad(calendarTheme_.nonCurrentMonthOffDayMarkColor.GetValue());
1064     focusedDayColor_ = RSColorQuad(calendarTheme_.focusedDayColor.GetValue());
1065     focusedLunarColor_ = RSColorQuad(calendarTheme_.focusedLunarColor.GetValue());
1066     focusedAreaBackgroundColor_ = RSColorQuad(calendarTheme_.focusedAreaBackgroundColor.GetValue());
1067     blurAreaBackgroundColor_ = RSColorQuad(calendarTheme_.blurAreaBackgroundColor.GetValue());
1068     markLunarColor_ = RSColorQuad(calendarTheme_.markLunarColor.GetValue());
1069 #endif
1070     dayFontWeight_ = StringUtils::StringToFontWeight(calendarTheme_.dayFontWeight);
1071     lunarDayFontWeight_ = StringUtils::StringToFontWeight(calendarTheme_.lunarDayFontWeight);
1072     workStateFontWeight_ = StringUtils::StringToFontWeight(calendarTheme_.workStateFontWeight);
1073 }
1074 
1075 bool RosenRenderCalendar::IsOffDay(const CalendarDay& dayInfo) const
1076 {
1077     auto weekday = Date::CalculateWeekDay(dayInfo.month.year, dayInfo.month.month + 1, dayInfo.day);
1078     std::vector<std::string> days;
1079     StringUtils::StringSplitter(offDays_, ',', days);
1080     bool setOffDay = true;
1081     for (const auto& day : days) {
1082         auto num = StringUtils::StringToInt(day);
1083         if (num < 0 || num > 6) {
1084             setOffDay = false;
1085             break;
1086         }
1087         if (num == weekday) {
1088             return true;
1089         }
1090     }
1091     if (!setOffDay) {
1092         if (weekday == 5 || weekday == 6) { // set default weekend
1093             return true;
1094         }
1095     }
1096     return false;
1097 }
1098 
1099 void RosenRenderCalendar::AddContentLayer(RenderContext& context)
1100 {
1101 #ifdef OHOS_PLATFORM
1102     auto canvas = static_cast<RosenRenderContext*>(&context)->GetCanvas();
1103     if (!drawCmdList_) {
1104         return;
1105     }
1106     drawCmdList_->Playback(*canvas);
1107 #endif
1108 }
1109 
1110 } // namespace OHOS::Ace
1111