xref: /MusicPlayer2/MusicPlayer2/CUIDrawer.cpp (revision 3bbfe61493ac5233d7ce8ca64697d34a45aa45b0)
1 #include "stdafx.h"
2 #include "CUIDrawer.h"
3 #include "MusicPlayer2.h"
4 
5 
6 CUIDrawer::CUIDrawer(UIColors& colors)
7     : m_colors(colors)
8 {
9 }
10 
11 
12 CUIDrawer::~CUIDrawer()
13 {
14 }
15 
16 void CUIDrawer::DrawLryicCommon(CRect rect, Alignment align)
17 {
18     SetDrawArea(rect);
19 
20     if (!IsDrawMultiLine(rect.Height()))
21         DrawLyricTextSingleLine(rect, true, align);
22     else
23         DrawLyricTextMultiLine(rect, align);
24 }
25 
26 int CUIDrawer::GetLyricTextHeight() const
27 {
28     //�����ı��߶�
29     if(!m_for_cortana_lyric)
30         m_pDC->SelectObject(&theApp.m_font_set.lyric.GetFont(theApp.m_ui_data.full_screen));
31     else
32         m_pDC->SelectObject(&theApp.m_font_set.cortana.GetFont());
33     return m_pDC->GetTextExtent(L"��").cy;	//���ݵ�ǰ���������ü����ı��ĸ߶�
34 }
35 
36 void CUIDrawer::Create(CDC * pDC, CWnd * pMainWnd)
37 {
38     CDrawCommon::Create(pDC, pMainWnd);
39 }
40 
41 bool CUIDrawer::IsDrawMultiLine(int height) const
42 {
43     return height >= static_cast<int>(GetLyricTextHeight() * 3.5);
44 }
45 
46 void CUIDrawer::SetForCortanaLyric(bool for_cortana_lyric)
47 {
48     m_for_cortana_lyric = for_cortana_lyric;
49 }
50 
51 void CUIDrawer::DrawLyricTextMultiLine(CRect lyric_area, Alignment align)
52 {
53     int line_space{};
54     if (m_for_cortana_lyric)
55     {
56         line_space = theApp.DPI(4);
57     }
58     else
59     {
60         line_space = theApp.m_app_setting_data.lyric_line_space;
61         if (theApp.m_ui_data.full_screen)
62             line_space = static_cast<int>(line_space * CONSTVAL::FULL_SCREEN_ZOOM_FACTOR);
63     }
64 
65     int lyric_height = GetLyricTextHeight() + line_space;			//�ı��߶ȼ����м��
66     int lyric_height2 = lyric_height * 2 + line_space;		//��������ĸ�ʸ߶�
67 
68     SetLyricFont();
69     if (CPlayerUIHelper::IsMidiLyric())
70     {
71         wstring current_lyric{ CPlayer::GetInstance().GetMidiLyric() };
72         DrawWindowText(lyric_area, current_lyric.c_str(), m_colors.color_text, Alignment::CENTER, false, true);
73     }
74     else if (CPlayer::GetInstance().m_Lyrics.IsEmpty())
75     {
76         DrawWindowText(lyric_area, CCommon::LoadText(IDS_NO_LYRIC_INFO), m_colors.color_text_2, Alignment::CENTER);
77     }
78     else
79     {
80         //CRect arect{ lyric_area };		//һ�и�ʵľ�������
81         //arect.bottom = arect.top + lyric_height;
82         //vector<CRect> rects(CPlayer::GetInstance().m_Lyrics.GetLyricCount() + 1, arect);
83         //Ϊÿһ���ʴ���һ�����Σ�������������
84         vector<CRect> rects;
85         int lyric_count = CPlayer::GetInstance().m_Lyrics.GetLyricCount() + 1;		//��ȡ������������ڵ�һ�и����Ҫ��ʾ���⣬��������Ҫ+1��
86         for (int i{}; i < lyric_count; i++)
87         {
88             CRect arect{ lyric_area };
89             if (!CPlayer::GetInstance().m_Lyrics.GetLyric(i).translate.empty() && theApp.m_ui_data.show_translate)
90                 arect.bottom = arect.top + lyric_height2;
91             else
92                 arect.bottom = arect.top + lyric_height;
93             rects.push_back(arect);
94         }
95         int center_pos = (lyric_area.top + lyric_area.bottom) / 2;		//������������y����
96         Time time{ CPlayer::GetInstance().GetCurrentPosition() };		//��ǰ����ʱ��
97         int lyric_index = CPlayer::GetInstance().m_Lyrics.GetLyricIndex(time) + 1;		//��ǰ��ʵ���ţ���ʵĵ�һ��GetLyricIndex���ص���0��������ʾʱ��һ����Ҫ��ʾ���⣬��������Ҫ+1��
98         int progress = CPlayer::GetInstance().m_Lyrics.GetLyricProgress(time);		//��ǰ��ʽ��ȣ���ΧΪ0~1000��
99         int y_progress;			//��ǰ�����y���ϵĽ���
100         if (!CPlayer::GetInstance().m_Lyrics.GetLyric(lyric_index).translate.empty() && theApp.m_ui_data.show_translate)
101             y_progress = progress * lyric_height2 / 1000;
102         else
103             y_progress = progress * lyric_height / 1000;
104         //int start_pos = center_pos - y_progress - (lyric_index + 1)*lyric_height;		//��1���ʵ���ʼy����
105         //�����1���ʵ���ʼy����
106         //���ڵ�ǰ�����Ҫ��ʾ�ڸ�����������λ�ã���˴�����λ�ÿ�ʼ����ȥ��ǰ�����Y���ϵĽ���
107         //�����μ�ȥ֮ǰÿһ���ʵĸ߶ȣ����õ��˵�һ���ʵ���ʼλ��
108         int start_pos;
109         start_pos = center_pos - y_progress;
110         for (int i{ lyric_index - 1 }; i >= 0; i--)
111         {
112             if (theApp.m_ui_data.show_translate && !CPlayer::GetInstance().m_Lyrics.GetLyric(i).translate.empty())
113                 start_pos -= lyric_height2;
114             else
115                 start_pos -= lyric_height;
116         }
117 
118         //���λ���ÿһ����
119         for (size_t i{}; i < rects.size(); i++)
120         {
121             //����ÿһ���ʵ�λ��
122             if (i == 0)
123                 rects[i].MoveToY(start_pos);
124             else
125                 rects[i].MoveToY(rects[i - 1].bottom);
126             //���Ƹ���ı�
127             if (!(rects[i] & lyric_area).IsRectEmpty())		//ֻ�е�һ���ʵľ�������͸������ľ����н���ʱ���Ż��Ƹ��
128             {
129                 //���ø���ı��ͷ����ı��ľ�������
130                 CRect rect_text{ rects[i] };
131                 CRect rect_translate;
132                 if (!CPlayer::GetInstance().m_Lyrics.GetLyric(i).translate.empty() && theApp.m_ui_data.show_translate)
133                 {
134                     rect_text.MoveToY(rect_text.top + line_space);
135                     rect_text.bottom = rect_text.top + GetLyricTextHeight();
136                     rect_translate = rect_text;
137                     rect_translate.MoveToY(rect_text.bottom + line_space);
138                 }
139 
140                 if (i == lyric_index && progress < 1000)		//�������ڲ��ŵĸ��
141                 {
142                     CLyrics::Lyric lyric = CPlayer::GetInstance().m_Lyrics.GetLyric(i);
143                     //����ʵ���ı��ӷǸ��������仯������Ч��
144                     int last_time_span = time - lyric.time;     //��ǰ���ŵĸ���ѳ�����ʱ��
145                     int fade_percent = last_time_span / 8;         //������ɫ�����仯�İٷֱȣ�����Խ�������ʱ��Խ����10��Ϊ1��
146                     COLORREF text_color = CColorConvert::GetGradientColor(m_colors.color_text_2, m_colors.color_text, fade_percent);
147                     //���Ƹ���ı�
148                     SetLyricFont();
149                     if (theApp.m_lyric_setting_data.lyric_karaoke_disp)
150                         DrawWindowText(rect_text, lyric.text.c_str(), m_colors.color_text, m_colors.color_text_2, progress, align, true);
151                     else
152                         DrawWindowText(rect_text, lyric.text.c_str(), text_color, text_color, progress, align, true);
153                     //���Ʒ����ı�
154                     if (!lyric.translate.empty() && theApp.m_ui_data.show_translate)
155                     {
156                         SetLyricFontTranslated();
157                         DrawWindowText(rect_translate, CPlayer::GetInstance().m_Lyrics.GetLyric(i).translate.c_str(), text_color, text_color, progress, align, true);
158                     }
159                 }
160                 else		//���Ʒ����ڲ��ŵĸ��
161                 {
162                     SetLyricFont();
163                     COLORREF text_color;
164                     if (i == lyric_index - 1)      //������һ���ʣ�����ʵ����һ������ɫ�Ӹ��������仯���Ǹ���Ч����
165                     {
166                         CLyrics::Lyric playing_lyric = CPlayer::GetInstance().m_Lyrics.GetLyric(lyric_index);
167                         int last_time_span = time - playing_lyric.time;     //��ǰ���ŵĸ���ѳ�����ʱ��
168                         int fade_percent = last_time_span / 20;         //������ɫ�����仯�İٷֱȣ�������ʱ��Ϊ2000����ʱΪ100%������ɫ�����仯��ʱ��Ϊ2��
169                         text_color = CColorConvert::GetGradientColor(m_colors.color_text, m_colors.color_text_2, fade_percent);
170                     }
171                     else
172                     {
173                         text_color = m_colors.color_text_2;
174                     }
175                     //���Ƹ���ı�
176                     DrawWindowText(rect_text, CPlayer::GetInstance().m_Lyrics.GetLyric(i).text.c_str(), text_color, align, true);
177                     //���Ʒ����ı�
178                     if (!CPlayer::GetInstance().m_Lyrics.GetLyric(i).translate.empty() && theApp.m_ui_data.show_translate)
179                     {
180                         SetLyricFontTranslated();
181                         DrawWindowText(rect_translate, CPlayer::GetInstance().m_Lyrics.GetLyric(i).translate.c_str(), text_color, align, true);
182                     }
183                 }
184             }
185         }
186     }
187 }
188 
189 void CUIDrawer::DrawLyricTextSingleLine(CRect rect, bool double_line, Alignment align)
190 {
191     SetLyricFont();
192 
193     if (CPlayerUIHelper::IsMidiLyric())
194     {
195         wstring current_lyric{ CPlayer::GetInstance().GetMidiLyric() };
196         DrawWindowText(rect, current_lyric.c_str(), m_colors.color_text, Alignment::CENTER, false, true);
197     }
198     else if (CPlayer::GetInstance().m_Lyrics.IsEmpty())
199     {
200         DrawWindowText(rect, CCommon::LoadText(IDS_NO_LYRIC_INFO), m_colors.color_text_2, Alignment::CENTER);
201     }
202     else
203     {
204         CRect lyric_rect = rect;
205         Time time = CPlayer::GetInstance().GetCurrentPosition();
206         CLyrics::Lyric current_lyric{ CPlayer::GetInstance().m_Lyrics.GetLyric(time, 0) };	//��ȡ�����
207         if (current_lyric.text.empty())		//�����ǰ���Ϊ�հף�����ʾΪʡ�Ժ�
208             current_lyric.text = CCommon::LoadText(IDS_DEFAULT_LYRIC_TEXT);
209         int progress{ CPlayer::GetInstance().m_Lyrics.GetLyricProgress(time) };		//��ȡ��ǰ��ʽ��ȣ���ΧΪ0~1000��
210 
211         //˫����ʾ���
212         if (double_line && (!CPlayer::GetInstance().m_Lyrics.IsTranslated() || !theApp.m_ui_data.show_translate) && rect.Height() > static_cast<int>(GetLyricTextHeight() * 1.73))
213         {
214             wstring next_lyric_text = CPlayer::GetInstance().m_Lyrics.GetLyric(time, 1).text;
215             if (next_lyric_text.empty())
216                 next_lyric_text = CCommon::LoadText(IDS_DEFAULT_LYRIC_TEXT);
217             //����ʵ���ı��ӷǸ��������仯������Ч��
218             int last_time_span = time - current_lyric.time;     //��ǰ���ŵĸ���ѳ�����ʱ��
219             int fade_percent = last_time_span / 8;         //������ɫ�����仯�İٷֱȣ�����Խ�������ʱ��Խ����10��Ϊ1��
220             DrawLyricDoubleLine(lyric_rect, current_lyric.text.c_str(), next_lyric_text.c_str(), progress, fade_percent);
221         }
222         else
223         {
224             if (theApp.m_ui_data.show_translate && !current_lyric.translate.empty() && rect.Height() > static_cast<int>(GetLyricTextHeight() * 1.73))
225             {
226                 lyric_rect.bottom = lyric_rect.top + rect.Height() / 2;
227                 CRect translate_rect = lyric_rect;
228                 translate_rect.MoveToY(lyric_rect.bottom);
229 
230                 SetLyricFontTranslated();
231                 DrawWindowText(translate_rect, current_lyric.translate.c_str(), m_colors.color_text, m_colors.color_text, progress, align, true);
232             }
233 
234             SetLyricFont();
235             if (theApp.m_lyric_setting_data.lyric_karaoke_disp)
236                 DrawWindowText(lyric_rect, current_lyric.text.c_str(), m_colors.color_text, m_colors.color_text_2, progress, align, true);
237             else
238                 DrawWindowText(lyric_rect, current_lyric.text.c_str(), m_colors.color_text, m_colors.color_text, progress, align, true);
239         }
240 
241         SetFont(m_pMainWnd->GetFont());
242     }
243 }
244 
245 void CUIDrawer::DrawSpectrum(CRect rect, SpectrumCol col, bool draw_reflex /*= false*/, bool low_freq_in_center)
246 {
247     int cols;		//Ҫ��ʾ��Ƶ�����ε�����
248     switch (col)
249     {
250     case CUIDrawer::SC_64:
251         cols = 64;
252         break;
253     case CUIDrawer::SC_32:
254         cols = 32;
255         break;
256     case CUIDrawer::SC_16:
257         cols = 16;
258         break;
259     case CUIDrawer::SC_8:
260         cols = 8;
261         break;
262     default:
263         cols = SPECTRUM_COL;
264         break;
265     }
266     int gap_width{ rect.Width() * (SPECTRUM_COL / cols) / 168 };		//Ƶ�����μ�϶���
267     if (theApp.m_ui_data.full_screen)
268         gap_width *= CONSTVAL::FULL_SCREEN_ZOOM_FACTOR;
269     if (gap_width < 1)
270         gap_width = 1;
271     int width = (rect.Width() - (cols - 1) * gap_width) / (cols - 1);
272 
273     DrawSpectrum(rect, width, gap_width, cols, m_colors.color_spectrum, draw_reflex, low_freq_in_center);
274 }
275 
276 void CUIDrawer::DrawSpectrum(CRect rect, int col_width, int gap_width, int cols, COLORREF color, bool draw_reflex /*= false*/, bool low_freq_in_center)
277 {
278     CRect rc_spectrum_top = rect;
279     if (draw_reflex)     //���Ҫ���Ƶ�Ӱ����Ӱռ�ܸ߶ȵ�1/3
280         rc_spectrum_top.bottom = rect.top + (rect.Height() * 2 / 3);
281 
282     CRect rects[SPECTRUM_COL];
283     rects[0] = rc_spectrum_top;
284     rects[0].right = rects[0].left + col_width;
285     for (int i{ 1 }; i < cols; i++)
286     {
287         rects[i] = rects[0];
288         rects[i].left += (i * (col_width + gap_width));
289         rects[i].right += (i * (col_width + gap_width));
290     }
291     for (int i{}; i < cols; i++)
292     {
293         int index;
294         if (low_freq_in_center)
295         {
296             if (i < cols / 2)
297                 index = (-i + cols / 2) * 2 - 1;
298             else
299                 index = (i - cols / 2) * 2;
300         }
301         else
302         {
303             index = i;
304         }
305         if (index >= cols)
306             index = cols;
307         if (index < 0)
308             index = 0;
309         float spetral_data = CPlayer::GetInstance().GetSpectralData()[index * (SPECTRUM_COL / cols)];
310         float peak_data = CPlayer::GetInstance().GetSpectralPeakData()[index * (SPECTRUM_COL / cols)];
311 
312         CRect rect_tmp{ rects[i] };
313         int spetral_height = static_cast<int>(spetral_data * rects[0].Height() / 30 * theApp.m_app_setting_data.sprctrum_height / 100);
314         int peak_height = static_cast<int>(peak_data * rects[0].Height() / 30 * theApp.m_app_setting_data.sprctrum_height / 100);
315         if (spetral_height <= 0 || CPlayer::GetInstance().IsError()) spetral_height = 1;		//Ƶ�׸߶�����Ϊ1�����أ�������ų���Ҳ����ʾƵ��
316         if (peak_height <= 0 || CPlayer::GetInstance().IsError()) peak_height = 1;		//Ƶ�׸߶�����Ϊ1�����أ�������ų���Ҳ����ʾƵ��
317         rect_tmp.top = rect_tmp.bottom - spetral_height;
318         if (rect_tmp.top < rects[0].top) rect_tmp.top = rects[0].top;
319         FillRect(rect_tmp, color, true);
320         //���Ƶ�Ӱ
321         if (draw_reflex)
322         {
323             CRect rc_invert = rect_tmp;
324             rc_invert.bottom = rect_tmp.top + rect_tmp.Height() * 2 / 3;
325             rc_invert.MoveToY(rect_tmp.bottom + gap_width);
326             FillAlphaRect(rc_invert, color, 96, true);
327         }
328 
329         //���ƶ���
330         CRect rect_peak{ rect_tmp };
331         rect_peak.bottom = rect_tmp.bottom - peak_height - gap_width;
332         rect_peak.top = rect_peak.bottom - max(theApp.DPIRound(1.1), gap_width / 2);
333         FillRect(rect_peak, color, true);
334         ////���ƶ��˵�Ӱ
335         //CRect rc_peak_invert = rect_peak;
336         //rc_peak_invert.MoveToY(rc_invert.top + peak_height + theApp.DPIRound(1.1));
337         //FillAlphaRect(rc_peak_invert, color, 96);
338     }
339 
340 }
341 
342 void CUIDrawer::DrawLyricDoubleLine(CRect rect, LPCTSTR lyric, LPCTSTR next_lyric, int progress, int fade_percent)
343 {
344     SetLyricFont();
345     static bool swap;
346     static int last_progress;
347     if (last_progress > progress)		//�����ǰ�ĸ�ʽ��ȱ��ϴε�С��˵������л�������һ��
348     {
349         swap = !swap;
350     }
351     last_progress = progress;
352 
353 
354     CRect up_rect{ rect }, down_rect{ rect };		//�ϰ벿�ֺ��°벿�ָ�ʵľ�������
355     up_rect.bottom = up_rect.top + (up_rect.Height() / 2);
356     down_rect.top = down_rect.bottom - (down_rect.Height() / 2);
357     //������һ���ʵ��ı�������Ҫ�Ŀ�ȣ��Ӷ�ʵ����һ�и���Ҷ���
358     //GetDC()->SelectObject(&theApp.m_font_set.lyric.GetFont(theApp.m_ui_data.full_screen));
359     int width;
360     if (!swap)
361         width = GetTextExtent(next_lyric).cx;
362     else
363         width = GetTextExtent(lyric).cx;
364     if (width < rect.Width())
365         down_rect.left = down_rect.right - width;
366 
367     COLORREF color1, color2;
368     if (theApp.m_lyric_setting_data.lyric_karaoke_disp)
369     {
370         color1 = m_colors.color_text;
371         color2 = m_colors.color_text_2;
372     }
373     else
374     {
375         color1 = color2 = CColorConvert::GetGradientColor(m_colors.color_text_2, m_colors.color_text, fade_percent);
376     }
377 
378     if (!swap)
379     {
380         DrawWindowText(up_rect, lyric, color1, color2, progress);
381         DrawWindowText(down_rect, next_lyric, m_colors.color_text_2);
382     }
383     else
384     {
385         DrawWindowText(up_rect, next_lyric, m_colors.color_text_2);
386         DrawWindowText(down_rect, lyric, color1, color2, progress);
387     }
388 }
389 
390 void CUIDrawer::SetLyricFont()
391 {
392     if (!m_for_cortana_lyric)
393         SetFont(&theApp.m_font_set.lyric.GetFont(theApp.m_ui_data.full_screen));
394     else
395         SetFont(&theApp.m_font_set.cortana.GetFont());
396 }
397 
398 void CUIDrawer::SetLyricFontTranslated()
399 {
400     if (!m_for_cortana_lyric)
401         SetFont(&theApp.m_font_set.lyric_translate.GetFont(theApp.m_ui_data.full_screen));
402     else
403         SetFont(&theApp.m_font_set.cortana_translate.GetFont());
404 }
405