soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SSkin.cpp
1//////////////////////////////////////////////////////////////////////////
2// File Name: SSkinPool
3//////////////////////////////////////////////////////////////////////////
4#include "souistd.h"
5#include "core/SSkin.h"
6#include "helper/SDIBHelper.h"
7#include <core/SGradient.h>
8SNSBEGIN
9
10//////////////////////////////////////////////////////////////////////////
11// SSkinImgList
13 : m_nStates(1)
14 , m_bTile(FALSE)
15 , m_bVertical(FALSE)
16 , m_filterLevel(kUndef_FilterLevel)
17 , m_bAutoFit(TRUE)
18 , m_bLazyLoad(FALSE)
19{
20}
21
25
27{
28 SIZE ret = { 0, 0 };
29 if (GetImage())
30 ret = GetImage()->Size();
31 if (m_bVertical)
32 ret.cy /= m_nStates;
33 else
34 ret.cx /= m_nStates;
35 return ret;
36}
37
39{
40 return m_nStates;
41}
42
44{
45 __baseCls::OnInitFinished(xmlNode);
46 if (!m_bLazyLoad && !m_strSrc.IsEmpty())
47 {
48 m_pImg.Attach(LOADIMAGE2(m_strSrc));
49 }
50}
51
52void SSkinImgList::_DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const
53{
54 if (!GetImage())
55 return;
56 SIZE sz = GetSkinSize();
57 RECT rcSrc = { 0, 0, sz.cx, sz.cy };
58 if (m_bVertical)
59 OffsetRect(&rcSrc, 0, iState * sz.cy);
60 else
61 OffsetRect(&rcSrc, iState * sz.cx, 0);
62 pRT->DrawBitmapEx(rcDraw, GetImage(), &rcSrc, GetExpandMode(), byAlpha);
63}
64
66{
67 if (m_bAutoFit)
68 return MAKELONG(m_bTile ? EM_TILE : EM_STRETCH, m_filterLevel);
69 else
70 return MAKELONG(EM_NULL, m_filterLevel);
71}
72
73HRESULT SSkinImgList::OnAttrSrc(const SStringW &value, BOOL bLoading)
74{
75 m_strSrc = value;
76#ifndef _WIN32
77 m_strSrc.ReplaceChar('\\', '/');
78#endif //_WIN32
79 if (!bLoading)
80 {
81 m_pImg.Attach(LOADIMAGE2(m_strSrc));
82 }
83 return S_OK;
84}
85
87{
88 m_pImg = pImg;
89 m_strSrc.Empty();
90 m_bLazyLoad = FALSE;
91 return true;
92}
93
95{
96 if (m_pImg)
97 return m_pImg;
98 if (m_bLazyLoad && !m_strSrc.IsEmpty())
99 {
100 m_pImg.Attach(LOADIMAGE2(m_strSrc));
101 m_strSrc.Empty();
102 }
103 return m_pImg;
104}
105
107{
108 if (!m_bEnableColorize)
109 return;
110 if (cr == m_crColorize)
111 return;
112 m_crColorize = cr;
113
114 IBitmapS *pImg = GetImage();
115 if (m_imgBackup)
116 { // restore
117 LPCVOID pSrc = m_imgBackup->GetPixelBits();
118 LPVOID pDst = pImg->LockPixelBits();
119 memcpy(pDst, pSrc, pImg->Width() * pImg->Height() * 4);
120 pImg->UnlockPixelBits(pDst);
121 }
122 else
123 {
124 if (!pImg)
125 return;
126 if (S_OK != pImg->Clone(&m_imgBackup))
127 return;
128 }
129
130 if (cr != 0)
131 SDIBHelper::Colorize(pImg, cr);
132 else
133 m_imgBackup = NULL; // free backup
134}
135
136void SSkinImgList::_Scale(ISkinObj *skinObj, int nScale)
137{
138 __baseCls::_Scale(skinObj, nScale);
139 SSkinImgList *pRet = sobj_cast<SSkinImgList>(skinObj);
140 pRet->m_nStates = m_nStates;
141 pRet->m_bTile = m_bTile;
142 pRet->m_bVertical = m_bVertical;
143 pRet->m_filterLevel = m_filterLevel;
144 pRet->m_bAutoFit = m_bAutoFit;
145 pRet->m_state2Index = m_state2Index;
146 pRet->m_bLazyLoad = FALSE;
147
148 CSize szSkin = GetSkinSize();
149 szSkin.cx = MulDiv(szSkin.cx, nScale, GetScale());
150 szSkin.cy = MulDiv(szSkin.cy, nScale, GetScale());
151 if (m_bVertical)
152 {
153 szSkin.cy *= m_nStates;
154 }
155 else
156 {
157 szSkin.cx *= m_nStates;
158 }
159
160 if (m_imgBackup)
161 {
162 m_imgBackup->Scale2(&pRet->m_imgBackup, szSkin.cx, szSkin.cy, kHigh_FilterLevel);
163 }
164 IBitmapS *pImg = GetImage();
165 if (pImg)
166 {
167 m_pImg->Scale2(&pRet->m_pImg, szSkin.cx, szSkin.cy, kHigh_FilterLevel);
168 }
169}
170
171//////////////////////////////////////////////////////////////////////////
172// SSkinImgCenter
173void SSkinImgCenter::_DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const
174{
175 SIZE szSkin = GetSkinSize();
176 CRect rcTarget = *rcDraw;
177 CPoint pt;
178 pt.x = rcTarget.left + (rcTarget.Width() - szSkin.cx) / 2;
179 pt.y = rcTarget.top + (rcTarget.Height() - szSkin.cy) / 2;
180
181 rcTarget = CRect(pt, szSkin);
182
183 RECT rcSrc = { 0, 0, szSkin.cx, szSkin.cy };
184 if (m_bVertical)
185 OffsetRect(&rcSrc, 0, iState * szSkin.cy);
186 else
187 OffsetRect(&rcSrc, iState * szSkin.cx, 0);
188
189 pRT->DrawBitmapEx(rcTarget, GetImage(), &rcSrc, GetExpandMode(), byAlpha);
190}
191
192//////////////////////////////////////////////////////////////////////////
193// SSkinImgFrame
197
198void SSkinImgFrame::_DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const
199{
200 if (!GetImage())
201 return;
202 SIZE sz = GetSkinSize();
203 CPoint pt;
204 if (IsVertical())
205 pt.y = sz.cy * iState;
206 else
207 pt.x = sz.cx * iState;
208 CRect rcSour(pt, sz);
209 pRT->DrawBitmap9Patch(rcDraw, GetImage(), &rcSour, &m_rcMargin, GetExpandMode(), byAlpha);
210}
211
213{
214 return MAKELONG(m_bTile ? EM_TILE : EM_STRETCH, m_filterLevel);
215}
216
217void SSkinImgFrame::_Scale(ISkinObj *skinObj, int nScale)
218{
219 SSkinImgList::_Scale(skinObj, nScale);
220 SSkinImgFrame *pClone = sobj_cast<SSkinImgFrame>(skinObj);
221 int nSrcScale = GetScale();
222 pClone->m_rcMargin.left = MulDiv(m_rcMargin.left, nScale, nSrcScale);
223 pClone->m_rcMargin.top = MulDiv(m_rcMargin.top, nScale, nSrcScale);
224 pClone->m_rcMargin.right = MulDiv(m_rcMargin.right, nScale, nSrcScale);
225 pClone->m_rcMargin.bottom = MulDiv(m_rcMargin.bottom, nScale, nSrcScale);
226}
227
228//////////////////////////////////////////////////////////////////////////
229// SSkinButton
231 : m_nCornerRadius(2)
232 , m_fCornerPercent(0.0)
233{
234 m_colors.m_crBorder[0] = RGB(0x70, 0x70, 0x70);
235 m_colors.m_crBorder[1] = CR_INVALID; // 不改变 原有的效果
236 m_colors.m_crBorder[2] = CR_INVALID;
237 m_colors.m_crBorder[3] = CR_INVALID;
238
239 m_colors.m_crUp[0] = (RGB(0xEE, 0xEE, 0xEE));
240 m_colors.m_crDown[0] = (RGB(0xD6, 0xD6, 0xD6));
241 m_colors.m_crUp[1] = (RGB(0xEE, 0xEE, 0xEE));
242 m_colors.m_crDown[1] = (RGB(0xE0, 0xE0, 0xE0));
243 m_colors.m_crUp[2] = (RGB(0xCE, 0xCE, 0xCE));
244 m_colors.m_crDown[2] = (RGB(0xC0, 0xC0, 0xC0));
245 m_colors.m_crUp[3] = (RGB(0x8E, 0x8E, 0x8E));
246 m_colors.m_crDown[3] = (RGB(0x80, 0x80, 0x80));
247}
248
249void SSkinButton::_DrawByIndex(IRenderTarget *pRT, LPCRECT prcDraw, int iState, BYTE byAlpha) const
250{
251 int nCorner = m_nCornerRadius;
252 if (m_fCornerPercent > 0.0)
253 {
254 int nW = prcDraw->right - prcDraw->left;
255 int nH = prcDraw->bottom - prcDraw->top;
256 nCorner = (nW < nH) ? (int)(nW * m_fCornerPercent) : (int)(nH * m_fCornerPercent);
257 }
258 // 只有 在 需要渐变的情况下 才 需要 这个
259 if (m_colors.m_crUp[iState] != m_colors.m_crDown[iState])
260 {
261 CRect rcDraw = *prcDraw;
262 rcDraw.DeflateRect(1, 1);
263 CPoint ptCorner(nCorner, nCorner);
264 GradientItem gradients[2] = { m_colors.m_crUp[iState], 0.0f, m_colors.m_crDown[iState], 1.0f };
265 pRT->DrawGradientRect(rcDraw, TRUE, ptCorner, gradients, 2, byAlpha);
266 }
267 else
268 {
269 SColor cr(m_colors.m_crDown[iState]);
270 cr.updateAlpha(byAlpha);
271 if (nCorner > 0)
272 pRT->FillSolidRoundRect(prcDraw, CPoint(nCorner, nCorner), cr.toCOLORREF());
273 else
274 pRT->FillSolidRect(prcDraw, cr.toCOLORREF());
275 }
276
277 if (CR_INVALID == m_colors.m_crBorder[iState]) // 不改变 原因的 效果
278 iState = 0;
279 // 画 边框
280 SAutoRefPtr<IPenS> pPen, pOldPen;
281 pRT->CreatePen(PS_SOLID, m_colors.m_crBorder[iState], 1, &pPen);
282 pRT->SelectObject(pPen, (IRenderObj **)&pOldPen);
283 pRT->DrawRoundRect(prcDraw, CPoint(nCorner, nCorner));
284 pRT->SelectObject(pOldPen, NULL);
285}
286
288{
289 return 4;
290}
291
292void SSkinButton::SetColors(COLORREF crUp[4], COLORREF crDown[4], COLORREF crBorder[4])
293{
294 memcpy(m_colors.m_crUp, crUp, 4 * sizeof(COLORREF));
295 memcpy(m_colors.m_crDown, crDown, 4 * sizeof(COLORREF));
296 memcpy(m_colors.m_crBorder, crBorder, 4 * sizeof(COLORREF));
297}
298
299void SSkinButton::OnColorize(COLORREF cr)
300{
301 if (!m_bEnableColorize)
302 return;
303 if (m_crColorize == cr)
304 return;
305 if (cr == 0)
306 {
307 memcpy(&m_colors, &m_colorsBackup, sizeof(BTNCOLORS));
308 m_crColorize = 0;
309 }
310 else
311 {
312 if (m_crColorize != 0)
313 { //从备份里获取数据
314 memcpy(&m_colors, &m_colorsBackup, sizeof(BTNCOLORS));
315 }
316 else
317 { //将数据备份
318 memcpy(&m_colorsBackup, &m_colors, sizeof(BTNCOLORS));
319 }
320 m_crColorize = cr;
321
322 //调整颜色值
323 for (int i = 0; i < 4; i++)
324 {
325 SDIBHelper::Colorize(m_colors.m_crBorder[i], m_crColorize);
326 SDIBHelper::Colorize(m_colors.m_crDown[i], m_crColorize);
327 SDIBHelper::Colorize(m_colors.m_crUp[i], m_crColorize);
328 }
329 }
330}
331
333{
334 return NULL;
335}
336
337//////////////////////////////////////////////////////////////////////////
338// SSkinGradation
340 : m_bVert(TRUE)
341 , m_crFrom(CR_INVALID)
342 , m_crTo(CR_INVALID)
343{
344}
345
346void SSkinGradation::_DrawByIndex(IRenderTarget *pRT, LPCRECT prcDraw, int iState, BYTE byAlpha) const
347{
348 GradientItem gradients[2] = { m_crFrom, 0.0f, m_crTo, 1.0f };
349 pRT->DrawGradientRect(prcDraw, m_bVert, CPoint(), gradients, 2, byAlpha);
350}
351
353{
354 return NULL;
355}
356
357//////////////////////////////////////////////////////////////////////////
359{
360 // set default to linear gradient
361 m_type = linear;
362 m_angle = 0.0f;
363 m_centerX = m_centerY = 0.5f;
364 m_radius.setInvalid();
365 m_ratio_radius = 0.5f;
366 m_bFullArc = TRUE;
367 m_gradient.Attach(new SGradient());
368}
369
370GradientInfo SGradientDesc::GetGradientInfo(int nScale, int wid, int hei) const
371{
372 GradientInfo ret;
373 ret.type = m_type;
374 switch (ret.type)
375 {
376 case linear:
377 ret.angle = m_angle;
378 break;
379 case radial:
380 if (m_radius.isValid())
381 ret.radial.radius = (float)m_radius.toPixelSize(nScale);
382 else
383 ret.radial.radius = m_ratio_radius * smax(wid, hei);
384 ret.sweep.centerX = m_centerX;
385 ret.sweep.centerY = m_centerY;
386 break;
387 case sweep:
388 ret.sweep.centerX = m_centerX;
389 ret.sweep.centerY = m_centerY;
390 ret.sweep.bFullArc = m_bFullArc;
391 break;
392 }
393 return ret;
394}
395
396//////////////////////////////////////////////////////////////////////////
398{
399 m_ptCorner = SPoint::Make(0.f, 0.f);
400 m_szCorner[0].setInvalid();
401 m_szCorner[1].setInvalid();
402 m_bEnableScale = false;
403 m_gradient.Attach(new SGradient());
404}
405
406void SSkinGradation2::_DrawByIndex(IRenderTarget *pRT, LPCRECT prcDraw, int iState, BYTE byAlpha) const
407{
408 CRect rc(prcDraw);
409 CPoint ptCorner;
410 if (m_szCorner[0].isValid() && m_szCorner[1].isValid())
411 {
412 ptCorner.x = m_szCorner[0].toPixelSize(GetScale());
413 ptCorner.y = m_szCorner[1].toPixelSize(GetScale());
414 }
415 else
416 {
417 ptCorner.x = (int)(rc.Width() / 2 * m_ptCorner.fX);
418 ptCorner.y = (int)(rc.Height() / 2 * m_ptCorner.fY);
419 }
420 GradientInfo info = GetGradientInfo(GetScale(), prcDraw->right - prcDraw->left, prcDraw->bottom - prcDraw->top);
421 pRT->DrawGradientRectEx(prcDraw, ptCorner, m_gradient->GetGradientData(), m_gradient->GetGradientLength(), &info, GetAlpha());
422}
423
425{
426 return NULL;
427}
428
430{
431 m_gradient->OnInitFinished(xmlNode);
432}
433
434//////////////////////////////////////////////////////////////////////////
435// SScrollbarSkin
437 : m_nMargin(0)
438 , m_bHasGripper(FALSE)
439 , m_bHasInactive(FALSE)
440{
441}
442
443CRect SSkinScrollbar::GetPartRect(int nSbCode, int nState, BOOL bVertical) const
444{
445 CSize sz = GetSkinSize();
446 CSize szFrame(sz.cx / 9, sz.cx / 9);
447 if (nSbCode == SB_CORNOR)
448 {
449 return CRect(CPoint(szFrame.cx * 8, 0), szFrame);
450 }
451 else if (nSbCode == SB_THUMBGRIPPER)
452 {
453 return CRect(CPoint(szFrame.cx * 8, (1 + (bVertical ? 0 : 1)) * szFrame.cy), szFrame);
454 }
455 else
456 {
457 if (nState == SBST_INACTIVE && !m_bHasInactive)
458 {
459 nState = SBST_NORMAL;
460 }
461 CRect rcRet;
462 int iPart = -1;
463 switch (nSbCode)
464 {
465 case SB_LINEUP:
466 iPart = 0;
467 break;
468 case SB_LINEDOWN:
469 iPart = 1;
470 break;
471 case SB_THUMBTRACK:
472 iPart = 2;
473 break;
474 case SB_PAGEUP:
475 case SB_PAGEDOWN:
476 iPart = 3;
477 break;
478 }
479 if (!bVertical)
480 iPart += 4;
481
482 return CRect(CPoint(szFrame.cx * iPart, szFrame.cy * nState), szFrame);
483 }
484}
485
486void SSkinScrollbar::_DrawByState(IRenderTarget *pRT, LPCRECT prcDraw, DWORD dwState, BYTE byAlpha) const
487{
488 if (!GetImage())
489 return;
490 int nSbCode = LOWORD(dwState);
491 int nState = LOBYTE(HIWORD(dwState));
492 BOOL bVertical = HIBYTE(HIWORD(dwState));
493 CRect rcMargin(0, 0, 0, 0);
494 if (bVertical)
495 rcMargin.top = m_nMargin, rcMargin.bottom = m_nMargin;
496 else
497 rcMargin.left = m_nMargin, rcMargin.right = m_nMargin;
498
499 CRect rcSour = GetPartRect(nSbCode, nState, bVertical);
500
501 pRT->DrawBitmap9Patch(prcDraw, GetImage(), &rcSour, &rcMargin, m_bTile ? EM_TILE : EM_STRETCH, byAlpha);
502
503 if (nSbCode == SB_THUMBTRACK && m_bHasGripper)
504 {
505 rcSour = GetPartRect(SB_THUMBGRIPPER, 0, bVertical);
506 CRect rcDraw = *prcDraw;
507
508 if (bVertical)
509 rcDraw.top += (rcDraw.Height() - rcSour.Height()) / 2, rcDraw.bottom = rcDraw.top + rcSour.Height();
510 else
511 rcDraw.left += (rcDraw.Width() - rcSour.Width()) / 2, rcDraw.right = rcDraw.left + rcSour.Width();
512 pRT->DrawBitmap9Patch(&rcDraw, GetImage(), &rcSour, &rcMargin, m_bTile ? EM_TILE : EM_STRETCH, byAlpha);
513 }
514}
515
516void SSkinScrollbar::_Scale(ISkinObj *skinObj, int nScale)
517{
518 __baseCls::_Scale(skinObj, nScale);
519
520 SSkinScrollbar *pRet = sobj_cast<SSkinScrollbar>(skinObj);
521 pRet->m_nMargin = MulDiv(m_nMargin, nScale, GetScale());
522 pRet->m_bHasInactive = m_bHasInactive;
523 pRet->m_bHasGripper = m_bHasGripper;
524}
525
527{
528 if (!GetImage())
529 return 0;
530 return GetImage()->Width() / 9;
531}
532
533//////////////////////////////////////////////////////////////////////////
534// SSkinColor
536 : m_nRadius(0)
537 , m_fCornerPercent(0.0)
538 , m_nBorderWidth(0)
539{
540 m_crStates[0] = RGBA(255, 255, 255, 255);
541 m_crStates[1] = CR_INVALID;
542 m_crStates[2] = CR_INVALID;
543 m_crStates[3] = CR_INVALID;
544 m_crBorders[0] = m_crBorders[1] = m_crBorders[2] = m_crBorders[3] = CR_INVALID;
545}
546
550
551void SSkinColorRect::_DrawByIndex(IRenderTarget *pRT, LPCRECT prcDraw, int iState, BYTE byAlpha) const
552{
553 if (iState > 3)
554 return;
555
556 int nCorner = m_nRadius;
557 if (m_fCornerPercent > 0.0)
558 {
559 int nW = prcDraw->right - prcDraw->left;
560 int nH = prcDraw->bottom - prcDraw->top;
561 nCorner = (nW < nH) ? (int)(nW * m_fCornerPercent) : (int)(nH * m_fCornerPercent);
562 }
563 int iBgColor = iState;
564 if (m_crStates[iBgColor] == CR_INVALID)
565 iBgColor = 0;
566 if (m_crStates[iBgColor] != CR_INVALID)
567 {
568 SColor cr(m_crStates[iBgColor]);
569 cr.updateAlpha(byAlpha);
570 if (nCorner > 0)
571 pRT->FillSolidRoundRect(prcDraw, CPoint(nCorner, nCorner), cr.toCOLORREF());
572 else
573 pRT->FillSolidRect(prcDraw, cr.toCOLORREF());
574 }
575 int iBorderColor = iState;
576 if (m_crBorders[iBorderColor] == CR_INVALID)
577 iBorderColor = 0;
578 if (m_crBorders[iBorderColor] != CR_INVALID && m_nBorderWidth > 0)
579 {
580 SAutoRefPtr<IPenS> pen, oldPen;
581 pRT->CreatePen(PS_SOLID, m_crBorders[iBorderColor], m_nBorderWidth, (IPenS **)&pen);
582 pRT->SelectObject(pen, (IRenderObj **)&oldPen);
583 if (nCorner > 0)
584 pRT->DrawRoundRect(prcDraw, CPoint(nCorner, nCorner));
585 else
586 pRT->DrawRectangle(prcDraw);
587 pRT->SelectObject(oldPen, NULL);
588 }
589}
590
592{
593 int nStates = 4;
594 for (int i = 3; i >= 0; i--)
595 {
596 if (m_crStates[i] == CR_INVALID)
597 nStates--;
598 else
599 break;
600 }
601 return nStates;
602}
603
605{
606 return NULL;
607}
608
609//////////////////////////////////////////////////////////////////////////
610
611SSkinShape::SSkinShape()
612 : m_shape(rectangle)
613{
614}
615
616void SSkinShape::OnInitFinished(IXmlNode *pNode)
617{
618 __baseCls::OnInitFinished(pNode);
619 SXmlNode xmlNode(pNode);
620 SXmlNode xmlSolid = xmlNode.child(SShapeSolid::GetClassName());
621 if (xmlSolid)
622 {
623 if (!m_solid)
624 m_solid.Attach(new SShapeSolid());
625 m_solid->InitFromXml(&xmlSolid);
626 }
627 SXmlNode xmlBitmap = xmlNode.child(SShapeBitmap::GetClassName());
628 if (xmlBitmap)
629 {
630 if (!m_bitmap)
631 m_bitmap.Attach(new SShapeBitmap());
632 m_bitmap->InitFromXml(&xmlBitmap);
633 }
634
635 SXmlNode xmlGrident = xmlNode.child(SGradientBrush::GetClassName());
636 if (xmlGrident)
637 {
638 if (!m_gradient)
639 m_gradient.Attach(new SGradientBrush());
640 m_gradient->InitFromXml(&xmlGrident);
641 }
642 SXmlNode xmlSize = xmlNode.child(SShapeSize::GetClassName());
643 if (xmlSize)
644 {
645 if (!m_shapeSize)
646 m_shapeSize.Attach(new SShapeSize());
647 m_shapeSize->InitFromXml(&xmlSize);
648 }
649 SXmlNode xmlStoke = xmlNode.child(SStroke::GetClassName());
650 if (xmlStoke)
651 {
652 if (!m_stroke)
653 m_stroke.Attach(new SStroke());
654 m_stroke->InitFromXml(&xmlStoke);
655 }
656 SXmlNode xmlConner = xmlNode.child(SCornerSize::GetClassName());
657 if (xmlConner)
658 {
659 if (!m_cornerSize)
660 m_cornerSize.Attach(new SCornerSize());
661 m_cornerSize->InitFromXml(&xmlConner);
662 }
663 SXmlNode xmlRatioConner = xmlNode.child(SRatioCornerSize::GetClassName());
664 if (xmlRatioConner)
665 {
666 if (!m_ratioCornerSize)
667 m_ratioCornerSize.Attach(new SRatioCornerSize());
668 m_ratioCornerSize->InitFromXml(&xmlRatioConner);
669 }
670
671 SXmlNode xmlRing = xmlNode.child(SShapeRing::GetClassName());
672 if (xmlRing)
673 {
674 if (!m_ringParam)
675 m_ringParam.Attach(new SShapeRing());
676 m_ringParam->InitFromXml(&xmlRing);
677 }
678}
679
680void SSkinShape::_Scale(ISkinObj *pObj, int nScale)
681{
682 __baseCls::_Scale(pObj, nScale);
683
684 SSkinShape *pRet = sobj_cast<SSkinShape>(pObj);
685 SASSERT(pRet);
686 pRet->m_solid = m_solid;
687 pRet->m_bitmap = m_bitmap; // todo:hjx
688 pRet->m_gradient = m_gradient;
689 pRet->m_shape = m_shape;
690 pRet->m_shapeSize = m_shapeSize;
691 pRet->m_cornerSize = m_cornerSize;
692 pRet->m_stroke = m_stroke;
693 pRet->m_ringParam = m_ringParam;
694}
695
696SIZE SSkinShape::GetSkinSize() const
697{
698 if (!m_shapeSize)
699 return CSize();
700
701 return CSize(m_shapeSize->m_width.toPixelSize(GetScale()), m_shapeSize->m_height.toPixelSize(GetScale()));
702}
703
704void SSkinShape::_DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const
705{
706 CRect rcDest(rcDraw);
707 SAutoRefPtr<IBrushS> pBrush, oldBrush;
708 if (m_solid)
709 {
710 pBrush.Attach(m_solid->CreateBrush(pRT, byAlpha));
711 }
712 else if (m_gradient != NULL)
713 {
714 pBrush.Attach(m_gradient->CreateBrush(pRT, GetScale(), byAlpha, rcDraw->right - rcDraw->left, rcDraw->bottom - rcDraw->top));
715 }
716 else if (m_bitmap)
717 {
718 pBrush.Attach(m_bitmap->CreateBrush(pRT, byAlpha));
719 }
720
721 SAutoRefPtr<IPenS> pPen, oldPen;
722 if (m_stroke != NULL)
723 {
724 int nPenWidth = m_stroke->m_width.toPixelSize(GetScale());
725 SColor color(m_stroke->m_color, byAlpha);
726 pRT->CreatePen(m_stroke->GetStyle(), color.toCOLORREF(), nPenWidth, &pPen);
727 rcDest.DeflateRect(nPenWidth / 2, nPenWidth / 2);
728 }
729
730 CPoint ptCorner = GetCornerSize(rcDest);
731 if (pBrush)
732 {
733 pRT->SelectObject(pBrush, (IRenderObj **)&oldBrush);
734 switch (m_shape)
735 {
736 case rectangle:
737 if (ptCorner.x != 0 || ptCorner.y != 0)
738 pRT->FillRoundRect(&rcDest, ptCorner);
739 else
740 pRT->FillRectangle(&rcDest);
741 break;
742 case oval:
743 pRT->FillEllipse(&rcDest);
744 break;
745 }
746 pRT->SelectObject(oldBrush, NULL);
747 }
748 if (pPen)
749 {
750 pRT->SelectObject(pPen, (IRenderObj **)&oldPen);
751 ptCorner = GetCornerSize(rcDest);
752 switch (m_shape)
753 {
754 case rectangle:
755 if (ptCorner.x != 0 || ptCorner.y != 0)
756 pRT->DrawRoundRect(&rcDest, ptCorner);
757 else
758 pRT->DrawRectangle(&rcDest);
759 break;
760 case oval:
761 pRT->DrawEllipse(&rcDest);
762 break;
763 case ring:
764 {
765 POINT ptCenter = { (rcDest.left + rcDest.right) / 2, (rcDest.top + rcDest.bottom) / 2 };
766 int nRadius = smin(rcDest.right - rcDest.left, rcDest.bottom - rcDest.top) / 2;
767 RECT rcRing = { ptCenter.x - nRadius, ptCenter.y - nRadius, ptCenter.x + nRadius, ptCenter.y + nRadius };
768 float startAngle = 0;
769 float endAngle = 360;
770 if (m_ringParam)
771 {
772 startAngle = m_ringParam->m_startAngle;
773 endAngle = m_ringParam->m_sweepAngle;
774 }
775 pRT->DrawArc(&rcRing, startAngle, endAngle, false);
776 }
777 break;
778 }
779 pRT->SelectObject(oldPen, NULL);
780 }
781}
782
783int SSkinShape::GetStates() const
784{
785 return 1;
786}
787
788POINT SSkinShape::GetCornerSize(const CRect &rc) const
789{
790 if (m_cornerSize)
791 return m_cornerSize->GetConner(GetScale());
792 if (m_ratioCornerSize)
793 return m_ratioCornerSize->GetConner(rc);
794 return CPoint();
795}
796
797SSkinShape::SStroke::SStroke()
798 : m_color(CR_INVALID)
799 , m_style(PS_SOLID)
800 , m_endStyle(0)
801 , m_joinStyle(0)
802{
803}
804
805int SSkinShape::SStroke::GetStyle() const
806{
807 int ret = m_style | m_endStyle | m_joinStyle;
808 if (m_endStyle || m_joinStyle)
809 {
810 ret |= PS_GEOMETRIC;
811 }
812 return ret;
813}
814
815IBrushS *SSkinShape::SShapeSolid::CreateBrush(IRenderTarget *pRT, BYTE byAlpha)
816{
817 if (m_crSolid == CR_INVALID)
818 return NULL;
819 SColor color(m_crSolid, byAlpha);
820 IBrushS *ret = NULL;
821 pRT->CreateSolidColorBrush(color.toCOLORREF(), &ret);
822 return ret;
823}
824
825IBrushS *SSkinShape::SShapeBitmap::CreateBrush(IRenderTarget *pRT, BYTE byAlpha)
826{
827 if (!m_pImg)
828 return NULL;
829 IBrushS *ret = NULL;
830 pRT->CreateBitmapBrush(m_pImg, m_tileX, m_tileY, &ret);
831 return ret;
832}
833
834IBrushS *SSkinShape::SGradientBrush::CreateBrush(IRenderTarget *pRT, int nScale, BYTE byAlpha, int wid, int hei) const
835{
836 if (m_gradient->GetGradientLength() < 2)
837 return NULL;
838 IBrushS *ret = NULL;
839 GradientInfo info = GetGradientInfo(nScale, wid, hei);
840 pRT->CreateGradientBrush(m_gradient->GetGradientData(), m_gradient->GetGradientLength(), &info, byAlpha, kRepeat_TileMode, &ret);
841 return ret;
842}
843
844void SSkinShape::SGradientBrush::OnInitFinished(THIS_ IXmlNode *xmlNode)
845{
846 m_gradient->OnInitFinished(xmlNode);
847}
848
849HRESULT SSkinShape::SCornerSize::OnAttrRadius(const SStringW strValue, BOOL bLoading)
850{
851 SStringWList values;
852 size_t nValues = SplitString(strValue, L',', values);
853 if (nValues == 1)
854 {
855 m_radiusX = m_radiusY = GETLAYOUTSIZE(values[0]);
856 return S_OK;
857 }
858 else if (nValues == 2)
859 {
860 m_radiusX = GETLAYOUTSIZE(values[0]);
861 m_radiusY = GETLAYOUTSIZE(values[1]);
862 return S_OK;
863 }
864 return E_INVALIDARG;
865}
866
867HRESULT SSkinShape::SRatioCornerSize::OnAttrRadius(const SStringW strValue, BOOL bLoading)
868{
869 SStringWList values;
870 size_t nValues = SplitString(strValue, L',', values);
871 if (nValues == 1)
872 {
873 swscanf_s(strValue.c_str(), L"%f", &m_radius.fX);
874 m_radius.fY = m_radius.fX;
875 return S_OK;
876 }
877 else if (nValues == 2)
878 {
879 swscanf_s(values[0].c_str(), L"%f", &m_radius.fX);
880 swscanf_s(values[1].c_str(), L"%f", &m_radius.fY);
881 return S_OK;
882 }
883 return E_INVALIDARG;
884}
885
886//////////////////////////////////////////////////////////////////////////
887// SSKinGroup
889{
890 return 4;
891}
892
893void SSKinGroup::_DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const
894{
895 if ((int)iState >= GetStates())
896 return;
897 ISkinObj *pSkin = m_skins[iState];
898 if (!pSkin)
899 return;
900 pSkin->DrawByIndex2(pRT, rcDraw, 0, byAlpha);
901}
902
904{
905 for (int i = 0; i < GetStates(); i++)
906 {
907 if (m_skins[i])
908 return m_skins[i]->GetSkinSize();
909 }
910 return CSize();
911}
912
913void SSKinGroup::_Scale(ISkinObj *skinObj, int nScale)
914{
915 __baseCls::_Scale(skinObj, nScale);
916 SSKinGroup *pRet = sobj_cast<SSKinGroup>(skinObj);
917 for (int i = 0; i < ARRAYSIZE(m_skins); i++)
918 {
919 if (!m_skins[i])
920 continue;
921 pRet->m_skins[i].Attach(m_skins[i]->Scale(nScale));
922 }
923}
924
925/*
926IBitmap中的内存为RGBA格式,.9中使用alpha通道==0或者255来确定如何拉伸
927*/
928HRESULT SSkinImgFrame2::OnAttrSrc(const SStringW &strValue, BOOL bLoading)
929{
930 IBitmapS *pImg = LOADIMAGE2(strValue);
931 if (!pImg)
932 return E_FAIL;
933 int nWid = pImg->Width();
934 int nHei = pImg->Height();
935 if (nWid < 2 || nHei < 2)
936 return E_INVALIDARG;
937 LPBYTE pBuf = (LPBYTE)pImg->LockPixelBits();
938
939 int left, right, top, bottom;
940 //检测第一扫描行中定义的left,right位置
941 LPBYTE p = pBuf;
942 int i = 1;
943 while (i < nWid - 1 && p[3] == 0)
944 i++, p += 4;
945 left = i - 1;
946
947 while (i < nWid - 1 && p[3] != 0)
948 i++, p += 4;
949 right = i - 1;
950
951 //检测第一列中定义的top,bottom位置
952 i = 1;
953 p = pBuf + (nWid * 4);
954 while (i < nHei - 1 && p[3] == 0)
955 i++, p += nWid * 4;
956 top = i - 1;
957 while (i < nHei - 1 && p[3] != 0)
958 i++, p += nWid * 4;
959 bottom = i - 1;
960
961 m_rcMargin.left = left;
962 m_rcMargin.right = nWid - 2 - right;
963 m_rcMargin.top = top;
964 m_rcMargin.bottom = nHei - 2 - bottom;
965
966 HRESULT hRet = S_OK;
967 IBitmapS *pImgCenter = NULL;
968 if (!pImg->GetRenderFactory()->CreateBitmap(&pImgCenter))
969 {
970 return E_OUTOFMEMORY;
971 }
972 hRet = pImgCenter->Init(nWid - 2, nHei - 2, NULL);
973 if (hRet != S_OK)
974 {
975 return hRet;
976 }
977 LPBYTE pBuf2 = (LPBYTE)pImgCenter->LockPixelBits();
978
979 LPBYTE pSrc = pBuf + (nWid * 4);
980 LPBYTE pDst = pBuf2;
981
982 i = 1;
983 pSrc += 4;
984 while (i < nHei - 1)
985 {
986 memcpy(pDst, pSrc, (nWid - 2) * 4);
987 pDst += (nWid - 2) * 4;
988 pSrc += nWid * 4;
989 i++;
990 }
991
992 pImg->UnlockPixelBits(pBuf);
993 pImgCenter->UnlockPixelBits(pBuf2);
994
995 SetImage(pImgCenter);
996 pImgCenter->Release();
997 pImg->Release();
998
999 return hRet;
1000}
1001
1002SNSEND
Skin Classes for SOUI.
#define SB_CORNOR
Constant for scrollbar corner.
Definition SSkin.h:617
#define SB_THUMBGRIPPER
Constant for scrollbar thumb gripper.
Definition SSkin.h:623
Smart pointer class for managing COM-style reference-counted objects.
void Attach(T *p2)
Attaches to an existing object without adding a reference.
以ARGB格式存储颜色值的类
Definition SColor.h:24
const COLORREF toCOLORREF() const
将颜色转换为COLORREF格式
Definition SColor.h:71
void updateAlpha(BYTE alpha)
更新颜色的Alpha值
Definition SColor.h:117
static bool Colorize(IBitmapS *pBmp, COLORREF crRef)
对位图进行着色处理
SGradientDesc()
Constructor for SGradientDesc.
Definition SSkin.cpp:358
GradientInfo GetGradientInfo(int nScale, int wid, int hei) const
Gets the gradient information.
Definition SSkin.cpp:370
Gradient management class.
Definition SGradient.h:18
Represents a group of skins for different states.
Definition SSkin.h:1135
void _DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const override
Draws the skin group by index.
Definition SSkin.cpp:893
int GetStates() SCONST OVERRIDE
Gets the number of states supported by the skin group.
Definition SSkin.cpp:888
SIZE GetSkinSize() SCONST OVERRIDE
Gets the size of the skin group.
Definition SSkin.cpp:903
void _Scale(ISkinObj *skinObj, int nScale) override
Scales the skin group.
Definition SSkin.cpp:913
void OnColorize(COLORREF cr) OVERRIDE
Handles colorization of the skin.
Definition SSkin.cpp:299
ISkinObj * Scale(int nScale) OVERRIDE
Scales the skin.
Definition SSkin.cpp:332
int GetStates() SCONST OVERRIDE
Gets the number of states in the skin.
Definition SSkin.cpp:287
SSkinButton()
Constructor for SSkinButton.
Definition SSkin.cpp:230
void _DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const override
Draws the skin by index.
Definition SSkin.cpp:249
void SetColors(COLORREF crUp[4], COLORREF crDown[4], COLORREF crBorder[4])
Sets the colors for different button states.
Definition SSkin.cpp:292
virtual ~SSkinColorRect()
Destructor for SSkinColorRect.
Definition SSkin.cpp:547
SSkinColorRect()
Constructor for SSkinColorRect.
Definition SSkin.cpp:535
void _DrawByIndex(IRenderTarget *pRT, LPCRECT prcDraw, int iState, BYTE byAlpha) const override
Draws the skin by index.
Definition SSkin.cpp:551
ISkinObj * Scale(int nScale) OVERRIDE
Scales the skin.
Definition SSkin.cpp:604
int GetStates() SCONST OVERRIDE
Gets the number of states in the skin.
Definition SSkin.cpp:591
void _DrawByIndex(IRenderTarget *pRT, LPCRECT prcDraw, int iState, BYTE byAlpha) const override
Draws the skin by index.
Definition SSkin.cpp:406
ISkinObj * Scale(int nScale) OVERRIDE
Scales the skin.
Definition SSkin.cpp:424
SSkinGradation2()
Constructor for SSkinGradation2.
Definition SSkin.cpp:397
void OnInitFinished(IXmlNode *xmlNode) OVERRIDE
Called when initialization is finished.
Definition SSkin.cpp:429
void _DrawByIndex(IRenderTarget *pRT, LPCRECT prcDraw, int iState, BYTE byAlpha) const override
Draws the skin by index.
Definition SSkin.cpp:346
SSkinGradation()
Constructor for SSkinGradation.
Definition SSkin.cpp:339
ISkinObj * Scale(int nScale) OVERRIDE
Scales the skin.
Definition SSkin.cpp:352
void _DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const override
Draws the skin by index.
Definition SSkin.cpp:173
HRESULT OnAttrSrc(const SStringW &strValue, BOOL bLoading)
Handles the 'src' attribute.
Definition SSkin.cpp:928
SSkinImgFrame()
Constructor for SSkinImgFrame.
Definition SSkin.cpp:194
void _Scale(ISkinObj *skinObj, int nScale) override
Scales the skin.
Definition SSkin.cpp:217
void _DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const override
Draws the skin by index.
Definition SSkin.cpp:198
UINT GetExpandMode() const override
Gets the expand mode for the skin.
Definition SSkin.cpp:212
void _Scale(ISkinObj *skinObj, int nScale) override
Scales the skin.
Definition SSkin.cpp:136
virtual ~SSkinImgList()
Destructor for SSkinImgList.
Definition SSkin.cpp:22
virtual bool SetImage(IBitmapS *pImg)
Sets the image for the skin.
Definition SSkin.cpp:86
SIZE GetSkinSize() SCONST OVERRIDE
Gets the size of the skin.
Definition SSkin.cpp:26
HRESULT OnAttrSrc(const SStringW &value, BOOL bLoading)
Handles the 'src' attribute.
Definition SSkin.cpp:73
void OnInitFinished(IXmlNode *pNode) OVERRIDE
Called when initialization is finished.
Definition SSkin.cpp:43
virtual BOOL IsVertical() const
Checks if the images are arranged vertically.
Definition SSkin.h:116
SSkinImgList()
Constructor for SSkinImgList.
Definition SSkin.cpp:12
void OnColorize(COLORREF cr) OVERRIDE
Handles colorization of the skin.
Definition SSkin.cpp:106
void _DrawByIndex(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) const override
Draws the skin by index.
Definition SSkin.cpp:52
int GetStates() SCONST OVERRIDE
Gets the number of states in the skin.
Definition SSkin.cpp:38
virtual UINT GetExpandMode() const
Gets the expand mode for the skin.
Definition SSkin.cpp:65
virtual IBitmapS * GetImage() const
Gets the image used by the skin.
Definition SSkin.cpp:94
int GetScale() SCONST OVERRIDE
Gets the scale factor of the skin.
BYTE GetAlpha() SCONST OVERRIDE
Gets the alpha value of the skin.
ISkinObj * Scale(int nScale) OVERRIDE
Scales the skin.
virtual CRect GetPartRect(int nSbCode, int nState, BOOL bVertical) const
Gets the rectangle of a specified part in the original bitmap.
Definition SSkin.cpp:443
void _Scale(ISkinObj *skinObj, int nScale) override
Scales the skin.
Definition SSkin.cpp:516
void _DrawByState(IRenderTarget *pRT, LPCRECT prcDraw, DWORD dwState, BYTE byAlpha) const override
Draws the skin by state.
Definition SSkin.cpp:486
virtual int GetIdealSize() const
Gets the ideal size of the scrollbar.
Definition SSkin.cpp:526
SSkinScrollbar()
Constructor for SSkinScrollbar.
Definition SSkin.cpp:436
A class representing an ASCII string.
Definition sstringw.h:96
const wchar_t * c_str() SCONST
Retrieves a C-style string representation of the string.
int ReplaceChar(wchar_t chOld, wchar_t chNew)
Replaces all occurrences of a character with another character.
Definition sstringw.cpp:636
Bitmap object interface.
Definition SRender-i.h:420
IRenderFactory * GetRenderFactory() SCONST PURE
Obtains the render factory that created this rendering object.
UINT Height() SCONST PURE
Retrieves the height of the bitmap.
SIZE Size() SCONST PURE
Retrieves the size of the bitmap.
UINT Width() SCONST PURE
Retrieves the width of the bitmap.
HRESULT Init(int nWid, int nHei, const LPVOID pBits) PURE
Initializes the bitmap from 32-bit bitmap data.
HRESULT Clone(IBitmapS **ppClone) SCONST PURE
Clones the bitmap.
long Release() PURE
Decrements the reference count for the object.
LPVOID LockPixelBits() PURE
Locks the pixel bits of the bitmap for writing.
void UnlockPixelBits(LPVOID pBuf) PURE
Unlocks the pixel bits of the bitmap.
Pen object interface.
Definition SRender-i.h:307
BOOL CreateBitmap(IBitmapS **ppBitmap) PURE
Creates a bitmap object.
Base class for all renderable objects.
Definition SRender-i.h:145
Interface for rendering target objects.
Definition SRender-i.h:1440
HRESULT DrawRectangle(LPCRECT pRect) PURE
Draw a rectangle outline.
HRESULT FillSolidRoundRect(LPCRECT pRect, POINT pt, COLORREF cr) PURE
Fill a rounded rectangle with a solid color.
HRESULT DrawEllipse(LPCRECT pRect) PURE
Draw an ellipse outline.
HRESULT FillEllipse(LPCRECT pRect) PURE
Fill an ellipse with the current brush.
HRESULT DrawBitmapEx(LPCRECT pRcDest, const IBitmapS *pBitmap, LPCRECT pRcSrc, UINT expendMode, BYTE byAlpha=0xFF) PURE
Draws a bitmap with expansion mode.
HRESULT DrawArc(LPCRECT pRect, float startAngle, float sweepAngle, BOOL useCenter) PURE
Draw an arc.
HRESULT CreateGradientBrush(const GradientItem *pGradients, int nCount, const GradientInfo *info, BYTE byAlpha, TileMode tileMode, IBrushS **ppBrush) PURE
Create a gradient brush.
HRESULT DrawGradientRectEx(LPCRECT pRect, POINT ptRoundCorner, const GradientItem *pGradients, int nCount, const GradientInfo *info, BYTE byAlpha=0xFF) PURE
Draw an extended gradient-filled rectangle.
HRESULT CreateBitmapBrush(IBitmapS *pBmp, TileMode xtm, TileMode ytm, IBrushS **ppBrush) PURE
Create a bitmap brush.
HRESULT SelectObject(IRenderObj *pObj, IRenderObj **pOldObj=NULL) PURE
Selects a new rendering object and optionally retrieves the previous one.
HRESULT CreateSolidColorBrush(COLORREF cr, IBrushS **ppBrush) PURE
Create a solid color brush.
HRESULT CreatePen(int iStyle, COLORREF cr, int cWidth, IPenS **ppPen) PURE
Create a pen object.
HRESULT FillSolidRect(LPCRECT pRect, COLORREF cr) PURE
Fill a rectangle with a solid color.
HRESULT FillRectangle(LPCRECT pRect) PURE
Fill a rectangle with the current brush.
HRESULT DrawBitmap9Patch(LPCRECT pRcDest, const IBitmapS *pBitmap, LPCRECT pRcSrc, LPCRECT pRcSourMargin, UINT expendMode, BYTE byAlpha=0xFF) PURE
Draws a 9-patch bitmap.
HRESULT DrawRoundRect(LPCRECT pRect, POINT pt) PURE
Draw a rounded rectangle outline.
HRESULT FillRoundRect(LPCRECT pRect, POINT pt) PURE
Fill a rounded rectangle with the current brush.
HRESULT DrawGradientRect(LPCRECT pRect, BOOL bVert, POINT ptRoundCorner, const GradientItem *pGradients, int nCount, BYTE byAlpha=0xFF) PURE
Draw a gradient-filled rectangle.
Interface for Skin Objects.
Definition SSkinobj-i.h:29
void DrawByIndex2(IRenderTarget *pRT, LPCRECT rcDraw, int iState, BYTE byAlpha) SCONST PURE
Draws the skin object to the specified render target with a given index and transparency.
void OnInitFinished(IXmlNode *xmlNode) PURE
Handles the completion of attribute initialization.
Interface for XML nodes.
Definition sxml-i.h:128